allow braces in macros, fix strings in multiline macros

This commit is contained in:
Redo 2022-10-31 20:42:34 -06:00
parent 4bc3828d43
commit dfc9f18ec7

View File

@ -176,23 +176,28 @@ local function evaluateExpression(expr)
return eval
end
local function preprocessCode(code)
code = "\n"..code.."\n"
local funcmacros = {}
code = code:gsub(".define ([%.a-zA-Z0-9_]+)%(([^%)]+)%) ([^\n]+)", function(name, args, repl)
local argt = separateCommas(args)
for argidx, arg in ipairs(argt) do assert(not arg:find("[^a-zA-Z0-9_]"), "invalid character in macro arg name: "..name.." "..arg) end
repl = " "..repl.." "
funcmacros[name] = function(callargs)
local invoc = 0
funcmacros[name] = function(b, callargs)
invoc = invoc + 1
local callargt = separateCommas(callargs)
local callrepl = repl
for argidx, arg in ipairs(argt) do
local callarg = callargt[argidx]
callrepl = callrepl:gsub("([^a-zA-Z0-9_])"..arg.."([^a-zA-Z0-9_])", "%1"..callarg.."%2")
end
return callrepl
callrepl = callrepl:gsub("(_BRACE_[0-9]+_)", "%1"..invoc.."_")
return b..callrepl
end
return ""
end)
for name, replf in pairs(funcmacros) do code = code:gsub(name.." *%(([^%)]+)%)", replf) end
for name, replf in pairs(funcmacros) do code = code:gsub("([^a-zA-Z0-9_])"..name.." *%(([^%)]+)%)", replf) end
local simplemacros = {}
code = code:gsub("%.define +([%.a-zA-Z0-9_]+) +([^\n]+)", function(name, repl)
@ -201,7 +206,13 @@ local function preprocessCode(code)
return ""
end)
--for name, repl in pairs(simplemacros) do code = code:gsub(name, repl, 1, true) end
for name, repl in pairs(simplemacros) do code = code:gsub(name, repl) end
for name, repl in pairs(simplemacros) do
local invoc = 0
code = code:gsub("([^a-zA-Z0-9_])"..name.."([^a-zA-Z0-9_])", function(b, a)
invoc = invoc+1
return b..(repl:gsub("(_BRACE_[0-9]+_)", "%1"..invoc.."_"))..a
end)
end
code = code:gsub("\\", "\n")
@ -254,12 +265,12 @@ local function prefixCode(code, fn) -- fix strings, add line numbers
local outt = {}
local outnextnl = {}
local linenum = 1
local skipnl = false
local function last() return outt[#outt] end
local function out(c) assert(type(c)=="string"); table.insert(outt, c); end
local function outn(n) out("$"..string.format("%02X", n).."\n"); end
local function outn(n) out("$"..string.format("%02X", n)) out("\\") end
local function outnext(c) assert(type(c)=="string"); table.insert(outnextnl, c); end
local state = "code" -- code, comment, string, stringesc
local skipnl = false
local lastbracelabel = 0
local function bracelabel() lastbracelabel = lastbracelabel+1; return "_BRACE_"..lastbracelabel.."_"; end
@ -271,33 +282,36 @@ local function prefixCode(code, fn) -- fix strings, add line numbers
for i = 1, #code do
local c = code:sub(i, i)
local cn = code:sub(i+1, i+1)
if state=="code" then
if c=="\r" then
elseif c=="\n" or c=="/" then
linenum = linenum+1
if skipnl then skipnl = false
else out("\n") out(".ln "..linenum); out("\n"); end
if not skipnl then out("\n") out(".ln "..linenum); out("\n"); end
lastnl = true
for _, v in ipairs(outnextnl) do out(v) end; outnextnl = {};
for _, v in ipairs(outnextnl) do
if v=="\n" and skipnl then out("\\")
else out(v) end
end; outnextnl = {};
skipnl = false
elseif c=="#" or c==";" or (c=="/" and cn=="/") then state = "comment"
elseif c=="\t" or c==" " then if (not lastnl) then out(" ") end
elseif c=="\"" then state = "string" lastnl = false
elseif c=="\\" then skipnl = true; out("\\");
elseif c:find("^[a-zA-Z0-9_%.:%$%(%)%*,%[%]%+%-%*%/]$") then out(c); lastnl = false
elseif c=="{" then
elseif c=="{" then
table.insert(bracestack, bracelabel())
if not lastnl then out(bracestack[#bracestack].."MID") end
outnext(bracestack[#bracestack].."START:"); outnext("\n")
outnext(bracestack[#bracestack].."START:"); outnext("\n");
elseif c=="}" then
if not lastnl then out(bracestack[#bracestack].."START") end
if not bracehasmid[#bracestack] then outnext(bracestack[#bracestack].."MID:") outnext("\n") end
outnext(bracestack[#bracestack].."END:")
if not bracehasmid[#bracestack] then outnext(bracestack[#bracestack].."MID:"); outnext("\n"); end
outnext(bracestack[#bracestack].."END:"); outnext("\n");
bracehasmid[#bracestack] = nil
bracestack[#bracestack] = nil
elseif c=="|" then
if not lastnl then out(bracestack[#bracestack].."END") out("\n") end
out(bracestack[#bracestack].."MID:") out("\n")
if not lastnl then out(bracestack[#bracestack].."END") end
outnext(bracestack[#bracestack].."MID:"); outnext("\n");
bracehasmid[#bracestack] = true
else error("invalid char "..c) end
elseif state=="comment" then