92 lines
2.1 KiB
Lua
92 lines
2.1 KiB
Lua
module(..., package.seeall)
|
|
|
|
local nodegen = require "tundra.nodegen"
|
|
|
|
local functions = {}
|
|
local _decl_meta = {}
|
|
_decl_meta.__index = _decl_meta
|
|
|
|
local current = nil
|
|
|
|
local function new_parser()
|
|
local obj = {
|
|
Functions = {},
|
|
Results = {},
|
|
DefaultTargets = {},
|
|
AlwaysTargets = {},
|
|
}
|
|
|
|
local outer_env = _G
|
|
local iseval = nodegen.is_evaluator
|
|
local function indexfunc(tab, var)
|
|
if iseval(var) then
|
|
-- Return an anonymous function such that
|
|
-- the code "Foo { ... }" will result in a call to
|
|
-- "nodegen.evaluate('Foo', { ... })"
|
|
return function (data)
|
|
local result = nodegen.evaluate(var, data)
|
|
obj.Results[#obj.Results + 1] = result
|
|
return result
|
|
end
|
|
end
|
|
local p = obj.Functions[var]
|
|
if p then return p end
|
|
return outer_env[var]
|
|
end
|
|
|
|
obj.FunctionMeta = { __index = indexfunc, __newindex = error }
|
|
obj.FunctionEnv = setmetatable({}, obj.FunctionMeta)
|
|
|
|
for name, fn in pairs(functions) do
|
|
obj.Functions[name] = setfenv(fn, obj.FunctionEnv)
|
|
end
|
|
|
|
obj.Functions["Default"] = function(default_obj)
|
|
obj.DefaultTargets[#obj.DefaultTargets + 1] = default_obj
|
|
end
|
|
|
|
obj.Functions["Always"] = function(always_obj)
|
|
obj.AlwaysTargets[#obj.AlwaysTargets + 1] = always_obj
|
|
end
|
|
|
|
current = setmetatable(obj, _decl_meta)
|
|
return current
|
|
end
|
|
|
|
function add_function(name, fn)
|
|
assert(name and fn)
|
|
functions[name] = fn
|
|
|
|
if current then
|
|
-- require called from within unit script
|
|
current.Functions[name] = setfenv(fn, current.FunctionEnv)
|
|
end
|
|
end
|
|
|
|
function _decl_meta:parse_rec(data)
|
|
local chunk
|
|
if type(data) == "table" then
|
|
for _, gen in ipairs(data) do
|
|
self:parse_rec(gen)
|
|
end
|
|
return
|
|
elseif type(data) == "function" then
|
|
chunk = data
|
|
elseif type(data) == "string" then
|
|
chunk = assert(loadfile(data))
|
|
else
|
|
croak("unknown type %s for unit_generator %q", type(data), tostring(data))
|
|
end
|
|
|
|
setfenv(chunk, self.FunctionEnv)
|
|
chunk()
|
|
end
|
|
|
|
function parse(data)
|
|
p = new_parser()
|
|
current = p
|
|
p:parse_rec(data)
|
|
current = nil
|
|
return p.Results, p.DefaultTargets, p.AlwaysTargets
|
|
end
|