-- LunaCON CON to Lunatic translator -- requires LPeg, http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html local lpeg = require("lpeg") if (not _EDUKE32_LUNATIC) then require("strict") end -- I think that the "too many pending calls/choices" is unavoidable in general. -- This limit is of course still arbitrary, but writing long if/else cascades -- in CON isn't pretty either (though sometimes necessary because nested switches -- don't work?) -- See also: http://lua-users.org/lists/lua-l/2010-03/msg00086.html lpeg.setmaxstack(1024); local Pat, Set, Range, Var = lpeg.P, lpeg.S, lpeg.R, lpeg.V ---- All keywords pattern -- needed for CON syntax local con = require("con_lang") local function match_until(matchsp, untilsp) -- (!untilsp matchsp)* in PEG -- sp: string or pattern return (matchsp - Pat(untilsp))^0 end local function printf(fmt, ...) print(string.format(fmt, ...)) end ---=== semantic action functions ===--- local inf = 1/0 local NaN = 0/0 -- Last keyword position, for error diagnosis. local g_lastkwpos = nil local g_lastkw = nil local g_badids = {} -- maps bad id strings to 'true' local g_recurslevel = -1 -- 0: base CON file, >0 included local g_filename = "???" local g_directory = "" -- with trailing slash if not empty local g_numerrors = 0 local g_ifnestlevel = 0 -- needed to cope with CONs dangling-else resolution local function getlinecol(pos) end -- fwd-decl local function linecolstr(pos) local line, col = getlinecol(pos) return string.format("%d:%d", line, col) end local function errprintf(fmt, ...) if (g_lastkwpos) then printf("%s %s: error: "..fmt, g_filename, linecolstr(g_lastkwpos), ...) else printf("%s ???: error: "..fmt, g_filename, ...) end g_numerrors = g_numerrors+1 end local function warnprintf(fmt, ...) if (g_lastkwpos) then printf("%s %s: warning: "..fmt, g_filename, linecolstr(g_lastkwpos), ...) else printf("%s ???: warning: "..fmt, g_filename, ...) end end local function parse_number(numstr) local num = tonumber(numstr) -- TODO: print line number if (num < -0x80000000 or num > 0xffffffff) then errprintf("number %s out of the range of a 32-bit integer", numstr) num = NaN elseif (num >= 0x80000000 and numstr:sub(1,2):lower()~="0x") then warnprintf("number %s converted to a negative one", numstr) num = num-0x100000000 end return num end local LABEL = { MOVE=2, AI=3, ACTION=5, [2]="move", [3]="ai", [5]="action" } local MOVE_NO_ = {0,0} local ACTION_NO_ = {0,0,0,0,0} local LABEL_NO = { [2]=MOVE_NO_, [3]={ACTION_NO_,MOVE_NO_,0}, [5]=ACTION_NO_ } -- will contain: -- * scalar numbers: `define'd values -- * tables of length 2, 3, 5: move, ai, action definitions (respectively) -- - move: { hvel , vvel } -- - ai: { action