summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/matcher/definition.lua58
-rw-r--r--src/matcher/init.lua5
-rw-r--r--src/parser/grammar.lua13
-rw-r--r--test/definition/init.lua17
-rw-r--r--test/main.lua16
5 files changed, 105 insertions, 4 deletions
diff --git a/src/matcher/definition.lua b/src/matcher/definition.lua
new file mode 100644
index 00000000..fe92ae50
--- /dev/null
+++ b/src/matcher/definition.lua
@@ -0,0 +1,58 @@
+local parser = require 'parser'
+
+local pos
+local defs = {}
+local scopes
+local result
+
+local function getResult(name, p)
+ result = {name, p}
+ for k in pairs(defs) do
+ defs[k] = nil
+ end
+end
+
+local function scopeInit()
+ scopes = {{}}
+end
+
+local function scopeSet(name, p)
+ local scope = scopes[#scopes]
+ scope[name] = p
+end
+
+local function scopeGet(name)
+ local scope = scopes[#scopes]
+ return scope[name]
+end
+
+local function checkDifinition(name, p)
+ if pos < p or pos > p + #name then
+ return
+ end
+ getResult(name, scopeGet(name))
+end
+
+function defs.Name(p, name)
+ checkDifinition(name, p)
+ return name
+end
+
+function defs.LocalVar(p, name)
+ scopeSet(name, p)
+end
+
+return function (buf, pos_)
+ pos = pos_
+ scopeInit()
+ parser.grammar(buf, 'Lua', defs)
+
+ if not result then
+ return nil
+ end
+ local name, start = result[1], result[2]
+ if not start then
+ return nil
+ end
+ return start, start + #name - 1
+end
diff --git a/src/matcher/init.lua b/src/matcher/init.lua
new file mode 100644
index 00000000..8e2a01e2
--- /dev/null
+++ b/src/matcher/init.lua
@@ -0,0 +1,5 @@
+local api = {
+ definition = require 'matcher.definition',
+}
+
+return api
diff --git a/src/parser/grammar.lua b/src/parser/grammar.lua
index eedbd8da..6f2f9d0a 100644
--- a/src/parser/grammar.lua
+++ b/src/parser/grammar.lua
@@ -185,7 +185,7 @@ Float16 <- ('.' X16*)? ([pP] [+-]? [1-9]? [0-9]*)?
]]
grammar 'Name' [[
-Name <- Sp [a-zA-Z_] [a-zA-Z0-9_]*
+Name <- Sp ({} {[a-zA-Z_] [a-zA-Z0-9_]*}) -> Name
]]
grammar 'Exp' [[
@@ -233,16 +233,20 @@ TableField <- NewIndex / NewField / Exp
NewIndex <- BL Exp BR ASSIGN Exp
NewField <- Name ASSIGN Exp
-Function <- FUNCTION PL ArgList? PR
+Function <- FUNCTION FuncName? PL ArgList? PR
(!END Action)*
END
+FuncName <- FuncPrefix (FuncSuffix)*
+FuncPrefix <- Name
+FuncSuffix <- DOT Name
+ / COLON Name
-- 纯占位,修改了 `relabel.lua` 使重复定义不抛错
Action <- !. .
]]
grammar 'Action' [[
-Action <- SEMICOLON / Do / Break / Return / Label / GoTo / If / For / While / Repeat / Set / Call
+Action <- SEMICOLON / Do / Break / Return / Label / GoTo / If / For / While / Repeat / Set / Local / Function / Call
ExpList <- Exp (COMMA Exp)*
@@ -291,6 +295,9 @@ Repeat <- REPEAT
Set <- LOCAL Name ASSIGN Exp
/ Simple ASSIGN Exp
+Local <- LOCAL Function
+ / LOCAL (Sp {} Name) -> LocalVar
+
Call <- Prefix (Suffix)*
]]
diff --git a/test/definition/init.lua b/test/definition/init.lua
new file mode 100644
index 00000000..9ce0b9e7
--- /dev/null
+++ b/test/definition/init.lua
@@ -0,0 +1,17 @@
+local matcher = require 'matcher'
+
+local function test(script)
+ local start = script:find('<!', 1, true) + 2
+ local finish = script:find('!>', 1, true) - 1
+ local pos = script:find('<?', 1, true) + 2
+ local new_script = script:gsub('<[!?]', ' '):gsub('[!?]>', ' ')
+
+ local a, b = matcher.definition(new_script, pos)
+ assert(a == start)
+ assert(b == finish)
+end
+
+test [[
+local <!a!>
+<?a?> = 1
+]]
diff --git a/test/main.lua b/test/main.lua
index d8730f09..e14a9b2b 100644
--- a/test/main.lua
+++ b/test/main.lua
@@ -7,4 +7,18 @@ package.path = package.path .. ';' .. root .. '\\src\\?.lua'
require 'filesystem'
require 'utility'
require 'global_protect'
-print('测试')
+
+local function main()
+ local function test(name)
+ local clock = os.clock()
+ print(('测试[%s]...'):format(name))
+ require(name)
+ print(('测试[%s]用时[%.3f]'):format(name, os.clock() - clock))
+ end
+
+ test 'definition'
+
+ print('测试完成')
+end
+
+main()