summaryrefslogtreecommitdiff
path: root/server/src/parser/ast.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/parser/ast.lua')
-rw-r--r--server/src/parser/ast.lua377
1 files changed, 377 insertions, 0 deletions
diff --git a/server/src/parser/ast.lua b/server/src/parser/ast.lua
new file mode 100644
index 00000000..2c434511
--- /dev/null
+++ b/server/src/parser/ast.lua
@@ -0,0 +1,377 @@
+local tonumber = tonumber
+local string_char = string.char
+local utf8_char = utf8.char
+
+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,
+ String = function (start, str, finish)
+ return {
+ type = 'string',
+ start = start,
+ finish = finish - 1,
+ [1] = str,
+ }
+ end,
+ Char10 = function (char)
+ char = tonumber(char)
+ if not char or char < 0 or char > 255 then
+ -- TODO 记录错误
+ return ''
+ end
+ return string_char(char)
+ end,
+ Char16 = function (char)
+ return string_char(tonumber(char, 16))
+ end,
+ CharUtf8 = function (char)
+ char = tonumber(char, 16)
+ if not char or char < 0 or char > 0x10ffff then
+ -- TODO 记录错误
+ return ''
+ end
+ return utf8_char(char)
+ end,
+ Number = function (start, number, finish)
+ return {
+ type = 'number',
+ start = start,
+ finish = finish - 1,
+ [1] = tonumber(number),
+ }
+ end,
+ Name = function (start, str, finish)
+ return {
+ type = 'name',
+ start = start,
+ finish = finish - 1,
+ [1] = str,
+ }
+ end,
+ Simple = function (first, ...)
+ if ... then
+ return {
+ type = 'simple',
+ first, ...,
+ }
+ elseif first == '' then
+ return nil
+ else
+ return first
+ end
+ end,
+ Index = function (exp)
+ exp.index = true
+ return exp
+ end,
+ Call = function (arg)
+ if arg == nil then
+ return {
+ type = 'call'
+ }
+ end
+ if arg.type == 'list' then
+ arg.type = 'call'
+ return arg
+ end
+ local obj = {
+ type = 'call',
+ [1] = arg,
+ }
+ return obj
+ end,
+ Binary = function (...)
+ local e1, op = ...
+ if not op then
+ return e1
+ end
+ local args = {...}
+ local e1 = args[1]
+ local e2
+ for i = 2, #args, 2 do
+ op, e2 = args[i], args[i+1]
+ e1 = {
+ type = op,
+ [1] = e1,
+ [2] = e2,
+ }
+ end
+ return e1
+ end,
+ Unary = function (...)
+ local e1, op = ...
+ if not op then
+ return e1
+ end
+ local args = {...}
+ local e1 = args[#args]
+ for i = #args - 1, 1, -1 do
+ op = args[i]
+ e1 = {
+ type = op,
+ [1] = e1,
+ }
+ end
+ return e1
+ end,
+ DOTS = function (start)
+ return {
+ type = '...',
+ start = start,
+ finish = start + 2,
+ }
+ end,
+ COLON = function (start)
+ return {
+ type = ':',
+ start = start,
+ finish = start,
+ }
+ end,
+ Function = function (start, name, arg, ...)
+ local obj = {
+ type = 'function',
+ start = start,
+ name = name,
+ arg = arg,
+ ...
+ }
+ local max = #obj
+ obj.finish = obj[max] - 1
+ obj[max] = nil
+ return obj
+ end,
+ LocalFunction = function (start, name, arg, ...)
+ local obj = {
+ type = 'localfunction',
+ start = start,
+ name = name,
+ arg = arg,
+ ...
+ }
+ local max = #obj
+ obj.finish = obj[max] - 1
+ obj[max] = nil
+ return obj
+ end,
+ Table = function (start, table, finish)
+ if table then
+ table.start = start
+ table.finish = finish - 1
+ else
+ table = {
+ type = 'table',
+ start = start,
+ finish = finish - 1,
+ }
+ end
+ return table
+ end,
+ TableFields = function (...)
+ if ... == '' then
+ return nil
+ else
+ return {
+ type = 'table',
+ ...,
+ }
+ end
+ end,
+ NewField = function (key, value)
+ return {
+ type = 'pair',
+ key, value,
+ }
+ end,
+ NewIndex = function (key, value)
+ key.index = true
+ return {
+ type = 'pair',
+ key, value,
+ }
+ end,
+ List = function (first, second, ...)
+ if second then
+ return {
+ type = 'list',
+ first, second, ...
+ }
+ elseif first == '' then
+ return nil
+ else
+ return first
+ end
+ end,
+ Set = function (keys, values)
+ return {
+ type = 'set',
+ keys, values,
+ }
+ end,
+ Local = function (keys, values)
+ return {
+ type = 'local',
+ keys, values,
+ }
+ end,
+ DoBody = function (...)
+ if ... == '' then
+ return {
+ type = 'do',
+ }
+ else
+ return {
+ type = 'do',
+ ...
+ }
+ end
+ end,
+ Do = function (start, action, finish)
+ action.start = start
+ action.finish = finish - 1
+ return action
+ end,
+ Break = function ()
+ return {
+ type = 'break',
+ }
+ end,
+ Return = function (exp)
+ if exp == nil or exp == '' then
+ exp = {
+ type = 'return'
+ }
+ else
+ if exp.type == 'list' then
+ exp.type = 'return'
+ else
+ exp = {
+ type = 'return',
+ [1] = exp,
+ }
+ end
+ end
+ return exp
+ end,
+ Label = function (name)
+ name.type = 'label'
+ return name
+ end,
+ GoTo = function (name)
+ name.type = 'goto'
+ return name
+ end,
+ IfBlock = function (exp, ...)
+ return {
+ filter = exp,
+ ...
+ }
+ end,
+ ElseIfBlock = function (exp, ...)
+ return {
+ filter = exp,
+ ...
+ }
+ end,
+ ElseBlock = function (...)
+ return {
+ ...
+ }
+ end,
+ If = function (start, ...)
+ local obj = {
+ type = 'if',
+ start = start,
+ ...
+ }
+ local max = #obj
+ obj.finish = obj[max] - 1
+ obj[max] = nil
+ return obj
+ end,
+ LoopDef = function (arg, min, max, step)
+ return arg, min, max, step
+ end,
+ Loop = function (start, arg, min, max, step, ...)
+ local obj = {
+ type = 'loop',
+ start = start,
+ arg = arg,
+ min = min,
+ max = max,
+ step = step,
+ ...
+ }
+ local max = #obj
+ obj.finish = obj[max] - 1
+ obj[max] = nil
+ return obj
+ end,
+ In = function (start, arg, exp, ...)
+ local obj = {
+ type = 'in',
+ start = start,
+ arg = arg,
+ exp = exp,
+ ...
+ }
+ local max = #obj
+ obj.finish = obj[max] - 1
+ obj[max] = nil
+ return obj
+ end,
+ While = function (start, filter, ...)
+ local obj = {
+ type = 'while',
+ start = start,
+ filter = filter,
+ ...
+ }
+ local max = #obj
+ obj.finish = obj[max] - 1
+ obj[max] = nil
+ return obj
+ end,
+ Repeat = function (start, ...)
+ local obj = {
+ type = 'repeat',
+ start = start,
+ ...
+ }
+ local max = #obj
+ obj.finish = obj[max] - 1
+ obj.filter = obj[max-1]
+ obj[max] = nil
+ obj[max-1] = nil
+ return obj
+ end,
+}
+
+return function (self, lua, mode)
+ local gram, err = self.grammar(lua, mode, defs)
+ if not gram then
+ return nil, err
+ end
+ return gram
+end