diff --git a/assembler-8608.lua b/assembler-8608.lua index 2c384d4..6c602f9 100644 --- a/assembler-8608.lua +++ b/assembler-8608.lua @@ -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