summaryrefslogtreecommitdiff
path: root/server/src/matcher/implementation.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/matcher/implementation.lua')
-rw-r--r--server/src/matcher/implementation.lua377
1 files changed, 377 insertions, 0 deletions
diff --git a/server/src/matcher/implementation.lua b/server/src/matcher/implementation.lua
new file mode 100644
index 00000000..bd28ee3a
--- /dev/null
+++ b/server/src/matcher/implementation.lua
@@ -0,0 +1,377 @@
+local parser = require 'parser'
+
+local pos
+local defs = {}
+local scopes
+local logics
+local result
+local namePos
+local colonPos
+
+local DUMMY_TABLE = {}
+
+local function logicPush()
+ logics[#logics+1] = 0
+end
+
+local function logicPop()
+ logics[#logics] = nil
+end
+
+local function logicAdd()
+ logics[#logics] = logics[#logics] + 1
+end
+
+local function logicGet()
+ local list = {}
+ for i = 1, #logics do
+ list[i] = logics[i]
+ end
+ return list
+end
+
+local function scopeInit()
+ scopes = {{}}
+end
+
+local function scopeGet(name)
+ for i = #scopes, 1, -1 do
+ local scope = scopes[i]
+ local list = scope[name]
+ if list then
+ return list
+ end
+ end
+ return nil
+end
+
+local function scopeSet(obj)
+ obj.logic = logicGet()
+ local name = obj[1]
+ local scope = scopes[#scopes]
+ local list = scope[name]
+ if list then
+ list[#list+1] = obj
+ else
+ scope[name] = {obj}
+ end
+end
+
+local function scopePush()
+ scopes[#scopes+1] = {}
+end
+
+local function scopePop()
+ scopes[#scopes] = nil
+end
+
+local function globalSet(obj)
+ obj.logic = logicGet()
+ local name = obj[1]
+ for i = #scopes, 1, -1 do
+ local scope = scopes[i]
+ local list = scope[name]
+ if list then
+ list[#list+1] = obj
+ return
+ end
+ end
+ local scope = scopes[1]
+ scope[name] = {obj}
+end
+
+local function sameLogic(cur, target)
+ for i = 1, #cur do
+ if target[i] == nil then
+ break
+ end
+ if cur[i] ~= target[i] then
+ return false
+ end
+ end
+ return true
+end
+
+local function mustCovered(results, target)
+ for _, result in ipairs(results) do
+ local logic = result.logic
+ if #logic == #target then
+ local isSame = true
+ for i = 1, #logic do
+ if logic[i] ~= target[i] then
+ isSame = false
+ end
+ end
+ if isSame then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+local function checkImplementation(name, p)
+ if result ~= nil then
+ return
+ end
+ if pos < p or pos > p + #name then
+ return
+ end
+ local list = scopeGet(name)
+ if list then
+ local logic = logicGet()
+ result = {}
+ for i = #list, 1, -1 do
+ local obj = list[i]
+ local name, start, finish = obj[1], obj[2], obj[3]
+ if not finish then
+ finish = start + #name - 1
+ end
+ -- 如果不在同一个分支里,则跳过
+ if not sameLogic(logic, obj.logic) then
+ goto CONTINUE
+ end
+ -- 如果该分支已经有确定值,则跳过
+ if mustCovered(result, obj.logic) then
+ goto CONTINUE
+ end
+ result[#result+1] = {start, finish, logic = obj.logic}
+ -- 如果分支长度比自己小,则一定是确信值,不用再继续找了
+ if #obj.logic <= #logic then
+ break
+ end
+ ::CONTINUE::
+ end
+ else
+ result = false
+ end
+end
+
+function defs.NamePos(p)
+ namePos = p
+end
+
+function defs.Name(str)
+ checkImplementation(str, namePos)
+ return {str, namePos, type = 'name'}
+end
+
+function defs.DOTSPos(p)
+ namePos = p
+end
+
+function defs.DOTS(str)
+ checkImplementation(str, namePos)
+ return {str, namePos, type = 'name'}
+end
+
+function defs.COLONPos(p)
+ colonPos = p
+end
+
+function defs.ColonName(name)
+ name.colon = colonPos
+ return name
+end
+
+function defs.LocalVar(names)
+ for _, name in ipairs(names) do
+ scopeSet(name)
+ end
+end
+
+function defs.LocalSet(names)
+ for _, name in ipairs(names) do
+ scopeSet(name)
+ end
+end
+
+function defs.Set(simples)
+ for _, simple in ipairs(simples) do
+ if simple.type == 'simple' and #simple == 1 then
+ local obj = simple[1]
+ local name = obj[1]
+ globalSet(obj)
+ end
+ end
+end
+
+function defs.Simple(...)
+ return { type = 'simple', ... }
+end
+
+function defs.ArgList(...)
+ if ... == '' then
+ return DUMMY_TABLE
+ end
+ return { type = 'list', ... }
+end
+
+function defs.FuncName(...)
+ if ... == '' then
+ return DUMMY_TABLE
+ end
+ return { type = 'simple', ... }
+end
+
+function defs.FunctionDef(simple, args)
+ if #simple == 1 then
+ globalSet(simple[1])
+ end
+ scopePush()
+ -- 判断隐藏的局部变量self
+ if #simple > 0 then
+ local name = simple[#simple]
+ if name.colon then
+ scopeSet {'self', name.colon, name.colon, type = 'name'}
+ end
+ end
+ for _, arg in ipairs(args) do
+ if arg.type == 'simple' and #arg == 1 then
+ local name = arg[1]
+ scopeSet(name)
+ end
+ if arg.type == 'name' then
+ scopeSet(arg)
+ end
+ end
+end
+
+function defs.FunctionLoc(simple, args)
+ if #simple == 1 then
+ scopeSet(simple[1])
+ end
+ scopePush()
+ -- 判断隐藏的局部变量self
+ if #simple > 0 then
+ local name = simple[#simple]
+ if name.colon then
+ scopeSet {'self', name.colon, name.colon, type = 'name'}
+ end
+ end
+ for _, arg in ipairs(args) do
+ if arg.type == 'simple' and #arg == 1 then
+ local name = arg[1]
+ scopeSet(name)
+ end
+ if arg.type == 'name' then
+ scopeSet(arg)
+ end
+ end
+end
+
+function defs.Function()
+ scopePop()
+end
+
+function defs.DoDef()
+ scopePush()
+end
+
+function defs.Do()
+ scopePop()
+end
+
+function defs.IfDef()
+ logicPush()
+ scopePush()
+end
+
+function defs.If()
+ scopePop()
+end
+
+function defs.ElseIfDef()
+ logicAdd()
+ scopePush()
+end
+
+function defs.ElseIf()
+ scopePop()
+end
+
+function defs.ElseDef()
+ logicAdd()
+ scopePush()
+end
+
+function defs.Else()
+ scopePop()
+end
+
+function defs.EndIf()
+ logicPop()
+end
+
+function defs.LoopDef(name)
+ logicPush()
+ scopePush()
+ scopeSet(name)
+end
+
+function defs.Loop()
+ scopePop()
+ logicPop()
+end
+
+function defs.LoopStart(name, exp)
+ return name
+end
+
+function defs.NameList(...)
+ return { type = 'list', ... }
+end
+
+function defs.SimpleList(...)
+ return { type = 'list', ... }
+end
+
+function defs.InDef(names)
+ logicPush()
+ scopePush()
+ for _, name in ipairs(names) do
+ scopeSet(name)
+ end
+end
+
+function defs.In()
+ scopePop()
+ logicPop()
+end
+
+function defs.WhileDef()
+ logicPush()
+ scopePush()
+end
+
+function defs.While()
+ scopePop()
+ logicPop()
+end
+
+function defs.RepeatDef()
+ logicPush()
+ scopePush()
+end
+
+function defs.Until()
+ scopePop()
+ logicPop()
+end
+
+return function (buf, pos_)
+ pos = pos_
+ result = nil
+ logics = {}
+ scopeInit()
+
+ local suc, err = parser.grammar(buf, 'Lua', defs)
+ if not suc then
+ return false, '语法错误', err
+ end
+
+ if not result then
+ return false, 'No word'
+ end
+ return true, result
+end