summaryrefslogtreecommitdiff
path: root/src/matcher
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2018-11-20 12:09:06 +0800
committer最萌小汐 <sumneko@hotmail.com>2018-11-20 12:09:06 +0800
commitafea7d6f14e7534a71591447ccc5b1110836ed8c (patch)
tree65c06a356922fb8f25f7bd92cad5e04483b71b69 /src/matcher
parent2f75dac6aba312260abb74afce64b1527d2ecea0 (diff)
downloadlua-language-server-afea7d6f14e7534a71591447ccc5b1110836ed8c.zip
支持转到实现
Diffstat (limited to 'src/matcher')
-rw-r--r--src/matcher/definition.lua14
-rw-r--r--src/matcher/implementation.lua280
-rw-r--r--src/matcher/init.lua3
3 files changed, 293 insertions, 4 deletions
diff --git a/src/matcher/definition.lua b/src/matcher/definition.lua
index 04d01135..a744efed 100644
--- a/src/matcher/definition.lua
+++ b/src/matcher/definition.lua
@@ -32,8 +32,16 @@ end
local function scopeSet(obj)
local name = obj[1]
+ local scope = scopes[#scopes]
+ if not scope[name] then
+ scope[name] = obj
+ end
+end
+
+local function globalSet(obj)
+ local name = obj[1]
if not scopeGet(name) then
- local scope = scopes[#scopes]
+ local scope = scopes[1]
scope[name] = obj
end
end
@@ -97,7 +105,7 @@ function defs.Set(simples)
if simple.type == 'simple' and #simple == 1 then
local obj = simple[1]
local name = obj[1]
- scopeSet(obj)
+ globalSet(obj)
end
end
end
@@ -122,7 +130,7 @@ end
function defs.FunctionDef(simple, args)
if #simple == 1 then
- scopeSet(simple[1])
+ globalSet(simple[1])
end
scopePush()
-- 判断隐藏的局部变量self
diff --git a/src/matcher/implementation.lua b/src/matcher/implementation.lua
new file mode 100644
index 00000000..e245ef90
--- /dev/null
+++ b/src/matcher/implementation.lua
@@ -0,0 +1,280 @@
+local parser = require 'parser'
+
+local pos
+local defs = {}
+local scopes
+local result
+local namePos
+local colonPos
+
+local DUMMY_TABLE = {}
+
+local function scopeInit()
+ scopes = {{}}
+end
+
+local function scopeGet(name)
+ for i = #scopes, 1, -1 do
+ local scope = scopes[i]
+ local obj = scope[name]
+ if obj then
+ return obj
+ end
+ end
+ return nil
+end
+
+local function scopeSet(obj)
+ local name = obj[1]
+ local scope = scopes[#scopes]
+ scope[name] = obj
+end
+
+local function globalSet(obj)
+ local name = obj[1]
+ for i = #scopes, 1, -1 do
+ local scope = scopes[i]
+ local old = scope[name]
+ if old then
+ scope[name] = obj
+ return
+ end
+ end
+ local scope = scopes[1]
+ scope[name] = obj
+end
+
+local function scopePush()
+ scopes[#scopes+1] = {}
+end
+
+local function scopePop()
+ scopes[#scopes] = nil
+end
+
+local function checkImplementation(name, p)
+ if pos < p or pos > p + #name then
+ return
+ end
+ result = scopeGet(name)
+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()
+ scopePush()
+end
+
+function defs.If()
+ scopePop()
+end
+
+function defs.ElseIfDef()
+ scopePush()
+end
+
+function defs.ElseIf()
+ scopePop()
+end
+
+function defs.ElseDef()
+ scopePush()
+end
+
+function defs.Else()
+ scopePop()
+end
+
+function defs.LoopDef(name)
+ scopePush()
+ scopeSet(name)
+end
+
+function defs.Loop()
+ scopePop()
+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)
+ scopePush()
+ for _, name in ipairs(names) do
+ scopeSet(name)
+ end
+end
+
+function defs.In()
+ scopePop()
+end
+
+function defs.WhileDef()
+ scopePush()
+end
+
+function defs.While()
+ scopePop()
+end
+
+function defs.RepeatDef()
+ scopePush()
+end
+
+function defs.Until()
+ scopePop()
+end
+
+return function (buf, pos_)
+ pos = pos_
+ result = nil
+ 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
+ local name, start, finish = result[1], result[2], result[3]
+ if not start then
+ return false, 'No match'
+ end
+ if not finish then
+ finish = start + #name - 1
+ end
+ return true, start, finish
+end
diff --git a/src/matcher/init.lua b/src/matcher/init.lua
index 8e2a01e2..c570b342 100644
--- a/src/matcher/init.lua
+++ b/src/matcher/init.lua
@@ -1,5 +1,6 @@
local api = {
- definition = require 'matcher.definition',
+ definition = require 'matcher.definition',
+ implementation = require 'matcher.implementation',
}
return api