
better path going forward to handling upgrades. Old syntax files will stick around for compatibility purposes. Old syntax can be parsed into valid syntax trees via the old syntax (.peg) files, and then old syntax trees should be valid and can be upgraded via the normal code path. This change has lots of improvements to Nomsu codegen too.
127 lines
3.0 KiB
Lua
127 lines
3.0 KiB
Lua
local repr
|
|
repr = require('utils').repr
|
|
local insert, remove, concat
|
|
do
|
|
local _obj_0 = table
|
|
insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
|
|
end
|
|
local Source
|
|
Source = require("code_obj").Source
|
|
local unpack = unpack or table.unpack
|
|
local AST = { }
|
|
AST.is_syntax_tree = function(n, t)
|
|
if t == nil then
|
|
t = nil
|
|
end
|
|
return type(n) == 'table' and getmetatable(n) and AST[n.type] == getmetatable(n) and (t == nil or n.type == t)
|
|
end
|
|
local types = {
|
|
"Number",
|
|
"Var",
|
|
"Block",
|
|
"EscapedNomsu",
|
|
"Text",
|
|
"List",
|
|
"Dict",
|
|
"DictEntry",
|
|
"IndexChain",
|
|
"Action",
|
|
"FileChunks"
|
|
}
|
|
for _index_0 = 1, #types do
|
|
local name = types[_index_0]
|
|
local cls = { }
|
|
do
|
|
cls.__class = cls
|
|
cls.__index = cls
|
|
cls.__name = name
|
|
cls.type = name
|
|
cls.is_instance = function(self, x)
|
|
return getmetatable(x) == self
|
|
end
|
|
cls.__tostring = function(self)
|
|
return tostring(self.type) .. "(" .. tostring(repr(tostring(self.source))) .. ", " .. tostring(concat((function()
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for _index_1 = 1, #self do
|
|
local v = self[_index_1]
|
|
_accum_0[_len_0] = repr(v)
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
return _accum_0
|
|
end)(), ', ')) .. ")"
|
|
end
|
|
cls.map = function(self, fn)
|
|
local replacement = fn(self)
|
|
if replacement ~= nil then
|
|
return replacement or nil
|
|
end
|
|
local replacements = { }
|
|
local changes = false
|
|
for i, v in ipairs(self) do
|
|
if AST.is_syntax_tree(v) then
|
|
replacement = v:map(fn)
|
|
else
|
|
replacement = v
|
|
end
|
|
changes = changes or (replacement ~= v)
|
|
replacements[#replacements + 1] = replacement
|
|
end
|
|
if not (changes) then
|
|
return self
|
|
end
|
|
return (self.__class)(self.source, unpack(replacements))
|
|
end
|
|
end
|
|
AST[name] = setmetatable(cls, {
|
|
__tostring = function(self)
|
|
return self.name
|
|
end,
|
|
__call = function(self, source, ...)
|
|
if type(source) == 'string' then
|
|
source = Source:from_string(source)
|
|
end
|
|
for i = 1, select('#', ...) do
|
|
assert(select(i, ...))
|
|
end
|
|
assert(Source:is_instance(source))
|
|
local inst = {
|
|
source = source,
|
|
...
|
|
}
|
|
setmetatable(inst, self)
|
|
if inst.__init then
|
|
inst:__init()
|
|
end
|
|
return inst
|
|
end
|
|
})
|
|
end
|
|
AST.Action.__init = function(self)
|
|
local stub_bits
|
|
do
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for _index_0 = 1, #self do
|
|
local a = self[_index_0]
|
|
_accum_0[_len_0] = type(a) == 'string' and a or '%'
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
stub_bits = _accum_0
|
|
end
|
|
self.stub = concat(stub_bits, " ")
|
|
end
|
|
AST.Action.get_args = function(self)
|
|
local _accum_0 = { }
|
|
local _len_0 = 1
|
|
for _index_0 = 1, #self do
|
|
local tok = self[_index_0]
|
|
if type(tok) ~= 'string' then
|
|
_accum_0[_len_0] = tok
|
|
_len_0 = _len_0 + 1
|
|
end
|
|
end
|
|
return _accum_0
|
|
end
|
|
return AST
|