84 lines
2.5 KiB
Lua
84 lines
2.5 KiB
Lua
-- Generator v2: Borderless Edition
|
|
-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
-- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
local generator = {}
|
|
|
|
do
|
|
function generator.parse_ast(file, ast)
|
|
local gcode = ""
|
|
for i=1, #ast do
|
|
local leaf = ast[i]
|
|
if leaf.type == "directive" then
|
|
gcode = gcode .. string.format("call_directive(%q,", leaf.name)
|
|
local pargs = {}
|
|
for i=1, #leaf.args do
|
|
if type(leaf.args[i]) ~= "table" then
|
|
table.insert(pargs, string.format("%q", leaf.args[i]))
|
|
elseif leaf.args[i].type == "lua_span" then
|
|
table.insert(pargs, leaf.args[i].val)
|
|
elseif leaf.args[i].type == "evar" then
|
|
table.insert(pargs, string.format("svar.get(%q)", leaf.args[i].val))
|
|
end
|
|
end
|
|
gcode = gcode .. table.concat(pargs, ",")..")\n"
|
|
elseif leaf.type == "lua_block" then
|
|
gcode = gcode .. leaf.val .. "\n"
|
|
elseif leaf.type == "shell_block" then
|
|
gcode = gcode .. string.format("shell_write(%q)\n", leaf.val)
|
|
elseif leaf.type == "content" then
|
|
gcode = gcode .. string.format("write_out(%q)\n", leaf.val)
|
|
elseif leaf.type == "lua_span" then
|
|
gcode = gcode .. "write_out("..leaf.val..")\n"
|
|
elseif leaf.type == "shell_span" then
|
|
gcode = gcode .. string.format("write_out(svar.get(%q))\n", leaf.val)
|
|
elseif leaf.type == "evar" then
|
|
gcode = gcode .. string.format("write_out(string.format(\"%%q\", svar.get(%q)))\n", leaf.val)
|
|
end
|
|
end
|
|
return gcode
|
|
end
|
|
|
|
function generator.run_gcode(fname, gcode)
|
|
fname = fname or "(unknown)"
|
|
local env = {
|
|
code = "",
|
|
fname = fname,
|
|
pragmas = {
|
|
include_file_name = "n",
|
|
prefix_local_file_numbers = "n",
|
|
wrap_includes = "n"
|
|
}
|
|
}
|
|
local fenv = {}
|
|
for k, v in pairs(_G) do
|
|
fenv[k] = v
|
|
end
|
|
fenv._G = fenv
|
|
fenv._GENERATOR = env
|
|
function fenv.call_directive(dname, ...)
|
|
if not directives[dname] then lc_error("@[{_GENERATOR.fname}]", "invalid directive "..dname) end
|
|
local r, er = directives[dname](env, ...)
|
|
if not r then lc_error("directive "..dname, er) end
|
|
end
|
|
|
|
function fenv.write_out(code)
|
|
env.code = env.code .. code
|
|
end
|
|
|
|
function fenv.shell_write(cmd)
|
|
local tmpname = os.tmpname()
|
|
local f = io.open(tmpname, "w")
|
|
f:write(cmd)
|
|
f:close()
|
|
local h = io.popen(os.getenv("SHELL").." "..tmpname, "r")
|
|
env.code = env.code .. h:read("*a")
|
|
h:close()
|
|
end
|
|
|
|
assert(load(gcode, "="..fname, "t", fenv))()
|
|
|
|
return env.code
|
|
end
|
|
end |