summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/matcher/implementation.lua105
-rw-r--r--test/implementation/if.lua28
-rw-r--r--test/implementation/local.lua10
3 files changed, 96 insertions, 47 deletions
diff --git a/src/matcher/implementation.lua b/src/matcher/implementation.lua
index 4431d2ed..bd28ee3a 100644
--- a/src/matcher/implementation.lua
+++ b/src/matcher/implementation.lua
@@ -3,34 +3,31 @@ local parser = require 'parser'
local pos
local defs = {}
local scopes
+local logics
local result
local namePos
local colonPos
-local maybeCount
local DUMMY_TABLE = {}
local function logicPush()
- local scope = scopes[#scopes]
- scope.logicId = (scope.logicId or 0) + 1
-end
-
-local function logicFlush()
- local scope = scopes[#scopes]
- scope.logicId = nil
+ logics[#logics+1] = 0
end
-local function logicGet()
- local scope = scopes[#scopes-1]
- return scope and scope.logicId
+local function logicPop()
+ logics[#logics] = nil
end
-local function maybePush()
- maybeCount = maybeCount + 1
+local function logicAdd()
+ logics[#logics] = logics[#logics] + 1
end
-local function maybePop()
- maybeCount = maybeCount - 1
+local function logicGet()
+ local list = {}
+ for i = 1, #logics do
+ list[i] = logics[i]
+ end
+ return list
end
local function scopeInit()
@@ -49,6 +46,7 @@ local function scopeGet(name)
end
local function scopeSet(obj)
+ obj.logic = logicGet()
local name = obj[1]
local scope = scopes[#scopes]
local list = scope[name]
@@ -68,9 +66,7 @@ local function scopePop()
end
local function globalSet(obj)
- obj.logicId = logicGet()
- obj.scopeId = #scopes
- obj.maybeId = maybeCount
+ obj.logic = logicGet()
local name = obj[1]
for i = #scopes, 1, -1 do
local scope = scopes[i]
@@ -84,6 +80,36 @@ local function globalSet(obj)
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
@@ -93,8 +119,7 @@ local function checkImplementation(name, p)
end
local list = scopeGet(name)
if list then
- local logicId = logicGet()
- local scopeId = #scopes
+ local logic = logicGet()
result = {}
for i = #list, 1, -1 do
local obj = list[i]
@@ -102,15 +127,19 @@ local function checkImplementation(name, p)
if not finish then
finish = start + #name - 1
end
- -- 跳过同层的逻辑分支
- if logicId and scopeId == obj.scopeId and logicId ~= obj.logicId then
+ -- 如果不在同一个分支里,则跳过
+ if not sameLogic(logic, obj.logic) then
goto CONTINUE
end
- result[#result+1] = {start, finish}
- if obj.maybeId and obj.maybeId > maybeCount then
+ -- 如果该分支已经有确定值,则跳过
+ if mustCovered(result, obj.logic) then
goto CONTINUE
end
- do break end
+ result[#result+1] = {start, finish, logic = obj.logic}
+ -- 如果分支长度比自己小,则一定是确信值,不用再继续找了
+ if #obj.logic <= #logic then
+ break
+ end
::CONTINUE::
end
else
@@ -245,7 +274,6 @@ end
function defs.IfDef()
logicPush()
- maybePush()
scopePush()
end
@@ -254,7 +282,7 @@ function defs.If()
end
function defs.ElseIfDef()
- logicPush()
+ logicAdd()
scopePush()
end
@@ -263,7 +291,7 @@ function defs.ElseIf()
end
function defs.ElseDef()
- logicPush()
+ logicAdd()
scopePush()
end
@@ -272,19 +300,18 @@ function defs.Else()
end
function defs.EndIf()
- logicFlush()
- maybePop()
+ logicPop()
end
function defs.LoopDef(name)
- maybePush()
+ logicPush()
scopePush()
scopeSet(name)
end
function defs.Loop()
scopePop()
- maybePop()
+ logicPop()
end
function defs.LoopStart(name, exp)
@@ -300,7 +327,7 @@ function defs.SimpleList(...)
end
function defs.InDef(names)
- maybePush()
+ logicPush()
scopePush()
for _, name in ipairs(names) do
scopeSet(name)
@@ -309,33 +336,33 @@ end
function defs.In()
scopePop()
- maybePop()
+ logicPop()
end
function defs.WhileDef()
- maybePush()
+ logicPush()
scopePush()
end
function defs.While()
scopePop()
- maybePop()
+ logicPop()
end
function defs.RepeatDef()
- maybePush()
+ logicPush()
scopePush()
end
function defs.Until()
scopePop()
- maybePop()
+ logicPop()
end
return function (buf, pos_)
pos = pos_
result = nil
- maybeCount = 0
+ logics = {}
scopeInit()
local suc, err = parser.grammar(buf, 'Lua', defs)
diff --git a/test/implementation/if.lua b/test/implementation/if.lua
index a9ab8b22..0da8be1a 100644
--- a/test/implementation/if.lua
+++ b/test/implementation/if.lua
@@ -69,10 +69,10 @@ end
]]
TEST [[
-x = 1
+x3 = 1
repeat
- <!x!> = 1
-until <?x?> == 1
+ <!x3!> = 1
+until <?x3?> == 1
]]
TEST [[
@@ -82,3 +82,25 @@ repeat
until 1
<?x?> = 1
]]
+
+TEST [[
+<!x!> = 1
+while 1 do
+ x = 1
+ <!x!> = 1
+end
+<?x?> = 1
+]]
+
+TEST [[
+<!x!> = 1
+if 1 then
+ if 1 then
+ x = 1
+ end
+else
+ if 1 then
+ <?x?> = 1
+ end
+end
+]]
diff --git a/test/implementation/local.lua b/test/implementation/local.lua
index 0737443d..7e9b3db0 100644
--- a/test/implementation/local.lua
+++ b/test/implementation/local.lua
@@ -47,11 +47,11 @@ end
]]
TEST [[
-local <!x!>
-if x then
- local x
-elseif <?x?> then
- local x
+local <!x2!>
+if x2 then
+ local x2
+elseif <?x2?> then
+ local x2
end
]]