diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-11-22 23:26:32 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-11-22 23:26:32 +0800 |
commit | d0ff66c9abe9d6abbca12fd811e0c3cb69c1033a (patch) | |
tree | bb34518d70b85de7656dbdbe958dfa221a3ff3b3 /server-beta/src/parser | |
parent | 0a2c2ad15e1ec359171fb0dd4c72e57c5b66e9ba (diff) | |
download | lua-language-server-d0ff66c9abe9d6abbca12fd811e0c3cb69c1033a.zip |
整理一下目录结构
Diffstat (limited to 'server-beta/src/parser')
-rw-r--r-- | server-beta/src/parser/ast.lua | 1738 | ||||
-rw-r--r-- | server-beta/src/parser/calcline.lua | 93 | ||||
-rw-r--r-- | server-beta/src/parser/compile.lua | 549 | ||||
-rw-r--r-- | server-beta/src/parser/emmy.lua | 321 | ||||
-rw-r--r-- | server-beta/src/parser/grammar.lua | 537 | ||||
-rw-r--r-- | server-beta/src/parser/guide.lua | 621 | ||||
-rw-r--r-- | server-beta/src/parser/init.lua | 11 | ||||
-rw-r--r-- | server-beta/src/parser/lines.lua | 46 | ||||
-rw-r--r-- | server-beta/src/parser/parse.lua | 45 | ||||
-rw-r--r-- | server-beta/src/parser/relabel.lua | 361 | ||||
-rw-r--r-- | server-beta/src/parser/split.lua | 9 |
11 files changed, 0 insertions, 4331 deletions
diff --git a/server-beta/src/parser/ast.lua b/server-beta/src/parser/ast.lua deleted file mode 100644 index dfd7656d..00000000 --- a/server-beta/src/parser/ast.lua +++ /dev/null @@ -1,1738 +0,0 @@ -local emmy = require 'parser.emmy' - -local tonumber = tonumber -local stringChar = string.char -local utf8Char = utf8.char -local tableUnpack = table.unpack -local mathType = math.type -local tableRemove = table.remove -local pairs = pairs -local tableSort = table.sort - -_ENV = nil - -local State -local PushError -local PushDiag - --- goto 单独处理 -local RESERVED = { - ['and'] = true, - ['break'] = true, - ['do'] = true, - ['else'] = true, - ['elseif'] = true, - ['end'] = true, - ['false'] = true, - ['for'] = true, - ['function'] = true, - ['if'] = true, - ['in'] = true, - ['local'] = true, - ['nil'] = true, - ['not'] = true, - ['or'] = true, - ['repeat'] = true, - ['return'] = true, - ['then'] = true, - ['true'] = true, - ['until'] = true, - ['while'] = true, -} - -local VersionOp = { - ['&'] = {'Lua 5.3', 'Lua 5.4'}, - ['~'] = {'Lua 5.3', 'Lua 5.4'}, - ['|'] = {'Lua 5.3', 'Lua 5.4'}, - ['<<'] = {'Lua 5.3', 'Lua 5.4'}, - ['>>'] = {'Lua 5.3', 'Lua 5.4'}, - ['//'] = {'Lua 5.3', 'Lua 5.4'}, -} - -local function checkOpVersion(op) - local versions = VersionOp[op.type] - if not versions then - return - end - for i = 1, #versions do - if versions[i] == State.version then - return - end - end - PushError { - type = 'UNSUPPORT_SYMBOL', - start = op.start, - finish = op.finish, - version = versions, - info = { - version = State.version, - } - } -end - -local function checkMissEnd(start) - if not State.MissEndErr then - return - end - local err = State.MissEndErr - State.MissEndErr = nil - local _, finish = State.lua:find('[%w_]+', start) - if not finish then - return - end - err.info.related = { - { - start = start, - finish = finish, - } - } - PushError { - type = 'MISS_END', - start = start, - finish = finish, - } -end - -local function getSelect(vararg, index) - return { - type = 'select', - start = vararg.start, - finish = vararg.finish, - vararg = vararg, - index = index, - } -end - -local function getValue(values, i) - if not values then - return nil, nil - end - local value = values[i] - if not value then - local last = values[#values] - if not last then - return nil, nil - end - if last.type == 'call' or last.type == 'varargs' then - return getSelect(last, i - #values + 1) - end - return nil, nil - end - if value.type == 'call' or value.type == 'varargs' then - value = getSelect(value, 1) - end - return value -end - -local function createLocal(key, effect, value, attrs) - if not key then - return nil - end - key.type = 'local' - key.effect = effect - key.value = value - key.attrs = attrs - if value then - key.range = value.finish - end - return key -end - -local function createCall(args, start, finish) - if args then - args.type = 'callargs' - args.start = start - args.finish = finish - end - return { - type = 'call', - start = start, - finish = finish, - args = args, - } -end - -local function packList(start, list, finish) - local lastFinish = start - local wantName = true - local count = 0 - for i = 1, #list do - local ast = list[i] - if ast.type == ',' then - if wantName or i == #list then - PushError { - type = 'UNEXPECT_SYMBOL', - start = ast.start, - finish = ast.finish, - info = { - symbol = ',', - } - } - end - wantName = true - else - if not wantName then - PushError { - type = 'MISS_SYMBOL', - start = lastFinish, - finish = ast.start - 1, - info = { - symbol = ',', - } - } - end - wantName = false - count = count + 1 - list[count] = list[i] - end - lastFinish = ast.finish + 1 - end - for i = count + 1, #list do - list[i] = nil - end - list.type = 'list' - list.start = start - list.finish = finish - 1 - return list -end - -local BinaryLevel = { - ['or'] = 1, - ['and'] = 2, - ['<='] = 3, - ['>='] = 3, - ['<'] = 3, - ['>'] = 3, - ['~='] = 3, - ['=='] = 3, - ['|'] = 4, - ['~'] = 5, - ['&'] = 6, - ['<<'] = 7, - ['>>'] = 7, - ['..'] = 8, - ['+'] = 9, - ['-'] = 9, - ['*'] = 10, - ['//'] = 10, - ['/'] = 10, - ['%'] = 10, - ['^'] = 11, -} - -local BinaryForward = { - [01] = true, - [02] = true, - [03] = true, - [04] = true, - [05] = true, - [06] = true, - [07] = true, - [08] = false, - [09] = true, - [10] = true, - [11] = false, -} - -local Defs = { - Nil = function (pos) - return { - type = 'nil', - start = pos, - finish = pos + 2, - } - end, - True = function (pos) - return { - type = 'boolean', - start = pos, - finish = pos + 3, - [1] = true, - } - end, - False = function (pos) - return { - type = 'boolean', - start = pos, - finish = pos + 4, - [1] = false, - } - end, - LongComment = function (beforeEq, afterEq, str, missPos) - if missPos then - local endSymbol = ']' .. ('='):rep(afterEq-beforeEq) .. ']' - local s, _, w = str:find('(%][%=]*%])[%c%s]*$') - if s then - PushError { - type = 'ERR_LCOMMENT_END', - start = missPos - #str + s - 1, - finish = missPos - #str + s + #w - 2, - info = { - symbol = endSymbol, - }, - fix = { - title = 'FIX_LCOMMENT_END', - { - start = missPos - #str + s - 1, - finish = missPos - #str + s + #w - 2, - text = endSymbol, - } - }, - } - end - PushError { - type = 'MISS_SYMBOL', - start = missPos, - finish = missPos, - info = { - symbol = endSymbol, - }, - fix = { - title = 'ADD_LCOMMENT_END', - { - start = missPos, - finish = missPos, - text = endSymbol, - } - }, - } - end - end, - CLongComment = function (start1, finish1, start2, finish2) - PushError { - type = 'ERR_C_LONG_COMMENT', - start = start1, - finish = finish2 - 1, - fix = { - title = 'FIX_C_LONG_COMMENT', - { - start = start1, - finish = finish1 - 1, - text = '--[[', - }, - { - start = start2, - finish = finish2 - 1, - text = '--]]' - }, - } - } - end, - CCommentPrefix = function (start, finish) - PushError { - type = 'ERR_COMMENT_PREFIX', - start = start, - finish = finish - 1, - fix = { - title = 'FIX_COMMENT_PREFIX', - { - start = start, - finish = finish - 1, - text = '--', - }, - } - } - end, - String = function (start, quote, str, finish) - return { - type = 'string', - start = start, - finish = finish - 1, - [1] = str, - [2] = quote, - } - end, - LongString = function (beforeEq, afterEq, str, missPos) - if missPos then - local endSymbol = ']' .. ('='):rep(afterEq-beforeEq) .. ']' - local s, _, w = str:find('(%][%=]*%])[%c%s]*$') - if s then - PushError { - type = 'ERR_LSTRING_END', - start = missPos - #str + s - 1, - finish = missPos - #str + s + #w - 2, - info = { - symbol = endSymbol, - }, - fix = { - title = 'FIX_LSTRING_END', - { - start = missPos - #str + s - 1, - finish = missPos - #str + s + #w - 2, - text = endSymbol, - } - }, - } - end - PushError { - type = 'MISS_SYMBOL', - start = missPos, - finish = missPos, - info = { - symbol = endSymbol, - }, - fix = { - title = 'ADD_LSTRING_END', - { - start = missPos, - finish = missPos, - text = endSymbol, - } - }, - } - end - return '[' .. ('='):rep(afterEq-beforeEq) .. '[', str - end, - Char10 = function (char) - char = tonumber(char) - if not char or char < 0 or char > 255 then - return '' - end - return stringChar(char) - end, - Char16 = function (pos, char) - if State.version == 'Lua 5.1' then - PushError { - type = 'ERR_ESC', - start = pos-1, - finish = pos, - version = {'Lua 5.2', 'Lua 5.3', 'Lua 5.4', 'LuaJIT'}, - info = { - version = State.version, - } - } - return char - end - return stringChar(tonumber(char, 16)) - end, - CharUtf8 = function (pos, char) - if State.version ~= 'Lua 5.3' - and State.version ~= 'Lua 5.4' - and State.version ~= 'LuaJIT' - then - PushError { - type = 'ERR_ESC', - start = pos-3, - finish = pos-2, - version = {'Lua 5.3', 'Lua 5.4', 'LuaJIT'}, - info = { - version = State.version, - } - } - return char - end - if #char == 0 then - PushError { - type = 'UTF8_SMALL', - start = pos-3, - finish = pos, - } - return '' - end - local v = tonumber(char, 16) - if not v then - for i = 1, #char do - if not tonumber(char:sub(i, i), 16) then - PushError { - type = 'MUST_X16', - start = pos + i - 1, - finish = pos + i - 1, - } - end - end - return '' - end - if State.version == 'Lua 5.4' then - if v < 0 or v > 0x7FFFFFFF then - PushError { - type = 'UTF8_MAX', - start = pos-3, - finish = pos+#char, - info = { - min = '00000000', - max = '7FFFFFFF', - } - } - end - else - if v < 0 or v > 0x10FFFF then - PushError { - type = 'UTF8_MAX', - start = pos-3, - finish = pos+#char, - version = v <= 0x7FFFFFFF and 'Lua 5.4' or nil, - info = { - min = '000000', - max = '10FFFF', - } - } - end - end - if v >= 0 and v <= 0x10FFFF then - return utf8Char(v) - end - return '' - end, - Number = function (start, number, finish) - local n = tonumber(number) - if n then - State.LastNumber = { - type = 'number', - start = start, - finish = finish - 1, - [1] = n, - } - return State.LastNumber - else - PushError { - type = 'MALFORMED_NUMBER', - start = start, - finish = finish - 1, - } - State.LastNumber = { - type = 'number', - start = start, - finish = finish - 1, - [1] = 0, - } - return State.LastNumber - end - end, - FFINumber = function (start, symbol) - local lastNumber = State.LastNumber - if mathType(lastNumber[1]) == 'float' then - PushError { - type = 'UNKNOWN_SYMBOL', - start = start, - finish = start + #symbol - 1, - info = { - symbol = symbol, - } - } - lastNumber[1] = 0 - return - end - if State.version ~= 'LuaJIT' then - PushError { - type = 'UNSUPPORT_SYMBOL', - start = start, - finish = start + #symbol - 1, - version = 'LuaJIT', - info = { - version = State.version, - } - } - lastNumber[1] = 0 - end - end, - ImaginaryNumber = function (start, symbol) - local lastNumber = State.LastNumber - if State.version ~= 'LuaJIT' then - PushError { - type = 'UNSUPPORT_SYMBOL', - start = start, - finish = start + #symbol - 1, - version = 'LuaJIT', - info = { - version = State.version, - } - } - end - lastNumber[1] = 0 - end, - Name = function (start, str, finish) - local isKeyWord - if RESERVED[str] then - isKeyWord = true - elseif str == 'goto' then - if State.version ~= 'Lua 5.1' and State.version ~= 'LuaJIT' then - isKeyWord = true - end - end - if isKeyWord then - PushError { - type = 'KEYWORD', - start = start, - finish = finish - 1, - } - end - return { - type = 'name', - start = start, - finish = finish - 1, - [1] = str, - } - end, - GetField = function (dot, field) - local obj = { - type = 'getfield', - field = field, - dot = dot, - start = dot.start, - finish = (field or dot).finish, - } - if field then - field.type = 'field' - field.parent = obj - end - return obj - end, - GetIndex = function (start, index, finish) - local obj = { - type = 'getindex', - start = start, - finish = finish - 1, - index = index, - } - if index then - index.parent = obj - end - return obj - end, - GetMethod = function (colon, method) - local obj = { - type = 'getmethod', - method = method, - colon = colon, - start = colon.start, - finish = (method or colon).finish, - } - if method then - method.type = 'method' - method.parent = obj - end - return obj - end, - Single = function (unit) - unit.type = 'getname' - return unit - end, - Simple = function (units) - local last = units[1] - for i = 2, #units do - local current = units[i] - current.node = last - current.start = last.start - last.next = current - last = units[i] - end - return last - end, - SimpleCall = function (call) - if call.type ~= 'call' and call.type ~= 'getmethod' then - PushError { - type = 'EXP_IN_ACTION', - start = call.start, - finish = call.finish, - } - end - return call - end, - BinaryOp = function (start, op) - return { - type = op, - start = start, - finish = start + #op - 1, - } - end, - UnaryOp = function (start, op) - return { - type = op, - start = start, - finish = start + #op - 1, - } - end, - Unary = function (first, ...) - if not ... then - return nil - end - local list = {first, ...} - local e = list[#list] - for i = #list - 1, 1, -1 do - local op = list[i] - checkOpVersion(op) - e = { - type = 'unary', - op = op, - start = op.start, - finish = e.finish, - [1] = e, - } - end - return e - end, - SubBinary = function (op, symb) - if symb then - return op, symb - end - PushError { - type = 'MISS_EXP', - start = op.start, - finish = op.finish, - } - end, - Binary = function (first, op, second, ...) - if not first then - return second - end - if not op then - return first - end - if not ... then - checkOpVersion(op) - return { - type = 'binary', - op = op, - start = first.start, - finish = second.finish, - [1] = first, - [2] = second, - } - end - local list = {first, op, second, ...} - local ops = {} - for i = 2, #list, 2 do - ops[#ops+1] = i - end - tableSort(ops, function (a, b) - local op1 = list[a] - local op2 = list[b] - local lv1 = BinaryLevel[op1.type] - local lv2 = BinaryLevel[op2.type] - if lv1 == lv2 then - local forward = BinaryForward[lv1] - if forward then - return op1.start > op2.start - else - return op1.start < op2.start - end - else - return lv1 < lv2 - end - end) - local final - for i = #ops, 1, -1 do - local n = ops[i] - local op = list[n] - local left = list[n-1] - local right = list[n+1] - local exp = { - type = 'binary', - op = op, - start = left.start, - finish = right and right.finish or op.finish, - [1] = left, - [2] = right, - } - local leftIndex, rightIndex - if list[left] then - leftIndex = list[left[1]] - else - leftIndex = n - 1 - end - if list[right] then - rightIndex = list[right[2]] - else - rightIndex = n + 1 - end - - list[leftIndex] = exp - list[rightIndex] = exp - list[left] = leftIndex - list[right] = rightIndex - list[exp] = n - final = exp - - checkOpVersion(op) - end - return final - end, - Paren = function (start, exp, finish) - if exp and exp.type == 'paren' then - exp.start = start - exp.finish = finish - 1 - return exp - end - return { - type = 'paren', - start = start, - finish = finish - 1, - exp = exp - } - end, - VarArgs = function (dots) - dots.type = 'varargs' - return dots - end, - PackLoopArgs = function (start, list, finish) - local list = packList(start, list, finish) - if #list == 0 then - PushError { - type = 'MISS_LOOP_MIN', - start = finish, - finish = finish, - } - elseif #list == 1 then - PushError { - type = 'MISS_LOOP_MAX', - start = finish, - finish = finish, - } - end - return list - end, - PackInNameList = function (start, list, finish) - local list = packList(start, list, finish) - if #list == 0 then - PushError { - type = 'MISS_NAME', - start = start, - finish = finish, - } - end - return list - end, - PackInExpList = function (start, list, finish) - local list = packList(start, list, finish) - if #list == 0 then - PushError { - type = 'MISS_EXP', - start = start, - finish = finish, - } - end - return list - end, - PackExpList = function (start, list, finish) - local list = packList(start, list, finish) - return list - end, - PackNameList = function (start, list, finish) - local list = packList(start, list, finish) - return list - end, - Call = function (start, args, finish) - return createCall(args, start, finish-1) - end, - COMMA = function (start) - return { - type = ',', - start = start, - finish = start, - } - end, - SEMICOLON = function (start) - return { - type = ';', - start = start, - finish = start, - } - end, - DOTS = function (start) - return { - type = '...', - start = start, - finish = start + 2, - } - end, - COLON = function (start) - return { - type = ':', - start = start, - finish = start, - } - end, - DOT = function (start) - return { - type = '.', - start = start, - finish = start, - } - end, - Function = function (functionStart, functionFinish, args, actions, endStart, endFinish) - actions.type = 'function' - actions.start = functionStart - actions.finish = endFinish - 1 - actions.args = args - actions.keyword= { - functionStart, functionFinish - 1, - endStart, endFinish - 1, - } - checkMissEnd(functionStart) - return actions - end, - NamedFunction = function (functionStart, functionFinish, name, args, actions, endStart, endFinish) - actions.type = 'function' - actions.start = functionStart - actions.finish = endFinish - 1 - actions.args = args - actions.keyword= { - functionStart, functionFinish - 1, - endStart, endFinish - 1, - } - checkMissEnd(functionStart) - if not name then - return - end - if name.type == 'getname' then - name.type = 'setname' - name.value = actions - elseif name.type == 'getfield' then - name.type = 'setfield' - name.value = actions - elseif name.type == 'getmethod' then - name.type = 'setmethod' - name.value = actions - end - name.range = actions.finish - name.vstart = functionStart - return name - end, - LocalFunction = function (start, functionStart, functionFinish, name, args, actions, endStart, endFinish) - actions.type = 'function' - actions.start = start - actions.finish = endFinish - 1 - actions.args = args - actions.keyword= { - functionStart, functionFinish - 1, - endStart, endFinish - 1, - } - checkMissEnd(start) - - if not name then - return - end - - if name.type ~= 'getname' then - PushError { - type = 'UNEXPECT_LFUNC_NAME', - start = name.start, - finish = name.finish, - } - return - end - - local loc = createLocal(name, name.start, actions) - loc.localfunction = true - loc.vstart = functionStart - - return loc - end, - Table = function (start, tbl, finish) - tbl.type = 'table' - tbl.start = start - tbl.finish = finish - 1 - local wantField = true - local lastStart = start + 1 - local fieldCount = 0 - for i = 1, #tbl do - local field = tbl[i] - if field.type == ',' or field.type == ';' then - if wantField then - PushError { - type = 'MISS_EXP', - start = lastStart, - finish = field.start - 1, - } - end - wantField = true - lastStart = field.finish + 1 - else - if not wantField then - PushError { - type = 'MISS_SEP_IN_TABLE', - start = lastStart, - finish = field.start - 1, - } - end - wantField = false - lastStart = field.finish + 1 - fieldCount = fieldCount + 1 - tbl[fieldCount] = field - end - end - for i = fieldCount + 1, #tbl do - tbl[i] = nil - end - return tbl - end, - NewField = function (start, field, value, finish) - local obj = { - type = 'tablefield', - start = start, - finish = finish-1, - field = field, - value = value, - } - if field then - field.type = 'field' - field.parent = obj - end - return obj - end, - NewIndex = function (start, index, value, finish) - local obj = { - type = 'tableindex', - start = start, - finish = finish-1, - index = index, - value = value, - } - if index then - index.parent = obj - end - return obj - end, - FuncArgs = function (start, args, finish) - args.type = 'funcargs' - args.start = start - args.finish = finish - 1 - local lastStart = start + 1 - local wantName = true - local argCount = 0 - for i = 1, #args do - local arg = args[i] - local argAst = arg - if argAst.type == ',' then - if wantName then - PushError { - type = 'MISS_NAME', - start = lastStart, - finish = argAst.start-1, - } - end - wantName = true - else - if not wantName then - PushError { - type = 'MISS_SYMBOL', - start = lastStart-1, - finish = argAst.start-1, - info = { - symbol = ',', - } - } - end - wantName = false - argCount = argCount + 1 - - if argAst.type == '...' then - args[argCount] = arg - if i < #args then - local a = args[i+1] - local b = args[#args] - PushError { - type = 'ARGS_AFTER_DOTS', - start = a.start, - finish = b.finish, - } - end - break - else - args[argCount] = createLocal(arg, arg.start) - end - end - lastStart = argAst.finish + 1 - end - for i = argCount + 1, #args do - args[i] = nil - end - if wantName and argCount > 0 then - PushError { - type = 'MISS_NAME', - start = lastStart, - finish = finish - 1, - } - end - return args - end, - Set = function (start, keys, values, finish) - for i = 1, #keys do - local key = keys[i] - if key.type == 'getname' then - key.type = 'setname' - key.value = getValue(values, i) - elseif key.type == 'getfield' then - key.type = 'setfield' - key.value = getValue(values, i) - elseif key.type == 'getindex' then - key.type = 'setindex' - key.value = getValue(values, i) - end - if key.value then - key.range = key.value.finish - end - end - if values then - for i = #keys+1, #values do - local value = values[i] - PushDiag('redundant-value', { - start = value.start, - finish = value.finish, - max = #keys, - passed = #values, - }) - end - end - return tableUnpack(keys) - end, - LocalAttr = function (attrs) - for i = 1, #attrs do - local attr = attrs[i] - local attrAst = attr - attrAst.type = 'localattr' - if State.version ~= 'Lua 5.4' then - PushError { - type = 'UNSUPPORT_SYMBOL', - start = attrAst.start, - finish = attrAst.finish, - version = 'Lua 5.4', - info = { - version = State.version, - } - } - elseif attrAst[1] ~= 'const' and attrAst[1] ~= 'close' then - PushError { - type = 'UNKNOWN_TAG', - start = attrAst.start, - finish = attrAst.finish, - info = { - tag = attrAst[1], - } - } - elseif i > 1 then - PushError { - type = 'MULTI_TAG', - start = attrAst.start, - finish = attrAst.finish, - info = { - tag = attrAst[1], - } - } - end - end - return attrs - end, - LocalName = function (name, attrs) - if not name then - return name - end - name.attrs = attrs - return name - end, - Local = function (start, keys, values, finish) - for i = 1, #keys do - local key = keys[i] - local attrs = key.attrs - key.attrs = nil - local value = getValue(values, i) - createLocal(key, finish, value, attrs) - end - if values then - for i = #keys+1, #values do - local value = values[i] - PushDiag('redundant-value', { - start = value.start, - finish = value.finish, - max = #keys, - passed = #values, - }) - end - end - return tableUnpack(keys) - end, - Do = function (start, actions, endA, endB) - actions.type = 'do' - actions.start = start - actions.finish = endB - 1 - actions.keyword= { - start, start + #'do' - 1, - endA , endB - 1, - } - checkMissEnd(start) - return actions - end, - Break = function (start, finish) - return { - type = 'break', - start = start, - finish = finish - 1, - } - end, - Return = function (start, exps, finish) - exps.type = 'return' - exps.start = start - exps.finish = finish - 1 - return exps - end, - Label = function (start, name, finish) - if State.version == 'Lua 5.1' then - PushError { - type = 'UNSUPPORT_SYMBOL', - start = start, - finish = finish - 1, - version = {'Lua 5.2', 'Lua 5.3', 'Lua 5.4', 'LuaJIT'}, - info = { - version = State.version, - } - } - return - end - if not name then - return nil - end - name.type = 'label' - return name - end, - GoTo = function (start, name, finish) - if State.version == 'Lua 5.1' then - PushError { - type = 'UNSUPPORT_SYMBOL', - start = start, - finish = finish - 1, - version = {'Lua 5.2', 'Lua 5.3', 'Lua 5.4', 'LuaJIT'}, - info = { - version = State.version, - } - } - return - end - if not name then - return nil - end - name.type = 'goto' - return name - end, - IfBlock = function (ifStart, ifFinish, exp, thenStart, thenFinish, actions, finish) - actions.type = 'ifblock' - actions.start = ifStart - actions.finish = finish - 1 - actions.filter = exp - actions.keyword= { - ifStart, ifFinish - 1, - thenStart, thenFinish - 1, - } - return actions - end, - ElseIfBlock = function (elseifStart, elseifFinish, exp, thenStart, thenFinish, actions, finish) - actions.type = 'elseifblock' - actions.start = elseifStart - actions.finish = finish - 1 - actions.filter = exp - actions.keyword= { - elseifStart, elseifFinish - 1, - thenStart, thenFinish - 1, - } - return actions - end, - ElseBlock = function (elseStart, elseFinish, actions, finish) - actions.type = 'elseblock' - actions.start = elseStart - actions.finish = finish - 1 - actions.keyword= { - elseStart, elseFinish - 1, - } - return actions - end, - If = function (start, blocks, endStart, endFinish) - blocks.type = 'if' - blocks.start = start - blocks.finish = endFinish - 1 - local hasElse - for i = 1, #blocks do - local block = blocks[i] - if i == 1 and block.type ~= 'ifblock' then - PushError { - type = 'MISS_SYMBOL', - start = block.start, - finish = block.start, - info = { - symbol = 'if', - } - } - end - if hasElse then - PushError { - type = 'BLOCK_AFTER_ELSE', - start = block.start, - finish = block.finish, - } - end - if block.type == 'elseblock' then - hasElse = true - end - end - checkMissEnd(start) - return blocks - end, - Loop = function (forA, forB, arg, steps, doA, doB, blockStart, block, endA, endB) - local loc = createLocal(arg, blockStart, steps[1]) - block.type = 'loop' - block.start = forA - block.finish = endB - 1 - block.loc = loc - block.max = steps[2] - block.step = steps[3] - block.keyword= { - forA, forB - 1, - doA , doB - 1, - endA, endB - 1, - } - checkMissEnd(forA) - return block - end, - In = function (forA, forB, keys, inA, inB, exp, doA, doB, blockStart, block, endA, endB) - local func = tableRemove(exp, 1) - block.type = 'in' - block.start = forA - block.finish = endB - 1 - block.keys = keys - block.keyword= { - forA, forB - 1, - inA , inB - 1, - doA , doB - 1, - endA, endB - 1, - } - - local values - if func then - local call = createCall(exp, func.finish + 1, exp.finish) - call.node = func - call.start = func.start - func.next = call - values = { call } - keys.range = call.finish - end - for i = 1, #keys do - local loc = keys[i] - if values then - createLocal(loc, blockStart, getValue(values, i)) - else - createLocal(loc, blockStart) - end - end - checkMissEnd(forA) - return block - end, - While = function (whileA, whileB, filter, doA, doB, block, endA, endB) - block.type = 'while' - block.start = whileA - block.finish = endB - 1 - block.filter = filter - block.keyword= { - whileA, whileB - 1, - doA , doB - 1, - endA , endB - 1, - } - checkMissEnd(whileA) - return block - end, - Repeat = function (repeatA, repeatB, block, untilA, untilB, filter, finish) - block.type = 'repeat' - block.start = repeatA - block.finish = finish - block.filter = filter - block.keyword= { - repeatA, repeatB - 1, - untilA , untilB - 1, - } - return block - end, - Lua = function (start, actions, finish) - actions.type = 'main' - actions.start = start - actions.finish = finish - 1 - return actions - end, - - -- 捕获错误 - UnknownSymbol = function (start, symbol) - PushError { - type = 'UNKNOWN_SYMBOL', - start = start, - finish = start + #symbol - 1, - info = { - symbol = symbol, - } - } - return - end, - UnknownAction = function (start, symbol) - PushError { - type = 'UNKNOWN_SYMBOL', - start = start, - finish = start + #symbol - 1, - info = { - symbol = symbol, - } - } - end, - DirtyName = function (pos) - PushError { - type = 'MISS_NAME', - start = pos, - finish = pos, - } - return nil - end, - DirtyExp = function (pos) - PushError { - type = 'MISS_EXP', - start = pos, - finish = pos, - } - return nil - end, - MissExp = function (pos) - PushError { - type = 'MISS_EXP', - start = pos, - finish = pos, - } - end, - MissExponent = function (start, finish) - PushError { - type = 'MISS_EXPONENT', - start = start, - finish = finish - 1, - } - end, - MissQuote1 = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = '"' - } - } - end, - MissQuote2 = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = "'" - } - } - end, - MissEscX = function (pos) - PushError { - type = 'MISS_ESC_X', - start = pos-2, - finish = pos+1, - } - end, - MissTL = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = '{', - } - } - end, - MissTR = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = '}', - } - } - end, - MissBR = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = ']', - } - } - end, - MissPL = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = '(', - } - } - end, - MissPR = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = ')', - } - } - end, - ErrEsc = function (pos) - PushError { - type = 'ERR_ESC', - start = pos-1, - finish = pos, - } - end, - MustX16 = function (pos, str) - PushError { - type = 'MUST_X16', - start = pos, - finish = pos + #str - 1, - } - end, - MissAssign = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = '=', - } - } - end, - MissTableSep = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = ',' - } - } - end, - MissField = function (pos) - PushError { - type = 'MISS_FIELD', - start = pos, - finish = pos, - } - end, - MissMethod = function (pos) - PushError { - type = 'MISS_METHOD', - start = pos, - finish = pos, - } - end, - MissLabel = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = '::', - } - } - end, - MissEnd = function (pos) - State.MissEndErr = PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = 'end', - } - } - return pos, pos - end, - MissDo = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = 'do', - } - } - return pos, pos - end, - MissComma = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = ',', - } - } - end, - MissIn = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = 'in', - } - } - return pos, pos - end, - MissUntil = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = 'until', - } - } - return pos, pos - end, - MissThen = function (pos) - PushError { - type = 'MISS_SYMBOL', - start = pos, - finish = pos, - info = { - symbol = 'then', - } - } - return pos, pos - end, - MissName = function (pos) - PushError { - type = 'MISS_NAME', - start = pos, - finish = pos, - } - end, - ExpInAction = function (start, exp, finish) - PushError { - type = 'EXP_IN_ACTION', - start = start, - finish = finish - 1, - } - return exp - end, - MissIf = function (start, block) - PushError { - type = 'MISS_SYMBOL', - start = start, - finish = start, - info = { - symbol = 'if', - } - } - return block - end, - MissGT = function (start) - PushError { - type = 'MISS_SYMBOL', - start = start, - finish = start, - info = { - symbol = '>' - } - } - end, - ErrAssign = function (start, finish) - PushError { - type = 'ERR_ASSIGN_AS_EQ', - start = start, - finish = finish - 1, - fix = { - title = 'FIX_ASSIGN_AS_EQ', - { - start = start, - finish = finish - 1, - text = '=', - } - } - } - end, - ErrEQ = function (start, finish) - PushError { - type = 'ERR_EQ_AS_ASSIGN', - start = start, - finish = finish - 1, - fix = { - title = 'FIX_EQ_AS_ASSIGN', - { - start = start, - finish = finish - 1, - text = '==', - } - } - } - return '==' - end, - ErrUEQ = function (start, finish) - PushError { - type = 'ERR_UEQ', - start = start, - finish = finish - 1, - fix = { - title = 'FIX_UEQ', - { - start = start, - finish = finish - 1, - text = '~=', - } - } - } - return '==' - end, - ErrThen = function (start, finish) - PushError { - type = 'ERR_THEN_AS_DO', - start = start, - finish = finish - 1, - fix = { - title = 'FIX_THEN_AS_DO', - { - start = start, - finish = finish - 1, - text = 'then', - } - } - } - return start, finish - end, - ErrDo = function (start, finish) - PushError { - type = 'ERR_DO_AS_THEN', - start = start, - finish = finish - 1, - fix = { - title = 'FIX_DO_AS_THEN', - { - start = start, - finish = finish - 1, - text = 'do', - } - } - } - return start, finish - end, -} - ---for k, v in pairs(emmy.ast) do --- Defs[k] = v ---end - -local function init(state) - State = state - PushError = state.pushError - PushDiag = state.pushDiag - emmy.init(State) -end - -local function close() - State = nil - PushError = nil - PushDiag = nil -end - -return { - defs = Defs, - init = init, - close = close, -} diff --git a/server-beta/src/parser/calcline.lua b/server-beta/src/parser/calcline.lua deleted file mode 100644 index 26f475d9..00000000 --- a/server-beta/src/parser/calcline.lua +++ /dev/null @@ -1,93 +0,0 @@ -local m = require 'lpeglabel' - -local row -local fl -local NL = (m.P'\r\n' + m.S'\r\n') * m.Cp() / function (pos) - row = row + 1 - fl = pos -end -local ROWCOL = (NL + m.P(1))^0 -local function rowcol(str, n) - row = 1 - fl = 1 - ROWCOL:match(str:sub(1, n)) - local col = n - fl + 1 - return row, col -end - -local function rowcol_utf8(str, n) - row = 1 - fl = 1 - ROWCOL:match(str:sub(1, n)) - return row, utf8.len(str, fl, n) -end - -local function position(str, _row, _col) - local cur = 1 - local row = 1 - while true do - if row == _row then - return cur + _col - 1 - elseif row > _row then - return cur - 1 - end - local pos = str:find('[\r\n]', cur) - if not pos then - return #str - end - row = row + 1 - if str:sub(pos, pos+1) == '\r\n' then - cur = pos + 2 - else - cur = pos + 1 - end - end -end - -local function position_utf8(str, _row, _col) - local cur = 1 - local row = 1 - while true do - if row == _row then - return utf8.offset(str, _col, cur) - elseif row > _row then - return cur - 1 - end - local pos = str:find('[\r\n]', cur) - if not pos then - return #str - end - row = row + 1 - if str:sub(pos, pos+1) == '\r\n' then - cur = pos + 2 - else - cur = pos + 1 - end - end -end - -local NL = m.P'\r\n' + m.S'\r\n' - -local function line(str, row) - local count = 0 - local res - local LINE = m.Cmt((1 - NL)^0, function (_, _, c) - count = count + 1 - if count == row then - res = c - return false - end - return true - end) - local MATCH = (LINE * NL)^0 * LINE - MATCH:match(str) - return res -end - -return { - rowcol = rowcol, - rowcol_utf8 = rowcol_utf8, - position = position, - position_utf8 = position_utf8, - line = line, -} diff --git a/server-beta/src/parser/compile.lua b/server-beta/src/parser/compile.lua deleted file mode 100644 index bcd9ecc8..00000000 --- a/server-beta/src/parser/compile.lua +++ /dev/null @@ -1,549 +0,0 @@ -local guide = require 'parser.guide' -local type = type - -local specials = { - ['_G'] = true, - ['rawset'] = true, - ['rawget'] = true, - ['setmetatable'] = true, - ['require'] = true, - ['dofile'] = true, - ['loadfile'] = true, - ['pcall'] = true, - ['xpcall'] = true, -} - -_ENV = nil - -local LocalLimit = 200 -local pushError, Compile, CompileBlock, Block, GoToTag, ENVMode, Compiled, LocalCount, Version, Root - -local function addRef(node, obj) - if not node.ref then - node.ref = {} - end - node.ref[#node.ref+1] = obj - obj.node = node -end - -local function addSpecial(name, obj) - if not Root.specials then - Root.specials = {} - end - if not Root.specials[name] then - Root.specials[name] = {} - end - Root.specials[name][#Root.specials[name]+1] = obj - obj.special = name -end - -local vmMap = { - ['getname'] = function (obj) - local loc = guide.getLocal(obj, obj[1], obj.start) - if loc then - obj.type = 'getlocal' - obj.loc = loc - addRef(loc, obj) - if loc.special then - addSpecial(loc.special, obj) - end - else - obj.type = 'getglobal' - if ENVMode == '_ENV' then - local node = guide.getLocal(obj, '_ENV', obj.start) - if node then - addRef(node, obj) - end - end - local name = obj[1] - if specials[name] then - addSpecial(name, obj) - end - end - return obj - end, - ['getfield'] = function (obj) - Compile(obj.node, obj) - end, - ['call'] = function (obj) - Compile(obj.node, obj) - Compile(obj.args, obj) - end, - ['callargs'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - end, - ['binary'] = function (obj) - Compile(obj[1], obj) - Compile(obj[2], obj) - end, - ['unary'] = function (obj) - Compile(obj[1], obj) - end, - ['varargs'] = function (obj) - local func = guide.getParentFunction(obj) - if func then - local index, vararg = guide.getFunctionVarArgs(func) - if not index then - pushError { - type = 'UNEXPECT_DOTS', - start = obj.start, - finish = obj.finish, - } - end - if vararg then - if not vararg.ref then - vararg.ref = {} - end - vararg.ref[#vararg.ref+1] = obj - end - end - end, - ['paren'] = function (obj) - Compile(obj.exp, obj) - end, - ['getindex'] = function (obj) - Compile(obj.node, obj) - Compile(obj.index, obj) - end, - ['setindex'] = function (obj) - Compile(obj.node, obj) - Compile(obj.index, obj) - Compile(obj.value, obj) - end, - ['getmethod'] = function (obj) - Compile(obj.node, obj) - Compile(obj.method, obj) - end, - ['setmethod'] = function (obj) - Compile(obj.node, obj) - Compile(obj.method, obj) - local value = obj.value - value.localself = { - type = 'local', - start = 0, - finish = 0, - method = obj, - effect = obj.finish, - tag = 'self', - [1] = 'self', - } - Compile(value, obj) - end, - ['function'] = function (obj) - local lastBlock = Block - local LastLocalCount = LocalCount - Block = obj - LocalCount = 0 - if obj.localself then - Compile(obj.localself, obj) - obj.localself = nil - end - Compile(obj.args, obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - Block = lastBlock - LocalCount = LastLocalCount - end, - ['funcargs'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - end, - ['table'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - end, - ['tablefield'] = function (obj) - Compile(obj.value, obj) - end, - ['tableindex'] = function (obj) - Compile(obj.index, obj) - Compile(obj.value, obj) - end, - ['index'] = function (obj) - Compile(obj.index, obj) - end, - ['select'] = function (obj) - local vararg = obj.vararg - if vararg.parent then - if not vararg.extParent then - vararg.extParent = {} - end - vararg.extParent[#vararg.extParent+1] = obj - else - Compile(vararg, obj) - end - end, - ['setname'] = function (obj) - Compile(obj.value, obj) - local loc = guide.getLocal(obj, obj[1], obj.start) - if loc then - obj.type = 'setlocal' - obj.loc = loc - addRef(loc, obj) - if loc.attrs then - local const - for i = 1, #loc.attrs do - local attr = loc.attrs[i][1] - if attr == 'const' - or attr == 'close' then - const = true - break - end - end - if const then - pushError { - type = 'SET_CONST', - start = obj.start, - finish = obj.finish, - } - end - end - else - obj.type = 'setglobal' - if ENVMode == '_ENV' then - local node = guide.getLocal(obj, '_ENV', obj.start) - if node then - addRef(node, obj) - end - end - end - end, - ['local'] = function (obj) - local attrs = obj.attrs - if attrs then - for i = 1, #attrs do - Compile(attrs[i], obj) - end - end - if Block then - if not Block.locals then - Block.locals = {} - end - Block.locals[#Block.locals+1] = obj - LocalCount = LocalCount + 1 - if LocalCount > LocalLimit then - pushError { - type = 'LOCAL_LIMIT', - start = obj.start, - finish = obj.finish, - } - end - end - if obj.localfunction then - obj.localfunction = nil - end - Compile(obj.value, obj) - if obj.value and obj.value.special then - addSpecial(obj.value.special, obj) - end - end, - ['setfield'] = function (obj) - Compile(obj.node, obj) - Compile(obj.value, obj) - end, - ['do'] = function (obj) - local lastBlock = Block - Block = obj - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['return'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - if Block and Block[#Block] ~= obj then - pushError { - type = 'ACTION_AFTER_RETURN', - start = obj.start, - finish = obj.finish, - } - end - local func = guide.getParentFunction(obj) - if func then - if not func.returns then - func.returns = {} - end - func.returns[#func.returns+1] = obj - end - end, - ['label'] = function (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(block, name) - if label then - if Version == 'Lua 5.4' - or block == guide.getBlock(label) then - pushError { - type = 'REDEFINED_LABEL', - start = obj.start, - finish = obj.finish, - relative = { - { - label.start, - label.finish, - } - } - } - end - end - block.labels[name] = obj - end - end, - ['goto'] = function (obj) - GoToTag[#GoToTag+1] = obj - end, - ['if'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - end, - ['ifblock'] = function (obj) - local lastBlock = Block - Block = obj - Compile(obj.filter, obj) - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['elseifblock'] = function (obj) - local lastBlock = Block - Block = obj - Compile(obj.filter, obj) - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['elseblock'] = function (obj) - local lastBlock = Block - Block = obj - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['loop'] = function (obj) - local lastBlock = Block - Block = obj - Compile(obj.loc, obj) - Compile(obj.max, obj) - Compile(obj.step, obj) - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['in'] = function (obj) - local lastBlock = Block - Block = obj - local keys = obj.keys - for i = 1, #keys do - Compile(keys[i], obj) - end - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['while'] = function (obj) - local lastBlock = Block - Block = obj - Compile(obj.filter, obj) - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['repeat'] = function (obj) - local lastBlock = Block - Block = obj - CompileBlock(obj, obj) - Compile(obj.filter, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['break'] = function (obj) - local block = guide.getBreakBlock(obj) - if block then - if not block.breaks then - block.breaks = {} - end - block.breaks[#block.breaks+1] = obj - else - pushError { - type = 'BREAK_OUTSIDE', - start = obj.start, - finish = obj.finish, - } - end - end, - ['main'] = function (obj) - Block = obj - if ENVMode == '_ENV' then - Compile({ - type = 'local', - start = 0, - finish = 0, - effect = 0, - tag = '_ENV', - special= '_G', - [1] = '_ENV', - }, obj) - end - --- _ENV 是上值,不计入局部变量计数 - LocalCount = 0 - CompileBlock(obj, obj) - Block = nil - end, -} - -function CompileBlock(obj, parent) - for i = 1, #obj do - local act = obj[i] - local f = vmMap[act.type] - if f then - act.parent = parent - f(act) - end - end -end - -function Compile(obj, parent) - if not obj then - return nil - end - if Compiled[obj] then - return - end - Compiled[obj] = true - obj.parent = parent - local f = vmMap[obj.type] - if not f then - return - end - f(obj) -end - -local function compileGoTo(obj) - local name = obj[1] - local label = guide.getLabel(obj, name) - if not label then - pushError { - type = 'NO_VISIBLE_LABEL', - start = obj.start, - finish = obj.finish, - info = { - label = name, - } - } - return - end - if not label.ref then - label.ref = {} - end - label.ref[#label.ref+1] = obj - - -- 如果有局部变量在 goto 与 label 之间声明, - -- 并在 label 之后使用,则算作语法错误 - - -- 如果 label 在 goto 之前声明,那么不会有中间声明的局部变量 - if obj.start > label.start then - return - end - - local block = guide.getBlock(obj) - local locals = block and block.locals - if not locals then - return - end - - for i = 1, #locals do - local loc = locals[i] - -- 检查局部变量声明位置为 goto 与 label 之间 - if loc.start < obj.start or loc.finish > label.finish then - goto CONTINUE - end - -- 检查局部变量的使用位置在 label 之后 - local refs = loc.ref - if not refs then - goto CONTINUE - end - for j = 1, #refs do - local ref = refs[j] - if ref.finish > label.finish then - pushError { - type = 'JUMP_LOCAL_SCOPE', - start = obj.start, - finish = obj.finish, - info = { - loc = loc[1], - }, - relative = { - { - start = label.start, - finish = label.finish, - }, - { - start = loc.start, - finish = loc.finish, - } - }, - } - return - end - end - ::CONTINUE:: - end -end - -local function PostCompile() - for i = 1, #GoToTag do - compileGoTo(GoToTag[i]) - end -end - -return function (self, lua, mode, version) - local state, err = self:parse(lua, mode, version) - if not state then - return nil, err - end - pushError = state.pushError - if version == 'Lua 5.1' or version == 'LuaJIT' then - ENVMode = 'fenv' - else - ENVMode = '_ENV' - end - Compiled = {} - GoToTag = {} - LocalCount = 0 - Version = version - Root = state.ast - if type(state.ast) == 'table' then - Compile(state.ast) - end - PostCompile() - Compiled = nil - GoToTag = nil - return state -end diff --git a/server-beta/src/parser/emmy.lua b/server-beta/src/parser/emmy.lua deleted file mode 100644 index 4c1e087a..00000000 --- a/server-beta/src/parser/emmy.lua +++ /dev/null @@ -1,321 +0,0 @@ -local State -local pushError - -local grammar = [[ -EmmyLua <- ({} '---' EmmyBody {} ShortComment) - -> EmmyLua -EmmySp <- (!'---@' !'---' Comment / %s / %nl)* -EmmyComments <- (EmmyComment (%nl EmmyComMulti / %nl EmmyComSingle)*) -EmmyComment <- EmmySp %s* {(!%nl .)*} -EmmyComMulti <- EmmySp '---|' {} -> en {(!%nl .)*} -EmmyComSingle <- EmmySp '---' !'@' %s* {} -> ' ' {(!%nl .)*} -EmmyBody <- '@class' %s+ EmmyClass -> EmmyClass - / '@type' %s+ EmmyType -> EmmyType - / '@alias' %s+ EmmyAlias -> EmmyAlias - / '@param' %s+ EmmyParam -> EmmyParam - / '@return' %s+ EmmyReturn -> EmmyReturn - / '@field' %s+ EmmyField -> EmmyField - / '@generic' %s+ EmmyGeneric -> EmmyGeneric - / '@vararg' %s+ EmmyVararg -> EmmyVararg - / '@language' %s+ EmmyLanguage -> EmmyLanguage - / '@see' %s+ EmmySee -> EmmySee - / '@overload' %s+ EmmyOverLoad -> EmmyOverLoad - / %s* EmmyComments -> EmmyComment - / EmmyIncomplete - -EmmyName <- ({} {[a-zA-Z_] [a-zA-Z0-9_]*}) - -> EmmyName -MustEmmyName <- EmmyName / DirtyEmmyName -DirtyEmmyName <- {} -> DirtyEmmyName -EmmyLongName <- ({} {(!%nl .)+}) - -> EmmyName -EmmyIncomplete <- MustEmmyName - -> EmmyIncomplete - -EmmyClass <- (MustEmmyName EmmyParentClass?) -EmmyParentClass <- %s* {} ':' %s* MustEmmyName - -EmmyType <- EmmyTypeUnits EmmyTypeEnums -EmmyTypeUnits <- {| - EmmyTypeUnit? - (%s* '|' %s* !String EmmyTypeUnit)* - |} -EmmyTypeEnums <- {| EmmyTypeEnum* |} -EmmyTypeUnit <- EmmyFunctionType - / EmmyTableType - / EmmyArrayType - / EmmyCommonType -EmmyCommonType <- EmmyName - -> EmmyCommonType -EmmyTypeEnum <- %s* (%nl %s* '---')? '|'? EmmyEnum - -> EmmyTypeEnum -EmmyEnum <- %s* {'>'?} %s* String (EmmyEnumComment / (!%nl !'|' .)*) -EmmyEnumComment <- %s* '#' %s* {(!%nl .)*} - -EmmyAlias <- MustEmmyName %s* EmmyType EmmyTypeEnum* - -EmmyParam <- MustEmmyName %s* EmmyType %s* EmmyOption %s* EmmyTypeEnum* -EmmyOption <- Table? - -> EmmyOption - -EmmyReturn <- {} %nil {} Table -> EmmyOption - / {} EmmyType {} EmmyOption - -EmmyField <- (EmmyFieldAccess MustEmmyName %s* EmmyType) -EmmyFieldAccess <- ({'public'} Cut %s*) - / ({'protected'} Cut %s*) - / ({'private'} Cut %s*) - / {} -> 'public' - -EmmyGeneric <- EmmyGenericBlock - (%s* ',' %s* EmmyGenericBlock)* -EmmyGenericBlock<- (MustEmmyName %s* (':' %s* EmmyType)?) - -> EmmyGenericBlock - -EmmyVararg <- EmmyType - -EmmyLanguage <- MustEmmyName - -EmmyArrayType <- ({} MustEmmyName -> EmmyCommonType {} '[' DirtyBR) - -> EmmyArrayType - / ({} PL EmmyCommonType DirtyPR '[' DirtyBR) - -> EmmyArrayType - -EmmyTableType <- ({} 'table' Cut '<' %s* EmmyType %s* ',' %s* EmmyType %s* '>' {}) - -> EmmyTableType - -EmmyFunctionType<- ({} 'fun' Cut %s* EmmyFunctionArgs %s* EmmyFunctionRtns {}) - -> EmmyFunctionType -EmmyFunctionArgs<- ('(' %s* EmmyFunctionArg %s* (',' %s* EmmyFunctionArg %s*)* DirtyPR) - -> EmmyFunctionArgs - / '(' %nil DirtyPR -> None - / %nil -EmmyFunctionRtns<- (':' %s* EmmyType (%s* ',' %s* EmmyType)*) - -> EmmyFunctionRtns - / %nil -EmmyFunctionArg <- MustEmmyName %s* ':' %s* EmmyType - -EmmySee <- {} MustEmmyName %s* '#' %s* MustEmmyName {} -EmmyOverLoad <- EmmyFunctionType -]] - -local ast = { - EmmyLua = function (start, emmy, finish) - emmy.start = start - emmy.finish = finish - 1 - State.emmy[#State.emmy+1] = emmy - end, - EmmyName = function (start, str) - return { - type = 'name', - start = start, - finish = start + #str - 1, - [1] = str, - } - end, - DirtyEmmyName = function (pos) - pushError { - type = 'MISS_NAME', - level = 'warning', - start = pos, - finish = pos, - } - return { - type = 'emmyName', - start = pos-1, - finish = pos-1, - [1] = '' - } - end, - EmmyClass = function (class, startPos, extends) - if extends and extends[1] == '' then - extends.start = startPos - end - return { - type = 'class', - class = class, - extends = extends, - } - end, - EmmyType = function (types, enums) - local result = { - type = 'type', - types = types, - enums = enums, - } - return result - end, - EmmyCommonType = function (name) - return { - type = 'common', - start = name.start, - finish = name.finish, - name = name, - } - end, - EmmyArrayType = function (start, emmy, _, finish) - emmy.type = 'emmyArrayType' - emmy.start = start - emmy.finish = finish - 1 - return emmy - end, - EmmyTableType = function (start, keyType, valueType, finish) - return { - type = 'emmyTableType', - start = start, - finish = finish - 1, - [1] = keyType, - [2] = valueType, - } - end, - EmmyFunctionType = function (start, args, returns, finish) - local result = { - start = start, - finish = finish - 1, - type = 'emmyFunctionType', - args = args, - returns = returns, - } - return result - end, - EmmyFunctionRtns = function (...) - return {...} - end, - EmmyFunctionArgs = function (...) - local args = {...} - args[#args] = nil - return args - end, - EmmyAlias = function (name, emmyName, ...) - return { - type = 'emmyAlias', - start = name.start, - finish = emmyName.finish, - name, - emmyName, - ... - } - end, - EmmyParam = function (argName, emmyName, option, ...) - local emmy = { - type = 'emmyParam', - option = option, - argName, - emmyName, - ... - } - emmy.start = emmy[1].start - emmy.finish = emmy[#emmy].finish - return emmy - end, - EmmyReturn = function (start, type, finish, option) - local emmy = { - type = 'emmyReturn', - option = option, - start = start, - finish = finish - 1, - [1] = type, - } - return emmy - end, - EmmyField = function (access, fieldName, ...) - local obj = { - type = 'emmyField', - access, fieldName, - ... - } - obj.start = obj[2].start - obj.finish = obj[3].finish - return obj - end, - EmmyGenericBlock = function (genericName, parentName) - return { - start = genericName.start, - finish = parentName and parentName.finish or genericName.finish, - genericName, - parentName, - } - end, - EmmyGeneric = function (...) - local emmy = { - type = 'emmyGeneric', - ... - } - emmy.start = emmy[1].start - emmy.finish = emmy[#emmy].finish - return emmy - end, - EmmyVararg = function (typeName) - return { - type = 'emmyVararg', - start = typeName.start, - finish = typeName.finish, - typeName, - } - end, - EmmyLanguage = function (language) - return { - type = 'emmyLanguage', - start = language.start, - finish = language.finish, - language, - } - end, - EmmySee = function (start, className, methodName, finish) - return { - type = 'emmySee', - start = start, - finish = finish - 1, - className, methodName - } - end, - EmmyOverLoad = function (EmmyFunctionType) - EmmyFunctionType.type = 'emmyOverLoad' - return EmmyFunctionType - end, - EmmyIncomplete = function (emmyName) - emmyName.type = 'emmyIncomplete' - return emmyName - end, - EmmyComment = function (...) - return { - type = 'emmyComment', - [1] = table.concat({...}), - } - end, - EmmyOption = function (options) - if not options or options == '' then - return nil - end - local option = {} - for _, pair in ipairs(options) do - if pair.type == 'pair' then - local key = pair[1] - local value = pair[2] - if key.type == 'name' then - option[key[1]] = value[1] - end - end - end - return option - end, - EmmyTypeEnum = function (default, enum, comment) - enum.type = 'enum' - if default ~= '' then - enum.default = true - end - enum.comment = comment - return enum - end, -} - -local function init(state) - State = state - pushError = state.pushError -end - -return { - grammar = grammar, - ast = ast, - init = init, -} diff --git a/server-beta/src/parser/grammar.lua b/server-beta/src/parser/grammar.lua deleted file mode 100644 index fd699bd4..00000000 --- a/server-beta/src/parser/grammar.lua +++ /dev/null @@ -1,537 +0,0 @@ -local re = require 'parser.relabel' -local m = require 'lpeglabel' -local emmy = require 'parser.emmy' -local ast = require 'parser.ast' - -local scriptBuf = '' -local compiled = {} -local defs = ast.defs - --- goto 可以作为名字,合法性之后处理 -local RESERVED = { - ['and'] = true, - ['break'] = true, - ['do'] = true, - ['else'] = true, - ['elseif'] = true, - ['end'] = true, - ['false'] = true, - ['for'] = true, - ['function'] = true, - ['if'] = true, - ['in'] = true, - ['local'] = true, - ['nil'] = true, - ['not'] = true, - ['or'] = true, - ['repeat'] = true, - ['return'] = true, - ['then'] = true, - ['true'] = true, - ['until'] = true, - ['while'] = true, -} - -defs.nl = (m.P'\r\n' + m.S'\r\n') -defs.s = m.S' \t' -defs.S = - defs.s -defs.ea = '\a' -defs.eb = '\b' -defs.ef = '\f' -defs.en = '\n' -defs.er = '\r' -defs.et = '\t' -defs.ev = '\v' -defs['nil'] = m.Cp() / function () return nil end -defs['false'] = m.Cp() / function () return false end -defs.NotReserved = function (_, _, str) - if RESERVED[str] then - return false - end - return true -end -defs.Reserved = function (_, _, str) - if RESERVED[str] then - return true - end - return false -end -defs.None = function () end -defs.np = m.Cp() / function (n) return n+1 end - -m.setmaxstack(1000) - -local eof = re.compile '!. / %{SYNTAX_ERROR}' - -local function grammar(tag) - return function (script) - scriptBuf = script .. '\r\n' .. scriptBuf - compiled[tag] = re.compile(scriptBuf, defs) * eof - end -end - -local function errorpos(pos, err) - return { - type = 'UNKNOWN', - start = pos or 0, - finish = pos or 0, - err = err, - } -end - -grammar 'Comment' [[ -Comment <- LongComment - / '--' ShortComment -LongComment <- ('--[' {} {:eq: '='* :} {} '[' - {(!CommentClose .)*} - (CommentClose / {})) - -> LongComment - / ( - {} '/*' {} - (!'*/' .)* - {} '*/' {} - ) - -> CLongComment -CommentClose <- ']' =eq ']' -ShortComment <- (!%nl .)* -]] - -grammar 'Sp' [[ -Sp <- (EmmyLua / Comment / %nl / %s)* -Sps <- (EmmyLua / Comment / %nl / %s)+ - --- 占位 -EmmyLua <- !. . -]] - -grammar 'Common' [[ -Word <- [a-zA-Z0-9_] -Cut <- !Word -X16 <- [a-fA-F0-9] -Rest <- (!%nl .)* - -AND <- Sp {'and'} Cut -BREAK <- Sp 'break' Cut -FALSE <- Sp 'false' Cut -GOTO <- Sp 'goto' Cut -LOCAL <- Sp 'local' Cut -NIL <- Sp 'nil' Cut -NOT <- Sp 'not' Cut -OR <- Sp {'or'} Cut -RETURN <- Sp 'return' Cut -TRUE <- Sp 'true' Cut - -DO <- Sp {} 'do' {} Cut - / Sp({} 'then' {} Cut) -> ErrDo -IF <- Sp {} 'if' {} Cut -ELSE <- Sp {} 'else' {} Cut -ELSEIF <- Sp {} 'elseif' {} Cut -END <- Sp {} 'end' {} Cut -FOR <- Sp {} 'for' {} Cut -FUNCTION <- Sp {} 'function' {} Cut -IN <- Sp {} 'in' {} Cut -REPEAT <- Sp {} 'repeat' {} Cut -THEN <- Sp {} 'then' {} Cut - / Sp({} 'do' {} Cut) -> ErrThen -UNTIL <- Sp {} 'until' {} Cut -WHILE <- Sp {} 'while' {} Cut - - -Esc <- '\' -> '' - EChar -EChar <- 'a' -> ea - / 'b' -> eb - / 'f' -> ef - / 'n' -> en - / 'r' -> er - / 't' -> et - / 'v' -> ev - / '\' - / '"' - / "'" - / %nl - / ('z' (%nl / %s)*) -> '' - / ({} 'x' {X16 X16}) -> Char16 - / ([0-9] [0-9]? [0-9]?) -> Char10 - / ('u{' {} {Word*} '}') -> CharUtf8 - -- 错误处理 - / 'x' {} -> MissEscX - / 'u' !'{' {} -> MissTL - / 'u{' Word* !'}' {} -> MissTR - / {} -> ErrEsc - -BOR <- Sp {'|'} -BXOR <- Sp {'~'} !'=' -BAND <- Sp {'&'} -Bshift <- Sp {BshiftList} -BshiftList <- '<<' - / '>>' -Concat <- Sp {'..'} -Adds <- Sp {AddsList} -AddsList <- '+' - / '-' -Muls <- Sp {MulsList} -MulsList <- '*' - / '//' - / '/' - / '%' -Unary <- Sp {} {UnaryList} -UnaryList <- NOT - / '#' - / '-' - / '~' !'=' -POWER <- Sp {'^'} - -BinaryOp <-( Sp {} {'or'} Cut - / Sp {} {'and'} Cut - / Sp {} {'<=' / '>=' / '<'!'<' / '>'!'>' / '~=' / '=='} - / Sp {} ({} '=' {}) -> ErrEQ - / Sp {} ({} '!=' {}) -> ErrUEQ - / Sp {} {'|'} - / Sp {} {'~'} - / Sp {} {'&'} - / Sp {} {'<<' / '>>'} - / Sp {} {'..'} !'.' - / Sp {} {'+' / '-'} - / Sp {} {'*' / '//' / '/' / '%'} - / Sp {} {'^'} - )-> BinaryOp -UnaryOp <-( Sp {} {'not' Cut / '#' / '~' !'=' / '-' !'-'} - )-> UnaryOp - -PL <- Sp '(' -PR <- Sp ')' -BL <- Sp '[' !'[' !'=' -BR <- Sp ']' -TL <- Sp '{' -TR <- Sp '}' -COMMA <- Sp ({} ',') - -> COMMA -SEMICOLON <- Sp ({} ';') - -> SEMICOLON -DOTS <- Sp ({} '...') - -> DOTS -DOT <- Sp ({} '.' !'.') - -> DOT -COLON <- Sp ({} ':' !':') - -> COLON -LABEL <- Sp '::' -ASSIGN <- Sp '=' !'=' -AssignOrEQ <- Sp ({} '==' {}) - -> ErrAssign - / Sp '=' - -DirtyBR <- BR / {} -> MissBR -DirtyTR <- TR / {} -> MissTR -DirtyPR <- PR / {} -> MissPR -DirtyLabel <- LABEL / {} -> MissLabel -NeedEnd <- END / {} -> MissEnd -NeedDo <- DO / {} -> MissDo -NeedAssign <- ASSIGN / {} -> MissAssign -NeedComma <- COMMA / {} -> MissComma -NeedIn <- IN / {} -> MissIn -NeedUntil <- UNTIL / {} -> MissUntil -NeedThen <- THEN / {} -> MissThen -]] - -grammar 'Nil' [[ -Nil <- Sp ({} -> Nil) NIL -]] - -grammar 'Boolean' [[ -Boolean <- Sp ({} -> True) TRUE - / Sp ({} -> False) FALSE -]] - -grammar 'String' [[ -String <- Sp ({} StringDef {}) - -> String -StringDef <- {'"'} - {~(Esc / !%nl !'"' .)*~} -> 1 - ('"' / {} -> MissQuote1) - / {"'"} - {~(Esc / !%nl !"'" .)*~} -> 1 - ("'" / {} -> MissQuote2) - / ('[' {} {:eq: '='* :} {} '[' %nl? - {(!StringClose .)*} -> 1 - (StringClose / {})) - -> LongString -StringClose <- ']' =eq ']' -]] - -grammar 'Number' [[ -Number <- Sp ({} {NumberDef} {}) -> Number - NumberSuffix? - ErrNumber? -NumberDef <- Number16 / Number10 -NumberSuffix<- ({} {[uU]? [lL] [lL]}) -> FFINumber - / ({} {[iI]}) -> ImaginaryNumber -ErrNumber <- ({} {([0-9a-zA-Z] / '.')+}) -> UnknownSymbol - -Number10 <- Float10 Float10Exp? - / Integer10 Float10? Float10Exp? -Integer10 <- [0-9]+ ('.' [0-9]*)? -Float10 <- '.' [0-9]+ -Float10Exp <- [eE] [+-]? [0-9]+ - / ({} [eE] [+-]? {}) -> MissExponent - -Number16 <- '0' [xX] Float16 Float16Exp? - / '0' [xX] Integer16 Float16? Float16Exp? -Integer16 <- X16+ ('.' X16*)? - / ({} {Word*}) -> MustX16 -Float16 <- '.' X16+ - / '.' ({} {Word*}) -> MustX16 -Float16Exp <- [pP] [+-]? [0-9]+ - / ({} [pP] [+-]? {}) -> MissExponent -]] - -grammar 'Name' [[ -Name <- Sp ({} NameBody {}) - -> Name -NameBody <- {[a-zA-Z_] [a-zA-Z0-9_]*} -FreeName <- Sp ({} {NameBody=>NotReserved} {}) - -> Name -KeyWord <- Sp NameBody=>Reserved -MustName <- Name / DirtyName -DirtyName <- {} -> DirtyName -]] - -grammar 'Exp' [[ -Exp <- (UnUnit BinUnit*) - -> Binary -BinUnit <- (BinaryOp UnUnit?) - -> SubBinary -UnUnit <- ExpUnit - / (UnaryOp+ (ExpUnit / MissExp)) - -> Unary -ExpUnit <- Nil - / Boolean - / String - / Number - / Dots - / Table - / Function - / Simple - -Simple <- {| Prefix (Sp Suffix)* |} - -> Simple -Prefix <- Sp ({} PL DirtyExp DirtyPR {}) - -> Paren - / Single -Single <- FreeName - -> Single -Suffix <- SuffixWithoutCall - / ({} PL SuffixCall DirtyPR {}) - -> Call -SuffixCall <- Sp ({} {| (COMMA / Exp)+ |} {}) - -> PackExpList - / %nil -SuffixWithoutCall - <- (DOT (Name / MissField)) - -> GetField - / ({} BL DirtyExp DirtyBR {}) - -> GetIndex - / (COLON (Name / MissMethod) NeedCall) - -> GetMethod - / ({} {| Table |} {}) - -> Call - / ({} {| String |} {}) - -> Call -NeedCall <- (!(Sp CallStart) {} -> MissPL)? -MissField <- {} -> MissField -MissMethod <- {} -> MissMethod -CallStart <- PL - / TL - / '"' - / "'" - / '[' '='* '[' - -DirtyExp <- Exp - / {} -> DirtyExp -MaybeExp <- Exp / MissExp -MissExp <- {} -> MissExp -ExpList <- Sp {| MaybeExp (Sp ',' MaybeExp)* |} - -Dots <- DOTS - -> VarArgs - -Table <- Sp ({} TL {| TableField* |} DirtyTR {}) - -> Table -TableField <- COMMA - / SEMICOLON - / NewIndex - / NewField - / Exp -Index <- BL DirtyExp DirtyBR -NewIndex <- Sp ({} Index NeedAssign DirtyExp {}) - -> NewIndex -NewField <- Sp ({} MustName ASSIGN DirtyExp {}) - -> NewField - -Function <- FunctionBody - -> Function -FuncArgs <- Sp ({} PL {| FuncArg+ |} DirtyPR {}) - -> FuncArgs - / PL DirtyPR %nil - / {} -> MissPL DirtyPR %nil -FuncArg <- DOTS - / Name - / COMMA -FunctionBody<- FUNCTION FuncArgs - {| (!END Action)* |} - NeedEnd - --- 纯占位,修改了 `relabel.lua` 使重复定义不抛错 -Action <- !END . -]] - -grammar 'Action' [[ -Action <- Sp (CrtAction / UnkAction) -CrtAction <- Semicolon - / Do - / Break - / Return - / Label - / GoTo - / If - / For - / While - / Repeat - / NamedFunction - / LocalFunction - / Local - / Set - / Call - / ExpInAction -UnkAction <- ({} {Word+}) - -> UnknownAction - / ({} '//' {} (LongComment / ShortComment)) - -> CCommentPrefix - / ({} {. (!Sps !CrtAction .)*}) - -> UnknownAction -ExpInAction <- Sp ({} Exp {}) - -> ExpInAction - -Semicolon <- Sp ';' -SimpleList <- {| Simple (Sp ',' Simple)* |} - -Do <- Sp ({} - 'do' Cut - {| (!END Action)* |} - NeedEnd) - -> Do - -Break <- Sp ({} BREAK {}) - -> Break - -Return <- Sp ({} RETURN ReturnExpList {}) - -> Return -ReturnExpList - <- Sp {| Exp (Sp ',' MaybeExp)* |} - / Sp {| !Exp !',' |} - / ExpList - -Label <- Sp ({} LABEL MustName DirtyLabel {}) - -> Label - -GoTo <- Sp ({} GOTO MustName {}) - -> GoTo - -If <- Sp ({} {| IfHead IfBody* |} NeedEnd) - -> If - -IfHead <- Sp (IfPart {}) -> IfBlock - / Sp (ElseIfPart {}) -> ElseIfBlock - / Sp (ElsePart {}) -> ElseBlock -IfBody <- Sp (ElseIfPart {}) -> ElseIfBlock - / Sp (ElsePart {}) -> ElseBlock -IfPart <- IF DirtyExp NeedThen - {| (!ELSEIF !ELSE !END Action)* |} -ElseIfPart <- ELSEIF DirtyExp NeedThen - {| (!ELSEIF !ELSE !END Action)* |} -ElsePart <- ELSE - {| (!ELSEIF !ELSE !END Action)* |} - -For <- Loop / In - -Loop <- LoopBody - -> Loop -LoopBody <- FOR LoopArgs NeedDo - {} {| (!END Action)* |} - NeedEnd -LoopArgs <- MustName AssignOrEQ - ({} {| (COMMA / !DO !END Exp)* |} {}) - -> PackLoopArgs - -In <- InBody - -> In -InBody <- FOR InNameList NeedIn InExpList NeedDo - {} {| (!END Action)* |} - NeedEnd -InNameList <- ({} {| (COMMA / !IN !DO !END Name)* |} {}) - -> PackInNameList -InExpList <- ({} {| (COMMA / !DO !DO !END Exp)* |} {}) - -> PackInExpList - -While <- WhileBody - -> While -WhileBody <- WHILE DirtyExp NeedDo - {| (!END Action)* |} - NeedEnd - -Repeat <- (RepeatBody {}) - -> Repeat -RepeatBody <- REPEAT - {| (!UNTIL Action)* |} - NeedUntil DirtyExp - -LocalAttr <- {| (Sp '<' Sp MustName Sp LocalAttrEnd)+ |} - -> LocalAttr -LocalAttrEnd<- '>' / {} -> MissGT -Local <- Sp ({} LOCAL LocalNameList ((AssignOrEQ ExpList) / %nil) {}) - -> Local -Set <- Sp ({} SimpleList AssignOrEQ ExpList {}) - -> Set -LocalNameList - <- {| LocalName (Sp ',' LocalName)* |} -LocalName <- (MustName LocalAttr?) - -> LocalName - -Call <- Simple - -> SimpleCall - -LocalFunction - <- Sp ({} LOCAL FunctionNamedBody) - -> LocalFunction - -NamedFunction - <- FunctionNamedBody - -> NamedFunction -FunctionNamedBody - <- FUNCTION FuncName FuncArgs - {| (!END Action)* |} - NeedEnd -FuncName <- {| Single (Sp SuffixWithoutCall)* |} - -> Simple - / {} -> MissName %nil -]] - ---grammar 'EmmyLua' (emmy.grammar) - -grammar 'Lua' [[ -Lua <- Head? - ({} {| Action* |} {}) -> Lua - Sp -Head <- '#' (!%nl .)* -]] - -return function (self, lua, mode) - local gram = compiled[mode] or compiled['Lua'] - local r, _, pos = gram:match(lua) - if not r then - local err = errorpos(pos) - return nil, err - end - - return r -end diff --git a/server-beta/src/parser/guide.lua b/server-beta/src/parser/guide.lua deleted file mode 100644 index af511555..00000000 --- a/server-beta/src/parser/guide.lua +++ /dev/null @@ -1,621 +0,0 @@ -local error = error -local type = type -local next = next -local tostring = tostring - -_ENV = nil - -local m = {} - -local blockTypes = { - ['while'] = true, - ['in'] = true, - ['loop'] = true, - ['repeat'] = true, - ['do'] = true, - ['function'] = true, - ['ifblock'] = true, - ['elseblock'] = true, - ['elseifblock'] = true, - ['main'] = true, -} - -local breakBlockTypes = { - ['while'] = true, - ['in'] = true, - ['loop'] = true, - ['repeat'] = true, -} - -m.childMap = { - ['main'] = {'#'}, - ['repeat'] = {'#', 'filter'}, - ['while'] = {'filter', '#'}, - ['in'] = {'keys', '#'}, - ['loop'] = {'loc', 'max', 'step', '#'}, - ['if'] = {'#'}, - ['ifblock'] = {'filter', '#'}, - ['elseifblock'] = {'filter', '#'}, - ['elseblock'] = {'#'}, - ['setfield'] = {'node', 'field', 'value'}, - ['setglobal'] = {'value'}, - ['local'] = {'attrs', 'value'}, - ['setlocal'] = {'value'}, - ['return'] = {'#'}, - ['do'] = {'#'}, - ['select'] = {'vararg'}, - ['table'] = {'#'}, - ['tableindex'] = {'index', 'value'}, - ['tablefield'] = {'field', 'value'}, - ['function'] = {'args', '#'}, - ['funcargs'] = {'#'}, - ['setmethod'] = {'node', 'method', 'value'}, - ['getmethod'] = {'node', 'method'}, - ['setindex'] = {'node', 'index', 'value'}, - ['getindex'] = {'node', 'index'}, - ['paren'] = {'exp'}, - ['call'] = {'node', 'args'}, - ['callargs'] = {'#'}, - ['getfield'] = {'node', 'field'}, - ['list'] = {'#'}, - ['binary'] = {1, 2}, - ['unary'] = {1} -} - -m.actionMap = { - ['main'] = {'#'}, - ['repeat'] = {'#'}, - ['while'] = {'#'}, - ['in'] = {'#'}, - ['loop'] = {'#'}, - ['if'] = {'#'}, - ['ifblock'] = {'#'}, - ['elseifblock'] = {'#'}, - ['elseblock'] = {'#'}, - ['do'] = {'#'}, - ['function'] = {'#'}, - ['funcargs'] = {'#'}, -} - ---- 是否是字面量 -function m.isLiteral(obj) - local tp = obj.type - return tp == 'nil' - or tp == 'boolean' - or tp == 'string' - or tp == 'number' - or tp == 'table' -end - ---- 获取字面量 -function m.getLiteral(obj) - local tp = obj.type - if tp == 'boolean' then - return obj[1] - elseif tp == 'string' then - return obj[1] - elseif tp == 'number' then - return obj[1] - end - return nil -end - ---- 寻找父函数 -function m.getParentFunction(obj) - for _ = 1, 1000 do - obj = obj.parent - if not obj then - break - end - local tp = obj.type - if tp == 'function' or tp == 'main' then - return obj - end - end - return nil -end - ---- 寻找所在区块 -function m.getBlock(obj) - for _ = 1, 1000 do - if not obj then - return nil - end - local tp = obj.type - if blockTypes[tp] then - return obj - end - obj = obj.parent - end - error('guide.getBlock overstack') -end - ---- 寻找所在父区块 -function m.getParentBlock(obj) - for _ = 1, 1000 do - obj = obj.parent - if not obj then - return nil - end - local tp = obj.type - if blockTypes[tp] then - return obj - end - end - error('guide.getParentBlock overstack') -end - ---- 寻找所在可break的父区块 -function m.getBreakBlock(obj) - for _ = 1, 1000 do - obj = obj.parent - if not obj then - return nil - end - local tp = obj.type - if breakBlockTypes[tp] then - return obj - end - if tp == 'function' then - return nil - end - end - error('guide.getBreakBlock overstack') -end - ---- 寻找根区块 -function m.getRoot(obj) - for _ = 1, 1000 do - local parent = obj.parent - if not parent then - return obj - end - obj = parent - end - error('guide.getRoot overstack') -end - ---- 寻找函数的不定参数,返回不定参在第几个参数上,以及该参数对象。 ---- 如果函数是主函数,则返回`0, nil`。 ----@return table ----@return integer -function m.getFunctionVarArgs(func) - if func.type == 'main' then - return 0, nil - end - if func.type ~= 'function' then - return nil, nil - end - local args = func.args - if not args then - return nil, nil - end - for i = 1, #args do - local arg = args[i] - if arg.type == '...' then - return i, arg - end - end - return nil, nil -end - ---- 获取指定区块中可见的局部变量 ----@param block table ----@param name string {comment = '变量名'} ----@param pos integer {comment = '可见位置'} -function m.getLocal(block, name, pos) - block = m.getBlock(block) - for _ = 1, 1000 do - if not block then - return nil - end - local locals = block.locals - local res - if not locals then - goto CONTINUE - end - for i = 1, #locals do - local loc = locals[i] - if loc.effect > pos then - break - end - if loc[1] == name then - if not res or res.effect < loc.effect then - res = loc - end - end - end - if res then - return res, res - end - ::CONTINUE:: - block = m.getParentBlock(block) - end - error('guide.getLocal overstack') -end - ---- 获取指定区块中可见的标签 ----@param block table ----@param name string {comment = '标签名'} -function m.getLabel(block, name) - block = m.getBlock(block) - for _ = 1, 1000 do - if not block then - return nil - end - local labels = block.labels - if labels then - local label = labels[name] - if label then - return label - end - end - if block.type == 'function' then - return nil - end - block = m.getParentBlock(block) - end - error('guide.getLocal overstack') -end - ---- 判断source是否包含offset -function m.isContain(source, offset) - return source.start <= offset and source.finish >= offset - 1 -end - ---- 判断offset在source的影响范围内 ---- ---- 主要针对赋值等语句时,key包含value -function m.isInRange(source, offset) - return (source.vstart or source.start) <= offset and (source.range or source.finish) >= offset - 1 -end - ---- 添加child -function m.addChilds(list, obj, map) - local keys = map[obj.type] - if keys then - for i = 1, #keys do - local key = keys[i] - if key == '#' then - for i = 1, #obj do - list[#list+1] = obj[i] - end - else - list[#list+1] = obj[key] - end - end - end -end - ---- 遍历所有包含offset的source -function m.eachSourceContain(ast, offset, callback) - local list = { ast } - while true do - local len = #list - if len == 0 then - return - end - local obj = list[len] - list[len] = nil - if m.isInRange(obj, offset) then - if m.isContain(obj, offset) then - local res = callback(obj) - if res ~= nil then - return res - end - end - m.addChilds(list, obj, m.childMap) - end - end -end - ---- 遍历所有指定类型的source -function m.eachSourceType(ast, type, callback) - local cache = ast.typeCache - if not cache then - local mark = {} - cache = {} - ast.typeCache = cache - m.eachSource(ast, function (source) - if mark[source] then - return - end - mark[source] = true - local tp = source.type - if not tp then - return - end - local myCache = cache[tp] - if not myCache then - myCache = {} - cache[tp] = myCache - end - myCache[#myCache+1] = source - end) - end - local myCache = cache[type] - if not myCache then - return - end - for i = 1, #myCache do - callback(myCache[i]) - end -end - ---- 遍历所有的source -function m.eachSource(ast, callback) - local list = { ast } - while true do - local len = #list - if len == 0 then - return - end - local obj = list[len] - list[len] = nil - callback(obj) - m.addChilds(list, obj, m.childMap) - end -end - ---- 获取指定的 special -function m.eachSpecialOf(ast, name, callback) - local root = m.getRoot(ast) - if not root.specials then - return - end - local specials = root.specials[name] - if not specials then - return - end - for i = 1, #specials do - callback(specials[i]) - end -end - ---- 获取偏移对应的坐标 ----@param lines table ----@return integer {name = 'row'} ----@return integer {name = 'col'} -function m.positionOf(lines, offset) - if offset < 1 then - return 0, 0 - end - local lastLine = lines[#lines] - if offset > lastLine.finish then - return #lines, lastLine.finish - lastLine.start + 1 - end - local min = 1 - local max = #lines - for _ = 1, 100 do - if max <= min then - local line = lines[min] - return min, offset - line.start + 1 - end - local row = (max - min) // 2 + min - local line = lines[row] - if offset < line.start then - max = row - 1 - elseif offset > line.finish then - min = row + 1 - else - return row, offset - line.start + 1 - end - end - error('Stack overflow!') -end - ---- 获取坐标对应的偏移 ----@param lines table ----@param row integer ----@param col integer ----@return integer {name = 'offset'} -function m.offsetOf(lines, row, col) - if row < 1 then - return 0 - end - if row > #lines then - local lastLine = lines[#lines] - return lastLine.finish - end - local line = lines[row] - local len = line.finish - line.start + 1 - if col < 0 then - return line.start - elseif col > len then - return line.finish - else - return line.start + col - 1 - end -end - -function m.lineContent(lines, text, row) - local line = lines[row] - if not line then - return '' - end - return text:sub(line.start, line.finish) -end - -function m.lineRange(lines, row) - local line = lines[row] - if not line then - return 0, 0 - end - return line.start, line.finish -end - -function m.getName(obj) - local tp = obj.type - if tp == 'getglobal' - or tp == 'setglobal' then - return obj[1] - elseif tp == 'local' - or tp == 'getlocal' - or tp == 'setlocal' then - return obj[1] - elseif tp == 'getfield' - or tp == 'setfield' - or tp == 'tablefield' then - return obj.field[1] - elseif tp == 'getmethod' - or tp == 'setmethod' then - return obj.method[1] - elseif tp == 'getindex' - or tp == 'setindex' - or tp == 'tableindex' then - return m.getName(obj.index) - elseif tp == 'field' - or tp == 'method' then - return obj[1] - elseif tp == 'index' then - return m.getName(obj.index) - elseif tp == 'string' then - return obj[1] - end - return nil -end - -function m.getKeyName(obj) - local tp = obj.type - if tp == 'getglobal' - or tp == 'setglobal' then - return 's|' .. obj[1] - elseif tp == 'getfield' - or tp == 'setfield' - or tp == 'tablefield' then - if obj.field then - return 's|' .. obj.field[1] - end - elseif tp == 'getmethod' - or tp == 'setmethod' then - if obj.method then - return 's|' .. obj.method[1] - end - elseif tp == 'getindex' - or tp == 'setindex' - or tp == 'tableindex' then - if obj.index then - return m.getKeyName(obj.index) - end - elseif tp == 'field' - or tp == 'method' then - return 's|' .. obj[1] - elseif tp == 'string' then - local s = obj[1] - if s then - return 's|' .. s - else - return s - end - elseif tp == 'number' then - local n = obj[1] - if n then - return ('n|%q'):format(obj[1]) - else - return 'n' - end - elseif tp == 'boolean' then - local b = obj[1] - if b then - return 'b|' .. tostring(b) - else - return 'b' - end - end - return nil -end - -function m.getENV(ast) - if ast.type ~= 'main' then - return nil - end - return ast.locals[1] -end - ---- 测试 a 到 b 的路径(不经过函数,不考虑 goto), ---- 每个路径是一个 block 。 ---- ---- 如果 a 在 b 的前面,返回 `"before"` 加上 2个`list<block>` ---- ---- 如果 a 在 b 的后面,返回 `"after"` 加上 2个`list<block>` ---- ---- 否则返回 `false` ---- ---- 返回的2个 `list` 分别为基准block到达 a 与 b 的路径。 ----@param a table ----@param b table ----@return string|boolean mode ----@return table|nil pathA ----@return table|nil pathB -function m.getPath(a, b) - --- 首先测试双方在同一个函数内 - if m.getParentFunction(a) ~= m.getParentFunction(b) then - return false - end - local mode - local objA - local objB - if a.finish < b.start then - mode = 'before' - objA = a - objB = b - elseif a.start > b.finish then - mode = 'after' - objA = b - objB = a - else - return 'equal', {}, {} - end - local pathA = {} - local pathB = {} - for _ = 1, 1000 do - objA = m.getParentBlock(objA) - pathA[#pathA+1] = objA - if objA.type == 'function' or objA.type == 'main' then - break - end - end - for _ = 1, 1000 do - objB = m.getParentBlock(objB) - pathB[#pathB+1] = objB - if objB.type == 'function' or objB.type == 'main' then - break - end - end - -- pathA: {1, 2, 3, 4, 5} - -- pathB: {5, 6, 2, 3} - local top = #pathB - local start - for i = #pathA, 1, -1 do - local currentBlock = pathA[i] - if currentBlock == pathB[top] then - start = i - break - end - end - -- pathA: { 1, 2, 3} - -- pathB: {5, 6, 2, 3} - local extra = 0 - local align = top - start - for i = start, 1, -1 do - local currentA = pathA[i] - local currentB = pathB[i+align] - if currentA ~= currentB then - extra = i - break - end - end - -- pathA: {1} - local resultA = {} - for i = extra, 1, -1 do - resultA[#resultA+1] = pathA[i] - end - -- pathB: {5, 6} - local resultB = {} - for i = extra + align, 1, -1 do - resultB[#resultB+1] = pathB[i] - end - return mode, resultA, resultB -end - -return m diff --git a/server-beta/src/parser/init.lua b/server-beta/src/parser/init.lua deleted file mode 100644 index 5eeb0da2..00000000 --- a/server-beta/src/parser/init.lua +++ /dev/null @@ -1,11 +0,0 @@ -local api = { - grammar = require 'parser.grammar', - parse = require 'parser.parse', - compile = require 'parser.compile', - split = require 'parser.split', - calcline = require 'parser.calcline', - lines = require 'parser.lines', - guide = require 'parser.guide', -} - -return api diff --git a/server-beta/src/parser/lines.lua b/server-beta/src/parser/lines.lua deleted file mode 100644 index c7961d13..00000000 --- a/server-beta/src/parser/lines.lua +++ /dev/null @@ -1,46 +0,0 @@ -local m = require 'lpeglabel' -local utf8Len = utf8.len - -_ENV = nil - -local function Line(start, line, range, finish) - line.start = start - line.finish = finish - 1 - line.range = range - 1 - return line -end - -local function Space(...) - local line = {...} - local sp = 0 - local tab = 0 - for i = 1, #line do - if line[i] == ' ' then - sp = sp + 1 - elseif line[i] == '\t' then - tab = tab + 1 - end - line[i] = nil - end - line.sp = sp - line.tab = tab - return line -end - -local parser = m.P{ -'Lines', -Lines = m.Ct(m.V'Line'^0 * m.V'LastLine'), -Line = m.Cp() * m.V'Indent' * (1 - m.V'Nl')^0 * m.Cp() * m.V'Nl' * m.Cp() / Line, -LastLine= m.Cp() * m.V'Indent' * (1 - m.V'Nl')^0 * m.Cp() * m.Cp() / Line, -Nl = m.P'\r\n' + m.S'\r\n', -Indent = m.C(m.S' \t')^0 / Space, -} - -return function (self, text) - local lines, err = parser:match(text) - if not lines then - return nil, err - end - - return lines -end diff --git a/server-beta/src/parser/parse.lua b/server-beta/src/parser/parse.lua deleted file mode 100644 index bbc01b10..00000000 --- a/server-beta/src/parser/parse.lua +++ /dev/null @@ -1,45 +0,0 @@ -local ast = require 'parser.ast' - -return function (self, lua, mode, version) - local errs = {} - local diags = {} - local state = { - version = version, - lua = lua, - emmy = {}, - root = {}, - errs = errs, - diags = diags, - pushError = function (err) - if err.finish < err.start then - err.finish = err.start - end - local last = errs[#errs] - if last then - if last.start <= err.start and last.finish >= err.finish then - return - end - end - err.level = err.level or 'error' - errs[#errs+1] = err - return err - end, - pushDiag = function (code, info) - if not diags[code] then - diags[code] = {} - end - diags[code][#diags[code]+1] = info - end - } - ast.init(state) - local suc, res, err = xpcall(self.grammar, debug.traceback, self, lua, mode) - ast.close() - if not suc then - return nil, res - end - if not res then - state.pushError(err) - end - state.ast = res - return state -end diff --git a/server-beta/src/parser/relabel.lua b/server-beta/src/parser/relabel.lua deleted file mode 100644 index ac902403..00000000 --- a/server-beta/src/parser/relabel.lua +++ /dev/null @@ -1,361 +0,0 @@ --- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $ - --- imported functions and modules -local tonumber, type, print, error = tonumber, type, print, error -local pcall = pcall -local setmetatable = setmetatable -local tinsert, concat = table.insert, table.concat -local rep = string.rep -local m = require"lpeglabel" - --- 'm' will be used to parse expressions, and 'mm' will be used to --- create expressions; that is, 're' runs on 'm', creating patterns --- on 'mm' -local mm = m - --- pattern's metatable -local mt = getmetatable(mm.P(0)) - - - --- No more global accesses after this point -_ENV = nil - - -local any = m.P(1) -local dummy = mm.P(false) - - -local errinfo = { - NoPatt = "no pattern found", - ExtraChars = "unexpected characters after the pattern", - - ExpPatt1 = "expected a pattern after '/'", - - ExpPatt2 = "expected a pattern after '&'", - ExpPatt3 = "expected a pattern after '!'", - - ExpPatt4 = "expected a pattern after '('", - ExpPatt5 = "expected a pattern after ':'", - ExpPatt6 = "expected a pattern after '{~'", - ExpPatt7 = "expected a pattern after '{|'", - - ExpPatt8 = "expected a pattern after '<-'", - - ExpPattOrClose = "expected a pattern or closing '}' after '{'", - - ExpNumName = "expected a number, '+', '-' or a name (no space) after '^'", - ExpCap = "expected a string, number, '{}' or name after '->'", - - ExpName1 = "expected the name of a rule after '=>'", - ExpName2 = "expected the name of a rule after '=' (no space)", - ExpName3 = "expected the name of a rule after '<' (no space)", - - ExpLab1 = "expected a label after '{'", - - ExpNameOrLab = "expected a name or label after '%' (no space)", - - ExpItem = "expected at least one item after '[' or '^'", - - MisClose1 = "missing closing ')'", - MisClose2 = "missing closing ':}'", - MisClose3 = "missing closing '~}'", - MisClose4 = "missing closing '|}'", - MisClose5 = "missing closing '}'", -- for the captures - - MisClose6 = "missing closing '>'", - MisClose7 = "missing closing '}'", -- for the labels - - MisClose8 = "missing closing ']'", - - MisTerm1 = "missing terminating single quote", - MisTerm2 = "missing terminating double quote", -} - -local function expect (pattern, label) - return pattern + m.T(label) -end - - --- Pre-defined names -local Predef = { nl = m.P"\n" } - - -local mem -local fmem -local gmem - - -local function updatelocale () - mm.locale(Predef) - Predef.a = Predef.alpha - Predef.c = Predef.cntrl - Predef.d = Predef.digit - Predef.g = Predef.graph - Predef.l = Predef.lower - Predef.p = Predef.punct - Predef.s = Predef.space - Predef.u = Predef.upper - Predef.w = Predef.alnum - Predef.x = Predef.xdigit - Predef.A = any - Predef.a - Predef.C = any - Predef.c - Predef.D = any - Predef.d - Predef.G = any - Predef.g - Predef.L = any - Predef.l - Predef.P = any - Predef.p - Predef.S = any - Predef.s - Predef.U = any - Predef.u - Predef.W = any - Predef.w - Predef.X = any - Predef.x - mem = {} -- restart memoization - fmem = {} - gmem = {} - local mt = {__mode = "v"} - setmetatable(mem, mt) - setmetatable(fmem, mt) - setmetatable(gmem, mt) -end - - -updatelocale() - - - -local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end) - - -local function getdef (id, defs) - local c = defs and defs[id] - if not c then - error("undefined name: " .. id) - end - return c -end - - -local function mult (p, n) - local np = mm.P(true) - while n >= 1 do - if n%2 >= 1 then np = np * p end - p = p * p - n = n/2 - end - return np -end - -local function equalcap (s, i, c) - if type(c) ~= "string" then return nil end - local e = #c + i - if s:sub(i, e - 1) == c then return e else return nil end -end - - -local S = (Predef.space + "--" * (any - Predef.nl)^0)^0 - -local name = m.C(m.R("AZ", "az", "__") * m.R("AZ", "az", "__", "09")^0) - -local arrow = S * "<-" - --- a defined name only have meaning in a given environment -local Def = name * m.Carg(1) - -local num = m.C(m.R"09"^1) * S / tonumber - -local String = "'" * m.C((any - "'" - m.P"\n")^0) * expect("'", "MisTerm1") - + '"' * m.C((any - '"' - m.P"\n")^0) * expect('"', "MisTerm2") - - -local defined = "%" * Def / function (c,Defs) - local cat = Defs and Defs[c] or Predef[c] - if not cat then - error("name '" .. c .. "' undefined") - end - return cat -end - -local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R - -local item = defined + Range + m.C(any - m.P"\n") - -local Class = - "[" - * (m.C(m.P"^"^-1)) -- optional complement symbol - * m.Cf(expect(item, "ExpItem") * (item - "]")^0, mt.__add) - / function (c, p) return c == "^" and any - p or p end - * expect("]", "MisClose8") - -local function adddef (t, k, exp) - if t[k] then - -- TODO 改了一下这里的代码,重复定义不会抛错 - --error("'"..k.."' already defined as a rule") - else - t[k] = exp - end - return t -end - -local function firstdef (n, r) return adddef({n}, n, r) end - - -local function NT (n, b) - if not b then - error("rule '"..n.."' used outside a grammar") - else return mm.V(n) - end -end - - -local exp = m.P{ "Exp", - Exp = S * ( m.V"Grammar" - + m.Cf(m.V"Seq" * (S * "/" * expect(S * m.V"Seq", "ExpPatt1"))^0, mt.__add) ); - Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix" * (S * m.V"Prefix")^0, mt.__mul); - Prefix = "&" * expect(S * m.V"Prefix", "ExpPatt2") / mt.__len - + "!" * expect(S * m.V"Prefix", "ExpPatt3") / mt.__unm - + m.V"Suffix"; - Suffix = m.Cf(m.V"Primary" * - ( S * ( m.P"+" * m.Cc(1, mt.__pow) - + m.P"*" * m.Cc(0, mt.__pow) - + m.P"?" * m.Cc(-1, mt.__pow) - + "^" * expect( m.Cg(num * m.Cc(mult)) - + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow) - + name * m.Cc"lab" - ), - "ExpNumName") - + "->" * expect(S * ( m.Cg((String + num) * m.Cc(mt.__div)) - + m.P"{}" * m.Cc(nil, m.Ct) - + m.Cg(Def / getdef * m.Cc(mt.__div)) - ), - "ExpCap") - + "=>" * expect(S * m.Cg(Def / getdef * m.Cc(m.Cmt)), - "ExpName1") - ) - )^0, function (a,b,f) if f == "lab" then return a + mm.T(b) else return f(a,b) end end ); - Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") - + String / mm.P - + Class - + defined - + "%" * expect(m.P"{", "ExpNameOrLab") - * expect(S * m.V"Label", "ExpLab1") - * expect(S * "}", "MisClose7") / mm.T - + "{:" * (name * ":" + m.Cc(nil)) * expect(m.V"Exp", "ExpPatt5") - * expect(S * ":}", "MisClose2") - / function (n, p) return mm.Cg(p, n) end - + "=" * expect(name, "ExpName2") - / function (n) return mm.Cmt(mm.Cb(n), equalcap) end - + m.P"{}" / mm.Cp - + "{~" * expect(m.V"Exp", "ExpPatt6") - * expect(S * "~}", "MisClose3") / mm.Cs - + "{|" * expect(m.V"Exp", "ExpPatt7") - * expect(S * "|}", "MisClose4") / mm.Ct - + "{" * expect(m.V"Exp", "ExpPattOrClose") - * expect(S * "}", "MisClose5") / mm.C - + m.P"." * m.Cc(any) - + (name * -arrow + "<" * expect(name, "ExpName3") - * expect(">", "MisClose6")) * m.Cb("G") / NT; - Label = num + name; - Definition = name * arrow * expect(m.V"Exp", "ExpPatt8"); - Grammar = m.Cg(m.Cc(true), "G") - * m.Cf(m.V"Definition" / firstdef * (S * m.Cg(m.V"Definition"))^0, - adddef) / mm.P; -} - -local pattern = S * m.Cg(m.Cc(false), "G") * expect(exp, "NoPatt") / mm.P - * S * expect(-any, "ExtraChars") - -local function lineno (s, i) - if i == 1 then return 1, 1 end - local adjustment = 0 - -- report the current line if at end of line, not the next - if s:sub(i,i) == '\n' then - i = i-1 - adjustment = 1 - end - local rest, num = s:sub(1,i):gsub("[^\n]*\n", "") - local r = #rest - return 1 + num, (r ~= 0 and r or 1) + adjustment -end - -local function calcline (s, i) - if i == 1 then return 1, 1 end - local rest, line = s:sub(1,i):gsub("[^\n]*\n", "") - local col = #rest - return 1 + line, col ~= 0 and col or 1 -end - - -local function splitlines(str) - local t = {} - local function helper(line) tinsert(t, line) return "" end - helper((str:gsub("(.-)\r?\n", helper))) - return t -end - -local function compile (p, defs) - if mm.type(p) == "pattern" then return p end -- already compiled - p = p .. " " -- for better reporting of column numbers in errors when at EOF - local ok, cp, label, poserr = pcall(function() return pattern:match(p, 1, defs) end) - if not ok and cp then - if type(cp) == "string" then - cp = cp:gsub("^[^:]+:[^:]+: ", "") - end - error(cp, 3) - end - if not cp then - local lines = splitlines(p) - local line, col = lineno(p, poserr) - local err = {} - tinsert(err, "L" .. line .. ":C" .. col .. ": " .. errinfo[label]) - tinsert(err, lines[line]) - tinsert(err, rep(" ", col-1) .. "^") - error("syntax error(s) in pattern\n" .. concat(err, "\n"), 3) - end - return cp -end - -local function match (s, p, i) - local cp = mem[p] - if not cp then - cp = compile(p) - mem[p] = cp - end - return cp:match(s, i or 1) -end - -local function find (s, p, i) - local cp = fmem[p] - if not cp then - cp = compile(p) / 0 - cp = mm.P{ mm.Cp() * cp * mm.Cp() + 1 * mm.V(1) } - fmem[p] = cp - end - local i, e = cp:match(s, i or 1) - if i then return i, e - 1 - else return i - end -end - -local function gsub (s, p, rep) - local g = gmem[p] or {} -- ensure gmem[p] is not collected while here - gmem[p] = g - local cp = g[rep] - if not cp then - cp = compile(p) - cp = mm.Cs((cp / rep + 1)^0) - g[rep] = cp - end - return cp:match(s) -end - - --- exported names -local re = { - compile = compile, - match = match, - find = find, - gsub = gsub, - updatelocale = updatelocale, - calcline = calcline -} - -return re diff --git a/server-beta/src/parser/split.lua b/server-beta/src/parser/split.lua deleted file mode 100644 index 6ce4a4e7..00000000 --- a/server-beta/src/parser/split.lua +++ /dev/null @@ -1,9 +0,0 @@ -local m = require 'lpeglabel' - -local NL = m.P'\r\n' + m.S'\r\n' -local LINE = m.C(1 - NL) - -return function (str) - local MATCH = m.Ct((LINE * NL)^0 * LINE) - return MATCH:match(str) -end |