diff options
Diffstat (limited to 'server/src/matcher/implementation.lua')
-rw-r--r-- | server/src/matcher/implementation.lua | 377 |
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 |