summaryrefslogtreecommitdiff
path: root/script/parser/ast.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script/parser/ast.lua')
-rw-r--r--script/parser/ast.lua1997
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,
-}