diff options
Diffstat (limited to 'script/parser/ast.lua')
-rw-r--r-- | script/parser/ast.lua | 1997 |
1 files changed, 0 insertions, 1997 deletions
diff --git a/script/parser/ast.lua b/script/parser/ast.lua deleted file mode 100644 index 648a6890..00000000 --- a/script/parser/ast.lua +++ /dev/null @@ -1,1997 +0,0 @@ -local tonumber = tonumber -local stringChar = string.char -local utf8Char = utf8.char -local tableUnpack = table.unpack -local mathType = math.type -local tableRemove = table.remove -local tableSort = table.sort -local print = print -local tostring = tostring - -_ENV = nil - -local DefaultState = { - lua = '', - options = {}, -} - -local State = DefaultState -local PushError -local PushDiag -local PushComment - --- 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 SymbolAlias = { - ['||'] = 'or', - ['&&'] = 'and', - ['!='] = '~=', - ['!'] = 'not', -} - -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, - sindex = 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, - ShortComment = function (start, text, finish) - PushComment { - type = 'comment.short', - start = start, - finish = finish - 1, - text = text, - } - end, - LongComment = function (start, beforeEq, afterEq, str, close, finish) - PushComment { - type = 'comment.long', - start = start, - finish = finish - 1, - text = str, - } - if not close then - local endSymbol = ']' .. ('='):rep(afterEq-beforeEq) .. ']' - local s, _, w = str:find('(%][%=]*%])[%c%s]*$') - if s then - PushError { - type = 'ERR_LCOMMENT_END', - start = finish - #str + s - 1, - finish = finish - #str + s + #w - 2, - info = { - symbol = endSymbol, - }, - fix = { - title = 'FIX_LCOMMENT_END', - { - start = finish - #str + s - 1, - finish = finish - #str + s + #w - 2, - text = endSymbol, - } - }, - } - end - PushError { - type = 'MISS_SYMBOL', - start = finish, - finish = finish, - info = { - symbol = endSymbol, - }, - fix = { - title = 'ADD_LCOMMENT_END', - { - start = finish, - finish = finish, - text = endSymbol, - } - }, - } - end - end, - CLongComment = function (start1, finish1, str, start2, finish2) - if State.options.nonstandardSymbol and State.options.nonstandardSymbol['/**/'] then - else - 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 - PushComment { - type = 'comment.clong', - start = start1, - finish = finish2 - 1, - text = str, - } - end, - CCommentPrefix = function (start, finish, commentFinish) - if State.options.nonstandardSymbol and State.options.nonstandardSymbol['//'] then - else - PushError { - type = 'ERR_COMMENT_PREFIX', - start = start, - finish = finish - 1, - fix = { - title = 'FIX_COMMENT_PREFIX', - { - start = start, - finish = finish - 1, - text = '--', - }, - } - } - end - PushComment { - type = 'comment.cshort', - start = start, - finish = commentFinish - 1, - text = '', - } - end, - String = function (start, quote, str, finish) - if quote == '`' then - if State.options.nonstandardSymbol and State.options.nonstandardSymbol['`'] then - else - PushError { - type = 'ERR_NONSTANDARD_SYMBOL', - start = start, - finish = finish - 1, - info = { - symbol = '"', - }, - fix = { - title = 'FIX_NONSTANDARD_SYMBOL', - symbol = '"', - { - start = start, - finish = start, - text = '"', - }, - { - start = finish - 1, - finish = finish - 1, - text = '"', - }, - } - } - end - end - 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 = mathType(n) == 'integer' and 'integer' or 'number', - start = start, - finish = finish - 1, - [1] = n, - } - State.LastRaw = number - return State.LastNumber - else - PushError { - type = 'MALFORMED_NUMBER', - start = start, - finish = finish - 1, - } - State.LastNumber = { - type = 'number', - start = start, - finish = finish - 1, - [1] = 0, - } - State.LastRaw = number - return State.LastNumber - end - end, - FFINumber = function (start, symbol) - local lastNumber = State.LastNumber - if State.LastRaw:find('.', 1, true) 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, - Integer2 = function (start, word) - if State.version ~= 'LuaJIT' then - PushError { - type = 'UNSUPPORT_SYMBOL', - start = start, - finish = start + 1, - version = 'LuaJIT', - info = { - version = State.version, - } - } - end - local num = 0 - for i = 1, #word do - if word:sub(i, i) == '1' then - num = num | (1 << (i - 1)) - end - end - return tostring(num) - 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 - if not State.options.unicodeName and str:find '[\x80-\xff]' then - PushError { - type = 'UNICODE_NAME', - 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', - bstart = start, - 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) - if SymbolAlias[op] then - if State.options.nonstandardSymbol and State.options.nonstandardSymbol[op] then - else - PushError { - type = 'ERR_NONSTANDARD_SYMBOL', - start = start, - finish = start + #op - 1, - info = { - symbol = SymbolAlias[op], - }, - fix = { - title = 'FIX_NONSTANDARD_SYMBOL', - symbol = SymbolAlias[op], - { - start = start, - finish = start + #op - 1, - text = SymbolAlias[op], - }, - } - } - end - op = SymbolAlias[op] - end - return { - type = op, - start = start, - finish = start + #op - 1, - } - end, - UnaryOp = function (start, op) - if SymbolAlias[op] then - if State.options.nonstandardSymbol and State.options.nonstandardSymbol[op] then - else - PushError { - type = 'ERR_NONSTANDARD_SYMBOL', - start = start, - finish = start + #op - 1, - info = { - symbol = SymbolAlias[op], - }, - fix = { - title = 'FIX_NONSTANDARD_SYMBOL', - symbol = SymbolAlias[op], - { - start = start, - finish = start + #op - 1, - text = SymbolAlias[op], - }, - } - } - end - op = SymbolAlias[op] - end - 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, - ASSIGN = function (start, symbol) - if State.options.nonstandardSymbol and State.options.nonstandardSymbol[symbol] then - else - PushError { - type = 'UNSUPPORT_SYMBOL', - start = start, - finish = start + #symbol - 1, - info = { - version = 'Lua', - } - } - end - end, - DOT = function (start) - return { - type = '.', - start = start, - finish = start, - } - end, - Function = 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 actions - 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 - elseif name.type == 'getindex' then - name.type = 'setfield' - name.value = actions - PushError { - type = 'INDEX_IN_FUNC_NAME', - start = name.bstart, - finish = name.finish, - } - end - name.range = actions.finish - name.vstart = functionStart - return name - end, - LocalFunction = function (start, name) - if name.type == 'function' then - PushError { - type = 'MISS_NAME', - start = name.keyword[2] + 1, - finish = name.keyword[2] + 1, - } - return name - end - if name.type ~= 'setname' then - PushError { - type = 'UNEXPECT_LFUNC_NAME', - start = name.start, - finish = name.finish, - } - return name - end - - local loc = createLocal(name, name.start, name.value) - loc.localfunction = true - loc.vstart = name.value.start - return name - end, - NamedFunction = function (name) - if name.type == 'function' then - PushError { - type = 'MISS_NAME', - start = name.keyword[2] + 1, - finish = name.keyword[2] + 1, - } - end - return name - end, - ExpFunction = function (func) - if func.type ~= 'function' then - PushError { - type = 'UNEXPECT_EFUNC_NAME', - start = func.start, - finish = func.finish, - } - return func.value - end - return func - 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 - local n = 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 - if field.type == 'tableexp' then - n = n + 1 - field.tindex = n - end - 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, - TableExp = function (start, value, finish) - if not value then - return - end - local obj = { - type = 'tableexp', - start = start, - finish = finish-1, - value = value, - } - 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, eqFinish, 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) - else - PushError { - type = 'UNEXPECT_SYMBOL', - start = eqFinish - 1, - finish = eqFinish - 1, - info = { - symbol = '=', - } - } - 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) - if #attrs == 0 then - return nil - end - 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 - attrs.start = attrs[1].start - attrs.finish = attrs[#attrs].finish - return attrs - end, - LocalName = function (name, attrs) - if not name then - return - 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 - 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 - 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) - if #exp == 0 then - exp[1] = getSelect(func, 2) - exp[2] = getSelect(func, 3) - exp[3] = getSelect(func, 4) - end - call.node = func - call.start = inA - call.finish = doB - 1 - func.next = call - func.iterator = true - 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, - RTContinue = function (_, pos, ...) - if State.options.nonstandardSymbol and State.options.nonstandardSymbol['continue'] then - return pos, ... - else - return false - end - end, - Continue = function (start, finish) - return { - type = 'nonstandardSymbol.continue', - start = start, - finish = finish - 1, - } - 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, - } - } - 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, - MissQuote3 = 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, - } - -- 当exp为nil时,不能返回任何值,否则会产生带洞的actionlist - if exp then - return exp - else - return - end - 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, - MissSpaceBetween = function (start) - PushError { - type = 'MISS_SPACE_BETWEEN', - start = start, - finish = start + 1, - fix = { - title = 'FIX_INSERT_SPACE', - { - start = start + 1, - finish = start, - text = ' ', - } - } - } - end, - CallArgSnip = function (name, tailStart, tailSymbol) - PushError { - type = 'UNEXPECT_SYMBOL', - start = tailStart, - finish = tailStart, - info = { - symbol = tailSymbol, - } - } - return name - end -} - -local function init(state) - State = state - PushError = state.pushError - PushDiag = state.pushDiag - PushComment = state.pushComment -end - -local function close() - State = DefaultState - PushError = function (...) end - PushDiag = function (...) end - PushComment = function (...) end -end - -return { - defs = Defs, - init = init, - close = close, -} |