summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/src/matcher/definition.lua172
-rw-r--r--server/test/definition/init.lua2
-rw-r--r--server/test/definition/table.lua16
3 files changed, 148 insertions, 42 deletions
diff --git a/server/src/matcher/definition.lua b/server/src/matcher/definition.lua
index a744efed..09081cdb 100644
--- a/server/src/matcher/definition.lua
+++ b/server/src/matcher/definition.lua
@@ -13,7 +13,7 @@ local function scopeInit()
scopes = {{}}
end
-local function scopeDef(obj)
+local function scopeLocal(obj)
local scope = scopes[#scopes]
local name = obj[1]
scope[name] = obj
@@ -32,20 +32,64 @@ end
local function scopeSet(obj)
local name = obj[1]
- local scope = scopes[#scopes]
- if not scope[name] then
+ if not scopeGet(name) then
+ local scope = scopes[1]
scope[name] = obj
end
end
-local function globalSet(obj)
+local function scopeGetTable(parent, name)
+ if not parent then
+ return nil
+ end
+ if not parent.child then
+ return nil
+ end
+ if not parent.child[name] then
+ return nil
+ end
+ return parent.child[name]
+end
+
+local function scopeSetTable(parent, obj)
+ if not parent then
+ return
+ end
local name = obj[1]
- if not scopeGet(name) then
- local scope = scopes[1]
- scope[name] = obj
+ if not parent.child then
+ parent.child = {}
+ end
+ if not parent.child[name] then
+ parent.child[name] = obj
end
end
+local function scopeSetSimple(simple)
+ if simple.type ~= 'simple' then
+ return
+ end
+ scopeSet(simple[1])
+ local tbl = scopeGet(simple[1][1])
+ for i = 2, #simple - 1 do
+ tbl = scopeGetTable(tbl, simple[i][1])
+ end
+ scopeSetTable(tbl, simple[#simple])
+end
+
+local function scopeGetSimple(simple, index)
+ if simple.type ~= 'simple' then
+ return
+ end
+ if not index then
+ index = #simple
+ end
+ local tbl = scopeGet(simple[1][1])
+ for i = 2, index do
+ tbl = scopeGetTable(tbl, simple[i][1])
+ end
+ return tbl
+end
+
local function scopePush()
scopes[#scopes+1] = {}
end
@@ -54,11 +98,36 @@ local function scopePop()
scopes[#scopes] = nil
end
-local function checkDifinition(name, p)
+local function checkName(obj)
+ local name = obj[1]
+ local p = obj[2]
if pos < p or pos > p + #name then
return
end
- result = scopeGet(name)
+ result = {
+ type = 'name',
+ object = scopeGet(name),
+ }
+end
+
+local function checkSimple(simple)
+ if simple.type ~= 'simple' then
+ return
+ end
+ for i = 2, #simple do
+ local obj = simple[i]
+ if obj.type == 'name' then
+ local name = obj[1]
+ local p = obj[2]
+ if pos >= p and pos <= p + #name then
+ result = {
+ type = 'simple',
+ table = scopeGetSimple(simple, i-1),
+ name = name,
+ }
+ end
+ end
+ end
end
function defs.NamePos(p)
@@ -66,8 +135,9 @@ function defs.NamePos(p)
end
function defs.Name(str)
- checkDifinition(str, namePos)
- return {str, namePos, type = 'name'}
+ local obj = {str, namePos, type = 'name'}
+ checkName(obj)
+ return obj
end
function defs.DOTSPos(p)
@@ -75,8 +145,9 @@ function defs.DOTSPos(p)
end
function defs.DOTS(str)
- checkDifinition(str, namePos)
- return {str, namePos, type = 'name'}
+ local obj = {str, namePos, type = 'name'}
+ checkName(obj)
+ return obj
end
function defs.COLONPos(p)
@@ -90,28 +161,28 @@ end
function defs.LocalVar(names)
for _, name in ipairs(names) do
- scopeDef(name)
+ scopeLocal(name)
end
end
function defs.LocalSet(names)
for _, name in ipairs(names) do
- scopeDef(name)
+ scopeLocal(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)
+ if simple.type == 'simple' then
+ scopeSetSimple(simple)
end
end
end
function defs.Simple(...)
- return { type = 'simple', ... }
+ local simple = { type = 'simple', ... }
+ checkSimple(simple)
+ return simple
end
function defs.ArgList(...)
@@ -129,47 +200,45 @@ function defs.FuncName(...)
end
function defs.FunctionDef(simple, args)
- if #simple == 1 then
- globalSet(simple[1])
- end
+ scopeSetSimple(simple)
scopePush()
-- 判断隐藏的局部变量self
if #simple > 0 then
local name = simple[#simple]
if name.colon then
- scopeDef {'self', name.colon, name.colon, type = 'name'}
+ scopeLocal {'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]
- scopeDef(name)
+ scopeLocal(name)
end
if arg.type == 'name' then
- scopeDef(arg)
+ scopeLocal(arg)
end
end
end
function defs.FunctionLoc(simple, args)
if #simple == 1 then
- scopeDef(simple[1])
+ scopeLocal(simple[1])
end
scopePush()
-- 判断隐藏的局部变量self
if #simple > 0 then
local name = simple[#simple]
if name.colon then
- scopeDef {'self', name.colon, name.colon, type = 'name'}
+ scopeLocal {'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]
- scopeDef(name)
+ scopeLocal(name)
end
if arg.type == 'name' then
- scopeDef(arg)
+ scopeLocal(arg)
end
end
end
@@ -212,7 +281,7 @@ end
function defs.LoopDef(name)
scopePush()
- scopeDef(name)
+ scopeLocal(name)
end
function defs.Loop()
@@ -234,7 +303,7 @@ end
function defs.InDef(names)
scopePush()
for _, name in ipairs(names) do
- scopeDef(name)
+ scopeLocal(name)
end
end
@@ -258,6 +327,30 @@ function defs.Until()
scopePop()
end
+local function parseResult(callback)
+ local obj
+ if result.type == 'name' then
+ obj = result.object
+ elseif result.type == 'simple' then
+ local tbl = result.table
+ local name = result.name
+ obj = scopeGetTable(tbl, name)
+ end
+
+ if not obj then
+ return
+ end
+
+ local name, start, finish = obj[1], obj[2], obj[3]
+ if not start then
+ return
+ end
+ if not finish then
+ finish = start + #name - 1
+ end
+ callback(start, finish)
+end
+
return function (buf, pos_)
pos = pos_
result = nil
@@ -271,12 +364,15 @@ return function (buf, pos_)
if not result then
return false, 'No word'
end
- local name, start, finish = result[1], result[2], result[3]
- if not start then
+
+ local list = {}
+ parseResult(function (start, finish)
+ list[#list+1] = {start, finish}
+ end)
+
+ if #list == 0 then
return false, 'No match'
end
- if not finish then
- finish = start + #name - 1
- end
- return true, start, finish
+
+ return true, list[1][1], list[1][2]
end
diff --git a/server/test/definition/init.lua b/server/test/definition/init.lua
index 9bd7a1d8..b88cfeef 100644
--- a/server/test/definition/init.lua
+++ b/server/test/definition/init.lua
@@ -18,5 +18,5 @@ require 'definition.set'
require 'definition.local'
require 'definition.arg'
require 'definition.function'
---require 'definition.table'
+require 'definition.table'
require 'definition.bug'
diff --git a/server/test/definition/table.lua b/server/test/definition/table.lua
index 13a3b555..60792141 100644
--- a/server/test/definition/table.lua
+++ b/server/test/definition/table.lua
@@ -1,6 +1,16 @@
TEST [[
-local t = {
- <!x!> = 1,
-}
+local t
+t.<!x!> = 1
t.<?x?> = 1
]]
+
+TEST [[
+t.<!x!> = 1
+t.<?x?> = 1
+]]
+
+TEST [[
+local <!t!>
+t.x = 1
+<?t?>.x = 1
+]]