From f7a5644be02e57eecf3bfaf9143c212cb9bb147a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Fri, 27 Sep 2019 14:04:12 +0800 Subject: =?UTF-8?q?=E6=9B=B4=E6=96=B0parser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server-beta/src/parser/compile.lua | 465 ++++++++++--------------------------- server-beta/src/parser/guide.lua | 101 ++++---- 2 files changed, 162 insertions(+), 404 deletions(-) (limited to 'server-beta/src') diff --git a/server-beta/src/parser/compile.lua b/server-beta/src/parser/compile.lua index b8abad22..28611719 100644 --- a/server-beta/src/parser/compile.lua +++ b/server-beta/src/parser/compile.lua @@ -3,7 +3,7 @@ local type = type _ENV = nil -local pushError, Root, Compile, CompileBlock, Cache, Block, GoToTag, Version, ENVMode, Value +local pushError, Compile, CompileBlock, Cache, Block, GoToTag, Version, ENVMode --[[ -- value 类右字面量创建,在set get call中传递 @@ -17,15 +17,7 @@ Value func -> 函数对象 --]] -local function createValue(data) - local id = #Value+1 - Value[id] = data - data.ref = {} - return id -end - -local function addValue(objID, valueID) - local obj = Root[objID] +local function addValue(obj, value) local vref = obj.vref if not vref then vref = {} @@ -33,28 +25,29 @@ local function addValue(objID, valueID) Cache[vref] = {} end local cache = Cache[vref] - if cache[valueID] then + if cache[value] then return end - cache[valueID] = true - vref[#vref+1] = valueID - local valueRef = Value[valueID].ref - valueRef[#valueRef+1] = objID + cache[value] = true + vref[#vref+1] = value + local valueRef = value.ref + if not valueRef then + valueRef = {} + value.ref = valueRef + end + valueRef[#valueRef+1] = obj end -local function getValue(objID) - local obj = Root[objID] +local function getValue(obj) local vref = obj.vref if vref then return vref end - addValue(objID, createValue {}) + addValue(obj, {}) return obj.vref end -local function mergeValue(objID1, objID2) - local obj1 = Root[objID1] - local obj2 = Root[objID2] +local function mergeValue(obj1, obj2) local vref1 = obj1.vref local vref2 = obj2.vref if not vref2 then @@ -67,134 +60,88 @@ local function mergeValue(objID1, objID2) end local cache = Cache[vref1] for i = 1, #vref2 do - local valueID = vref2[i] - if not cache[valueID] then - cache[valueID] = true - vref1[#vref1+1] = valueID - local valueRef = Value[valueID].ref - valueRef[#valueRef+1] = objID1 + local value = vref2[i] + if not cache[value] then + cache[value] = true + vref1[#vref1+1] = value + local valueRef = value.ref + if not valueRef then + valueRef = {} + value.ref = valueRef + end + valueRef[#valueRef+1] = obj1 end end end -local function setChildValue(objID, keyID, valueID) - if not valueID then +local function setChildValue(obj, key, value) + if not value then return end - local objVref = getValue(objID) - local key = guide.getKeyName(Root[keyID]) - local valueVref = getValue(valueID) + local objVref = getValue(obj) + local keyName = guide.getKeyName(key) + local valueVref = getValue(value) for i = 1, #objVref do - local value = Value[objVref[i]] - if not value.child then - value.child = {} + local v = objVref[i] + if not v.child then + v.child = {} end - value.child[key] = valueVref + v.child[keyName] = valueVref end end -local function addLocalRef(nodeID, objID) - local node = Root[nodeID] - local obj = Root[objID] +local function addLocalRef(node, obj) if not node.ref then node.ref = {} end - node.ref[#node.ref+1] = objID - obj.node = nodeID + node.ref[#node.ref+1] = obj + obj.node = node end local vmMap = { - ['nil'] = function (obj) - Root[#Root+1] = obj - return #Root - end, - ['boolean'] = function (obj) - Root[#Root+1] = obj - return #Root - end, - ['string'] = function (obj) - Root[#Root+1] = obj - return #Root - end, - ['number'] = function (obj) - Root[#Root+1] = obj - return #Root - end, - ['...'] = function (obj) - Root[#Root+1] = obj - return #Root - end, ['getname'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local loc = guide.getLocal(Root, obj, obj[1], obj.start) + local loc = guide.getLocal(obj, obj[1], obj.start) if loc then obj.type = 'getlocal' - obj.loc = Cache[loc] + obj.loc = loc if not loc.ref then loc.ref = {} end - loc.ref[#loc.ref+1] = id + loc.ref[#loc.ref+1] = obj else obj.type = 'getglobal' if ENVMode == '_ENV' then - local node, nodeID = guide.getLocal(Root, obj, '_ENV', obj.start) + local node = guide.getLocal(obj, '_ENV', obj.start) if node then - addLocalRef(nodeID, id) + addLocalRef(node, obj) end end end - return id + return obj end, ['getfield'] = function (obj) - local node = obj.node - Root[#Root+1] = obj - local id = #Root - obj.node = Compile(node, id) - return id + Compile(obj.node, obj) end, ['call'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local node = obj.node - local args = obj.args - if node then - obj.node = Compile(node, id) - end - if args then - obj.args = Compile(args, id) - end - return id + Compile(obj.node, obj) + Compile(obj.args, obj) end, ['callargs'] = function (obj) - Root[#Root+1] = obj - local id = #Root for i = 1, #obj do - local arg = obj[i] - obj[i] = Compile(arg, id) + Compile(obj[i], obj) end - return id end, ['binary'] = function (obj) - local e1 = obj[1] - local e2 = obj[2] - Root[#Root+1] = obj - local id = #Root - obj[1] = Compile(e1, id) - obj[2] = Compile(e2, id) - return id + Compile(obj[1], obj) + Compile( obj[2], obj) end, ['unary'] = function (obj) - local e = obj[1] - Root[#Root+1] = obj - local id = #Root - obj[1] = Compile(e, id) - return id + Compile(obj[1], obj) end, ['varargs'] = function (obj) - local func = guide.getParentFunction(Root, obj) + local func = guide.getParentFunction(obj) if func then - local index = guide.getFunctionVarArgs(Root, func) + local index = guide.getFunctionVarArgs(func) if not index then pushError { type = 'UNEXPECT_DOTS', @@ -203,244 +150,133 @@ local vmMap = { } end end - Root[#Root+1] = obj - return #Root end, ['paren'] = function (obj) - local exp = obj.exp - Root[#Root+1] = obj - local id = #Root - obj.exp = Compile(exp, id) - return id + Compile(obj.exp, obj) end, ['getindex'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local node = obj.node - obj.node = Compile(node, id) - local index = obj.index - if index then - obj.index = Compile(index, id) - end - return id + Compile(obj.node, obj) + Compile(obj.index, obj) end, ['setindex'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local node = obj.node - obj.node = Compile(node, id) - local index = obj.index - if index then - obj.index = Compile(index, id) - end - local value = obj.value - if value then - obj.value = Compile(value, id) - end - return id + Compile(obj.node, obj) + Compile(obj.index, obj) + Compile(obj.value, obj) end, ['getmethod'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local node = obj.node - local method = obj.method - obj.node = Compile(node, id) - if method then - obj.method = Compile(method, id) - end - return id + Compile(obj.node, obj) + Compile(obj.method, obj) end, ['setmethod'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local node = obj.node - local method = obj.method + Compile(obj.node, obj) + Compile(obj.method, obj) local value = obj.value - obj.node = Compile(node, id) - if method then - obj.method = Compile(method, id) - end value.localself = { type = 'local', start = 0, finish = 0, - method = id, + method = obj, effect = obj.finish, [1] = 'self', } - obj.value = Compile(value, id) - return id - end, - ['method'] = function (obj) - Root[#Root+1] = obj - return #Root + Compile(value, obj) end, ['function'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root if obj.localself then - Compile(obj.localself, id) + Compile(obj.localself, obj) obj.localself = nil end - local args = obj.args - if args then - obj.args = Compile(args, id) - end + Compile(obj.args, obj) for i = 1, #obj do - local act = obj[i] - obj[i] = Compile(act, id) + Compile(obj[i], obj) end Block = lastBlock - return id end, ['funcargs'] = function (obj) - Root[#Root+1] = obj - local id = #Root for i = 1, #obj do - local arg = obj[i] - obj[i] = Compile(arg, id) + Compile(obj[i], obj) end - return id end, ['table'] = function (obj) - Root[#Root+1] = obj - local id = #Root for i = 1, #obj do - local v = obj[i] - obj[i] = Compile(v, id) + Compile(obj[i], obj) end - return id end, ['tablefield'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local value = obj.value - if value then - obj.value = Compile(value, id) - end - return id + Compile(obj.value, obj) end, ['tableindex'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local index = obj.index - local value = obj.value - obj.index = Compile(index, id) - obj.value = Compile(value, id) - return id + Compile(obj.index, obj) + Compile(obj.value, obj) end, ['index'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local index = obj.index - obj.index = Compile(index, id) - return id + Compile(obj.index, obj) end, ['select'] = function (obj) - Root[#Root+1] = obj - local id = #Root local vararg = obj.vararg - if not Cache[vararg] then - obj.vararg = Compile(vararg, id) - Cache[vararg] = obj.vararg - else - obj.vararg = Cache[vararg] + if vararg.parent then if not vararg.extParent then vararg.extParent = {} end - vararg.extParent[#vararg.extParent+1] = id + vararg.extParent[#vararg.extParent+1] = obj + else + Compile(vararg, obj) end - return id end, ['setname'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local value = obj.value - if value then - obj.value = Compile(value, id) - end - local loc = guide.getLocal(Root, obj, obj[1], obj.start) + Compile(obj.value, obj) + local loc = guide.getLocal(obj, obj[1], obj.start) if loc then obj.type = 'setlocal' - obj.loc = Cache[loc] + obj.loc = loc if not loc.ref then loc.ref = {} end - loc.ref[#loc.ref+1] = id + loc.ref[#loc.ref+1] = obj else obj.type = 'setglobal' if ENVMode == '_ENV' then - local node, nodeID = guide.getLocal(Root, obj, '_ENV', obj.start) + local node = guide.getLocal(obj, '_ENV', obj.start) if node then - addLocalRef(nodeID, id) - setChildValue(nodeID, id, obj.value) + addLocalRef(node, obj) + setChildValue(node, obj, obj.value) end end end - return id end, ['local'] = function (obj) - Root[#Root+1] = obj - local id = #Root local attrs = obj.attrs if attrs then for i = 1, #attrs do - local attr = attrs[i] - attrs[i] = Compile(attr, id) + Compile(attrs[i], obj) end end if Block then if not Block.locals then Block.locals = {} end - Block.locals[#Block.locals+1] = id + Block.locals[#Block.locals+1] = obj end if obj.localfunction then obj.localfunction = nil - Cache[obj] = id - local value = obj.value - if value then - obj.value = Compile(value, id) - end - else - local value = obj.value - if value then - obj.value = Compile(value, id) - end - Cache[obj] = id end - return id - end, - ['localattr'] = function (obj) - Root[#Root+1] = obj - return #Root + Compile(obj.value, obj) end, ['setfield'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local node = obj.node - local value = obj.value - obj.node = Compile(node, id) - obj.value = Compile(value, id) - return id + Compile(obj.node, obj) + Compile(obj.value, obj) end, ['do'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root - CompileBlock(obj, id) + CompileBlock(obj, obj) Block = lastBlock - return id end, ['return'] = function (obj) - Root[#Root+1] = obj - local id = #Root for i = 1, #obj do - local act = obj[i] - obj[i] = Compile(act, id) + Compile(obj[i], obj) end if Block and Block[#Block] ~= obj then pushError { @@ -449,18 +285,15 @@ local vmMap = { finish = obj.finish, } end - return id end, ['label'] = function (obj) - Root[#Root+1] = obj - local id = #Root - local block = guide.getBlock(Root, obj) + local block = guide.getBlock(obj) if block then if not block.labels then block.labels = {} end local name = obj[1] - local label = guide.getLabel(Root, block, name) + local label = guide.getLabel(block, name) if label then pushError { type = 'REDEFINED_LABEL', @@ -474,146 +307,97 @@ local vmMap = { } } end - block.labels[name] = id + block.labels[name] = obj end - return id end, ['goto'] = function (obj) - Root[#Root+1] = obj - local id = #Root GoToTag[#GoToTag+1] = obj - return id end, ['if'] = function (obj) - Root[#Root+1] = obj - local id = #Root for i = 1, #obj do - local block = obj[i] - obj[i] = Compile(block, id) + Compile(obj[i], obj) end - return id end, ['ifblock'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root - local filter = obj.filter - obj.filter = Compile(filter, id) - CompileBlock(obj, id) + Compile(obj.filter, obj) + CompileBlock(obj, obj) Block = lastBlock - return id end, ['elseifblock'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root - local filter = obj.filter - if filter then - obj.filter = Compile(filter, id) - end - CompileBlock(obj, id) + Compile(obj.filter, obj) + CompileBlock(obj, obj) Block = lastBlock - return id end, ['elseblock'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root - CompileBlock(obj, id) + CompileBlock(obj, obj) Block = lastBlock - return id end, ['loop'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root - local loc = obj.loc - local max = obj.max - local step = obj.step - if loc then - obj.loc = Compile(loc, id) - end - if max then - obj.max = Compile(max, id) - end - if step then - obj.step = Compile(step, id) - end - CompileBlock(obj, id) + Compile(obj.loc, obj) + Compile(obj.max, obj) + Compile(obj.step, obj) + CompileBlock(obj, obj) Block = lastBlock - return id end, ['in'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root local keys = obj.keys for i = 1, #keys do - local loc = keys[i] - keys[i] = Compile(loc, id) + Compile(keys[i], obj) end - CompileBlock(obj, id) + CompileBlock(obj, obj) Block = lastBlock - return id end, ['while'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root - local filter = obj.filter - obj.filter = Compile(filter, id) - CompileBlock(obj, id) + Compile(obj.filter, obj) + CompileBlock(obj, obj) Block = lastBlock - return id end, ['repeat'] = function (obj) local lastBlock = Block Block = obj - Root[#Root+1] = obj - local id = #Root - CompileBlock(obj, id) - local filter = obj.filter - obj.filter = Compile(filter, id) + CompileBlock(obj, obj) + Compile(obj.filter, obj) Block = lastBlock - return id end, ['break'] = function (obj) - if not guide.getBreakBlock(Root, obj) then + if not guide.getBreakBlock(obj) then pushError { type = 'BREAK_OUTSIDE', start = obj.start, finish = obj.finish, } end - Root[#Root+1] = obj - return #Root end, ['main'] = function (obj) Block = obj - Root[#Root+1] = obj - local id = #Root if ENVMode == '_ENV' then - local envID = Compile({ + local env = { type = 'local', start = 0, finish = 0, effect = 0, [1] = '_ENV', - }, id) - addValue(envID, createValue { + } + Compile(env, obj) + addValue(env, { type = 'table', tag = '_ENV', }) end - CompileBlock(obj, id) + CompileBlock(obj, obj) Block = nil - return id end, } @@ -623,7 +407,7 @@ function CompileBlock(obj, parent) local f = vmMap[act.type] if f then act.parent = parent - obj[i] = f(act) + f(act) end end end @@ -634,15 +418,15 @@ function Compile(obj, parent) end local f = vmMap[obj.type] if not f then - return nil + return end obj.parent = parent - return f(obj) + f(obj) end local function compileGoTo(obj) local name = obj[1] - local label = guide.getLabel(Root, obj, name) + local label = guide.getLabel(obj, name) if not label then pushError { type = 'NO_VISIBLE_LABEL', @@ -662,14 +446,14 @@ local function compileGoTo(obj) return end - local block = guide.getBlock(Root, obj) + local block = guide.getBlock(obj) local locals = block and block.locals if not locals then return end for i = 1, #locals do - local loc = Root[locals[i]] + local loc = locals[i] -- 检查局部变量声明位置为 goto 与 label 之间 if loc.start < obj.start or loc.finish > label.finish then goto CONTINUE @@ -680,7 +464,7 @@ local function compileGoTo(obj) goto CONTINUE end for j = 1, #refs do - local ref = Root[refs[j]] + local ref = refs[j] if ref.finish > label.finish then pushError { type = 'JUMP_LOCAL_SCOPE', @@ -719,7 +503,6 @@ return function (self, lua, mode, version) return nil, err end pushError = state.pushError - Root = state.root Version = version if version == 'Lua 5.1' or version == 'LuaJIT' then ENVMode = 'fenv' @@ -728,14 +511,10 @@ return function (self, lua, mode, version) end Cache = {} GoToTag = {} - Value = {} if type(state.ast) == 'table' then Compile(state.ast) end PostCompile() - state.ast = nil - state.value = Value Cache = nil - Value = nil return state end diff --git a/server-beta/src/parser/guide.lua b/server-beta/src/parser/guide.lua index 747d8d4f..a3cc4056 100644 --- a/server-beta/src/parser/guide.lua +++ b/server-beta/src/parser/guide.lua @@ -26,9 +26,9 @@ local breakBlockTypes = { } --- 寻找所在函数 -function m.getParentFunction(root, obj) +function m.getParentFunction(obj) for _ = 1, 1000 do - obj = root[obj.parent] + obj = obj.parent if not obj then break end @@ -41,7 +41,7 @@ function m.getParentFunction(root, obj) end --- 寻找所在区块 -function m.getBlock(root, obj) +function m.getBlock(obj) for _ = 1, 1000 do if not obj then return nil @@ -50,15 +50,15 @@ function m.getBlock(root, obj) if blockTypes[tp] then return obj end - obj = root[obj.parent] + obj = obj.parent end error('guide.getBlock overstack') end --- 寻找所在父区块 -function m.getParentBlock(root, obj) +function m.getParentBlock(obj) for _ = 1, 1000 do - obj = root[obj.parent] + obj = obj.parent if not obj then return nil end @@ -71,9 +71,9 @@ function m.getParentBlock(root, obj) end --- 寻找所在可break的父区块 -function m.getBreakBlock(root, obj) +function m.getBreakBlock(obj) for _ = 1, 1000 do - obj = root[obj.parent] + obj = obj.parent if not obj then return nil end @@ -92,19 +92,19 @@ end --- 如果函数是主函数,则返回`0, nil`。 ---@return table ---@return integer -function m.getFunctionVarArgs(root, func) +function m.getFunctionVarArgs(func) if func.type == 'main' then return 0, nil end if func.type ~= 'function' then return nil, nil end - local args = root[func.args] + local args = func.args if not args then return nil, nil end for i = 1, #args do - local arg = root[args[i]] + local arg = args[i] if arg.type == '...' then return i, arg end @@ -113,12 +113,11 @@ function m.getFunctionVarArgs(root, func) end --- 获取指定区块中可见的局部变量 ----@param root table ---@param block table ---@param name string {comment = '变量名'} ---@param pos integer {comment = '可见位置'} -function m.getLocal(root, block, name, pos) - block = m.getBlock(root, block) +function m.getLocal(block, name, pos) + block = m.getBlock(block) for _ = 1, 1000 do if not block then return nil @@ -129,32 +128,30 @@ function m.getLocal(root, block, name, pos) goto CONTINUE end for i = 1, #locals do - local locID = locals[i] - local loc = root[locID] + local loc = locals[i] if loc.effect > pos then break end if loc[1] == name then - if not res or root[res].effect < loc.effect then - res = locID + if not res or res.effect < loc.effect then + res = loc end end end if res then - return root[res], res + return res, res end ::CONTINUE:: - block = m.getParentBlock(root, block) + block = m.getParentBlock(block) end error('guide.getLocal overstack') end --- 获取指定区块中可见的标签 ----@param root table ---@param block table ---@param name string {comment = '标签名'} -function m.getLabel(root, block, name) - block = m.getBlock(root, block) +function m.getLabel(block, name) + block = m.getBlock(block) for _ = 1, 1000 do if not block then return nil @@ -163,13 +160,13 @@ function m.getLabel(root, block, name) if labels then local label = labels[name] if label then - return root[label] + return label end end if block.type == 'function' then return nil end - block = m.getParentBlock(root, block) + block = m.getParentBlock(block) end error('guide.getLocal overstack') end @@ -183,20 +180,20 @@ function m.isContain(source, offset) end --- 遍历所有包含offset的source -function m.eachSource(root, offset, callback) - for i = 1, #root do - local source = root[i] - if m.isContain(source, offset) then - local res = callback(source) - if res ~= nil then - return res - end - end - end +function m.eachSource(offset, callback) + --for i = 1, #root do + -- local source = root[i] + -- if m.isContain(source, offset) then + -- local res = callback(source) + -- if res ~= nil then + -- return res + -- end + -- end + --end end --- 遍历所有某种类型的source -function m.eachSourceOf(root, types, callback) +function m.eachSourceOf(types, callback) if type(types) == 'string' then types = {[types] = callback} elseif type(types) == 'table' then @@ -206,13 +203,13 @@ function m.eachSourceOf(root, types, callback) else return end - for i = 1, #root do - local source = root[i] - local f = types[source.type] - if f then - f(source) - end - end + --for i = 1, #root do + -- local source = root[i] + -- local f = types[source.type] + -- if f then + -- f(source) + -- end + --end end --- 获取偏移对应的坐标(row从0开始,col为光标位置) @@ -295,22 +292,4 @@ function m.getKeyName(obj) end end -function m.eachField(value, obj, key, callback) - local vref = obj.vref - if not vref then - return - end - for x = 1, #vref do - local vID = vref[x] - local v = value[vID] - local child = v.child - if child then - local refs = child[key] - if refs then - - end - end - end -end - return m -- cgit v1.2.3