Lunatic translator improvements.

git-svn-id: https://svn.eduke32.com/eduke32@2612 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2012-04-22 19:10:46 +00:00
parent 6d9411f669
commit cb8e0d1b57
2 changed files with 468 additions and 433 deletions

View file

@ -2,369 +2,376 @@
-- require("lpeg")
-- con_keyword = dofile("con_lang.lua")
-- NOTE: These MUST be in reverse lexicographical order!
-- Per CON syntax, valid identifiers names are disjunct from keywords,
-- so that a rule like
-- t_identifier = -con_keyword * (sp1 + "[") * t_identifier_all
-- (from the final grammar in lunacon.lua) must match the longest
-- possible keyword name, else the negation might wrongly not fail.
return
lpeg.P(false) +
"{" +
"}" +
"action" +
"activatebysector" +
"activatecheat" +
"actor" +
"addammo" +
"addinventory" +
"addkills" +
"addlog" +
"addlogvar" +
"addphealth" +
"addstrength" +
"addvar" +
"addvarvar" +
"addweapon" +
"addweaponvar" +
"ai" +
"andvar" +
"andvarvar" +
"angoff" +
"angoffvar" +
"betaname" +
"break" +
"cactor" +
"calchypotenuse" +
"cansee" +
"canseespr" +
"case" +
"changespritesect" +
"changespritestat" +
"cheatkeys" +
"checkactivatormotion" +
"checkavailinven" +
"checkavailweapon" +
"clearmapstate" +
"clipdist" +
"clipmove" +
"clipmovenoslide" +
"cmenu" +
"copy" +
"cos" +
"count" +
"cstat" +
"cstator" +
"debris" +
"debug" +
"default" +
"define" +
"definecheat" +
"definegamefuncname" +
"definegametype" +
"definelevelname" +
"defineprojectile" +
"definequote" +
"defineskillname" +
"definesound" +
"definevolumename" +
"digitalnumber" +
"digitalnumberz" +
"displayrand" +
"displayrandvar" +
"displayrandvarvar" +
"dist" +
"divvar" +
"divvarvar" +
"dragpoint" +
"dynamicremap" +
"echo" +
"else" +
"enda" +
"endevent" +
"endofgame" +
"ends" +
"endswitch" +
"enhanced" +
"eqspawn" +
"eqspawnvar" +
"eshoot" +
"eshootvar" +
"espawn" +
"espawnvar" +
"eventloadactor" +
"ezshoot" +
"ezshootvar" +
"fall" +
"findnearactor" +
"findnearactor3d" +
"findnearactor3dvar" +
"findnearactorvar" +
"findnearactorz" +
"findnearactorzvar" +
"findnearsprite" +
"findnearsprite3d" +
"findnearsprite3dvar" +
"findnearspritevar" +
"findnearspritez" +
"findnearspritezvar" +
"findotherplayer" +
"findplayer" +
"flash" +
"gamearray" +
"gamestartup" +
"gametext" +
"gametextz" +
"gamevar" +
"getactor" +
"getactorangle" +
"getactorvar" +
"getangle" +
"getangletotarget" +
"getarraysize" +
"getceilzofslope" +
"getcurraddress" +
"getflorzofslope" +
"getincangle" +
"getinput" +
"getkeyname" +
"getlastpal" +
"getplayer" +
"getplayerangle" +
"getplayervar" +
"getpname" +
"getprojectile" +
"getsector" +
"gettextureceiling" +
"gettexturefloor" +
"getthisprojectile" +
"getticks" +
"gettimedate" +
"gettspr" +
"getuserdef" +
"getwall" +
"getzrange" +
"globalsound" +
"globalsoundvar" +
"gmaxammo" +
"guniqhudid" +
"guts" +
"headspritesect" +
"headspritestat" +
"hitradius" +
"hitradiusvar" +
"hitscan" +
"ifaction" +
"ifactioncount" +
"ifactor" +
"ifactornotstayput" +
"ifactorsound" +
"ifai" +
"ifangdiffl" +
"ifawayfromwall" +
"ifbulletnear" +
"ifcansee" +
"ifcanseetarget" +
"ifcanshoottarget" +
"ifceilingdistl" +
"ifclient" +
"ifcount" +
"ifdead" +
"iffloordistl" +
"ifgapzl" +
"ifgotweaponce" +
"ifhitspace" +
"ifhitweapon" +
"ifinouterspace" +
"ifinspace" +
"ifinwater" +
"ifmove" +
"ifmultiplayer" +
"ifnosounds" +
"ifnotmoving" +
"ifonwater" +
"ifoutside" +
"ifp" +
"ifpdistg" +
"ifpdistl" +
"ifphealthl" +
"ifpinventory" +
"ifrespawn" +
"ifrnd" +
"ifserver" +
"ifsound" +
"ifspawnedby" +
"ifspritepal" +
"ifsquished" +
"ifstrength" +
"ifvarand" +
"ifvare" +
"ifvareither" +
"ifvarg" +
"ifvarl" +
"ifvarn" +
"ifvaror" +
"ifvarvarand" +
"ifvarvare" +
"ifvarvareither" +
"ifvarvarg" +
"ifvarvarl" +
"ifvarvarn" +
"ifvarvaror" +
"ifvarvarxor" +
"ifvarxor" +
"ifwasweapon" +
"include" +
"includedefault" +
"inittimer" +
"insertspriteq" +
"jump" +
"killit" +
"ldist" +
"lineintersect" +
"loadmapstate" +
"lockplayer" +
"lotsofglass" +
"mail" +
"mikesnd" +
"minitext" +
"modvar" +
"modvarvar" +
"money" +
"move" +
"movesprite" +
"mulscale" +
"mulvar" +
"mulvarvar" +
"music" +
"myos" +
"myospal" +
"myospalx" +
"myosx" +
"neartag" +
"nextspritesect" +
"nextspritestat" +
"nullop" +
"onevent" +
"operate" +
"operateactivators" +
"operatemasterswitches" +
"operaterespawns" +
"operatesectors" +
"orvar" +
"orvarvar" +
"palfrom" +
"paper" +
"pkick" +
"precache" +
"prevspritesect" +
"prevspritestat" +
"pstomp" +
"qgetsysstr" +
"qspawn" +
"qspawnvar" +
"qsprintf" +
"qstrcat" +
"qstrcpy" +
"qstrlen" +
"qstrncat" +
"qsubstr" +
"quake" +
"quote" +
"randvar" +
"randvarvar" +
"rayintersect" +
"readarrayfromfile" +
"readgamevar" +
"redefinequote" +
"resetactioncount" +
"resetcount" +
"resetplayer" +
"resizearray" +
"respawnhitag" +
"return" +
"rotatepoint" +
"rotatesprite" +
"rotatesprite16" +
"save" +
"savegamevar" +
"savemapstate" +
"savenn" +
"scriptsize" +
"sectclearinterpolation" +
"sectgethitag" +
"sectgetlotag" +
"sectorofwall" +
"sectsetinterpolation" +
"setactor" +
"setactorangle" +
"setactorsoundpitch" +
"setactorvar" +
"setarray" +
"setaspect" +
"setcfgname" +
"setdefname" +
"setgamename" +
"setgamepalette" +
"setinput" +
"setplayer" +
"setplayerangle" +
"setplayervar" +
"setprojectile" +
"setsector" +
"setsprite" +
"setthisprojectile" +
"settspr" +
"setuserdef" +
"setvar" +
"setvarvar" +
"setwall" +
"shiftvarl" +
"shiftvarr" +
"shoot" +
"shootvar" +
"showview" +
"showviewunbiased" +
"sin" +
"sizeat" +
"sizeto" +
"sleeptime" +
"smaxammo" +
"sound" +
"soundonce" +
"soundoncevar" +
"soundvar" +
"spawn" +
"spgethitag" +
"spgetlotag" +
"spriteflags" +
"spritenopal" +
"spritenoshade" +
"spritenvg" +
"spritepal" +
"spriteshadow" +
"sqrt" +
"ssp" +
"startlevel" +
"starttrack" +
"starttrackvar" +
"state" +
"stopactorsound" +
"stopallsounds" +
"stopsound" +
"stopsoundvar" +
"strength" +
"subvar" +
"subvarvar" +
"switch" +
"time" +
"tip" +
"tossweapon" +
"updatesector" +
"updatesectorz" +
"useractor" +
"userquote" +
"wackplayer" +
"whilevarn" +
"whilevarvarn" +
"writearraytofile" +
"xorvar" +
"xorvarvar" +
"zshoot" +
"{" +
"zshootvar" +
"zshoot" +
"xorvarvar" +
"xorvar" +
"writearraytofile" +
"whilevarvarn" +
"whilevarn" +
"wackplayer" +
"userquote" +
"useractor" +
"updatesectorz" +
"updatesector" +
"tossweapon" +
"tip" +
"time" +
"switch" +
"subvarvar" +
"subvar" +
"strength" +
"stopsoundvar" +
"stopsound" +
"stopallsounds" +
"stopactorsound" +
"state" +
"starttrackvar" +
"starttrack" +
"startlevel" +
"ssp" +
"sqrt" +
"spriteshadow" +
"spritepal" +
"spritenvg" +
"spritenoshade" +
"spritenopal" +
"spriteflags" +
"spgetlotag" +
"spgethitag" +
"spawn" +
"soundvar" +
"soundoncevar" +
"soundonce" +
"sound" +
"smaxammo" +
"sleeptime" +
"sizeto" +
"sizeat" +
"sin" +
"showviewunbiased" +
"showview" +
"shootvar" +
"shoot" +
"shiftvarr" +
"shiftvarl" +
"setwall" +
"setvarvar" +
"setvar" +
"setuserdef" +
"settspr" +
"setthisprojectile" +
"setsprite" +
"setsector" +
"setprojectile" +
"setplayervar" +
"setplayerangle" +
"setplayer" +
"setinput" +
"setgamepalette" +
"setgamename" +
"setdefname" +
"setcfgname" +
"setaspect" +
"setarray" +
"setactorvar" +
"setactorsoundpitch" +
"setactorangle" +
"setactor" +
"sectsetinterpolation" +
"sectorofwall" +
"sectgetlotag" +
"sectgethitag" +
"sectclearinterpolation" +
"scriptsize" +
"savenn" +
"savemapstate" +
"savegamevar" +
"save" +
"rotatesprite16" +
"rotatesprite" +
"rotatepoint" +
"return" +
"respawnhitag" +
"resizearray" +
"resetplayer" +
"resetcount" +
"resetactioncount" +
"redefinequote" +
"readgamevar" +
"readarrayfromfile" +
"rayintersect" +
"randvarvar" +
"randvar" +
"quote" +
"quake" +
"qsubstr" +
"qstrncat" +
"qstrlen" +
"qstrcpy" +
"qstrcat" +
"qsprintf" +
"qspawnvar" +
"qspawn" +
"qgetsysstr" +
"pstomp" +
"prevspritestat" +
"prevspritesect" +
"precache" +
"pkick" +
"paper" +
"palfrom" +
"orvarvar" +
"orvar" +
"operatesectors" +
"operaterespawns" +
"operatemasterswitches" +
"operateactivators" +
"operate" +
"onevent" +
"nullop" +
"nextspritestat" +
"nextspritesect" +
"neartag" +
"myosx" +
"myospalx" +
"myospal" +
"myos" +
"music" +
"mulvarvar" +
"mulvar" +
"mulscale" +
"movesprite" +
"move" +
"money" +
"modvarvar" +
"modvar" +
"minitext" +
"mikesnd" +
"mail" +
"lotsofglass" +
"lockplayer" +
"loadmapstate" +
"lineintersect" +
"ldist" +
"killit" +
"jump" +
"insertspriteq" +
"inittimer" +
"includedefault" +
"include" +
"ifwasweapon" +
"ifvarxor" +
"ifvarvarxor" +
"ifvarvaror" +
"ifvarvarn" +
"ifvarvarl" +
"ifvarvarg" +
"ifvarvareither" +
"ifvarvare" +
"ifvarvarand" +
"ifvaror" +
"ifvarn" +
"ifvarl" +
"ifvarg" +
"ifvareither" +
"ifvare" +
"ifvarand" +
"ifstrength" +
"ifsquished" +
"ifspritepal" +
"ifspawnedby" +
"ifsound" +
"ifserver" +
"ifrnd" +
"ifrespawn" +
"ifpinventory" +
"ifphealthl" +
"ifpdistl" +
"ifpdistg" +
"ifp" +
"ifoutside" +
"ifonwater" +
"ifnotmoving" +
"ifnosounds" +
"ifmultiplayer" +
"ifmove" +
"ifinwater" +
"ifinspace" +
"ifinouterspace" +
"ifhitweapon" +
"ifhitspace" +
"ifgotweaponce" +
"ifgapzl" +
"iffloordistl" +
"ifdead" +
"ifcount" +
"ifclient" +
"ifceilingdistl" +
"ifcanshoottarget" +
"ifcanseetarget" +
"ifcansee" +
"ifbulletnear" +
"ifawayfromwall" +
"ifangdiffl" +
"ifai" +
"ifactorsound" +
"ifactornotstayput" +
"ifactor" +
"ifactioncount" +
"ifaction" +
"hitscan" +
"hitradiusvar" +
"hitradius" +
"headspritestat" +
"headspritesect" +
"guts" +
"guniqhudid" +
"gmaxammo" +
"globalsoundvar" +
"globalsound" +
"getzrange" +
"getwall" +
"getuserdef" +
"gettspr" +
"gettimedate" +
"getticks" +
"getthisprojectile" +
"gettexturefloor" +
"gettextureceiling" +
"getsector" +
"getprojectile" +
"getpname" +
"getplayervar" +
"getplayerangle" +
"getplayer" +
"getlastpal" +
"getkeyname" +
"getinput" +
"getincangle" +
"getflorzofslope" +
"getcurraddress" +
"getceilzofslope" +
"getarraysize" +
"getangletotarget" +
"getangle" +
"getactorvar" +
"getactorangle" +
"getactor" +
"gamevar" +
"gametextz" +
"gametext" +
"gamestartup" +
"gamearray" +
"flash" +
"findplayer" +
"findotherplayer" +
"findnearspritezvar" +
"findnearspritez" +
"findnearspritevar" +
"findnearsprite3dvar" +
"findnearsprite3d" +
"findnearsprite" +
"findnearactorzvar" +
"findnearactorz" +
"findnearactorvar" +
"findnearactor3dvar" +
"findnearactor3d" +
"findnearactor" +
"fall" +
"ezshootvar" +
"ezshoot" +
"eventloadactor" +
"espawnvar" +
"espawn" +
"eshootvar" +
"eshoot" +
"eqspawnvar" +
"eqspawn" +
"enhanced" +
"endswitch" +
"ends" +
"endofgame" +
"endevent" +
"enda" +
"else" +
"echo" +
"dynamicremap" +
"dragpoint" +
"divvarvar" +
"divvar" +
"dist" +
"displayrandvarvar" +
"displayrandvar" +
"displayrand" +
"digitalnumberz" +
"digitalnumber" +
"definevolumename" +
"definesound" +
"defineskillname" +
"definequote" +
"defineprojectile" +
"definelevelname" +
"definegametype" +
"definegamefuncname" +
"definecheat" +
"define" +
"default" +
"debug" +
"debris" +
"cstator" +
"cstat" +
"count" +
"cos" +
"copy" +
"cmenu" +
"clipmovenoslide" +
"clipmove" +
"clipdist" +
"clearmapstate" +
"checkavailweapon" +
"checkavailinven" +
"checkactivatormotion" +
"cheatkeys" +
"changespritestat" +
"changespritesect" +
"case" +
"canseespr" +
"cansee" +
"calchypotenuse" +
"cactor" +
"break" +
"betaname" +
"angoffvar" +
"angoff" +
"andvarvar" +
"andvar" +
"ai" +
"addweaponvar" +
"addweapon" +
"addvarvar" +
"addvar" +
"addstrength" +
"addphealth" +
"addlogvar" +
"addlog" +
"addkills" +
"addinventory" +
"addammo" +
"actor" +
"activatecheat" +
"activatebysector" +
"action" +
lpeg.P(false)

View file

@ -160,7 +160,6 @@ local Co = {
--== Run time CON commands ==--
--- 1. Gamevar Operators
local varop = cmd(W,D)
local varvarop = cmd(W,R)
@ -168,18 +167,20 @@ local varvarop = cmd(W,R)
local arraypat = sp0 * "[" * sp0 * t_define * sp0 * "]"
-- The member name must match keywords, too (_all), because e.g. cstat is a member
-- of sprite[]
-- XXX: actor and sprite members can have parm2, e.g. this is legal:
-- ifvare player[THISACTOR].gotweapon 4 0
-- but not parsed currently.
local memberpat = sp0 * "." * sp0 * t_identifier_all
local getstructcmd = -- get<structname>[<idx>].<member> (<parm2>)? <<var>>
-- existence of a second parameter is determined later
-- This is wrong, (sp1 id)? will match (sp1 wvar) if there's no 2nd param:
-- arraypat * memberpat * (sp1 * t_identifier)^-1 * sp1 * t_wvar
-- XXX: This is still wrong.
arraypat * memberpat * sp1 * (t_identifier * sp1 * t_wvar + t_wvar)
arraypat * memberpat * sp1 * (t_rvar * sp1 * t_wvar + t_wvar)
local setstructcmd = -- set<structname>[<idx>].<member> (<parm2>)? <var>
-- existence of a second parameter is determined later
arraypat * memberpat * sp1 * (t_identifier * sp1 * t_rvar + t_rvar)
arraypat * memberpat * sp1 * (t_rvar * sp1 * t_rvar + t_rvar)
local getperxvarcmd = -- get<actor/player>var[<idx>].<member> <<var>>
arraypat * memberpat * sp1 * t_wvar
@ -201,7 +202,6 @@ local Ci = {
getplayer = getstructcmd,
getprojectile = getstructcmd,
getsector = getstructcmd,
getsprite = getstructcmd,
getthisprojectile = getstructcmd,
gettspr = getstructcmd,
getuserdef = getstructcmd,
@ -215,7 +215,6 @@ local Ci = {
setplayer = setstructcmd,
setprojectile = setstructcmd,
setsector = setstructcmd,
setsprite = setstructcmd,
setthisprojectile = setstructcmd,
settspr = setstructcmd,
setuserdef = setstructcmd,
@ -224,6 +223,8 @@ local Ci = {
setactorvar = setperxvarcmd,
setplayervar = setperxvarcmd,
setsprite = cmd(R,R,R,R),
setvarvar = varvarop,
addvarvar = varvarop,
subvarvar = varvarop,
@ -253,7 +254,7 @@ local Ci = {
calchypotenuse = cmd(W,R,R),
sin = cmd(W,R),
cos = cmd(W,R),
mulscale = cmd(W,R,R),
mulscale = cmd(W,R,R,R),
getangle = cmd(W,R,R),
getincangle = cmd(W,R,R),
@ -365,20 +366,20 @@ local Ci = {
tossweapon = cmd(),
wackplayer = cmd(),
-- sprite searching
findplayer = cmd(D,D),
findotherplayer = cmd(D,D),
-- player/sprite searching
findplayer = cmd(W),
findotherplayer = cmd(W),
findnearspritezvar = cmd(D,R,R,W),
findnearspritez = cmd(D,D,D,W),
findnearspritevar = cmd(D,R,W),
findnearsprite3dvar = cmd(D,R,W),
findnearsprite3d = cmd(D,D,W),
findnearspritevar = cmd(D,R,W),
findnearsprite = cmd(D,D,W),
findnearactorzvar = cmd(D,R,R,W),
findnearactorz = cmd(D,D,D,W),
findnearactorvar = cmd(D,R,W),
findnearactor3dvar = cmd(D,R,W),
findnearactor3d = cmd(D,D,W),
findnearactorvar = cmd(D,R,W),
findnearactor = cmd(D,D,W),
-- quotes
@ -407,7 +408,7 @@ local Ci = {
displayrand = cmd(W),
displayrandvar = cmd(W,D),
displayrandvarvar = cmd(W,R),
dist = cmd(W),
dist = cmd(W,R,R),
dragpoint = cmd(R,R,R),
hitscan = cmd(R,R,R,R,R,R,R,W,W,W,W,W,W,R), -- 7R 6W 1R
@ -418,7 +419,7 @@ local Ci = {
digitalnumberz = cmd(W,R,R,R,R,R,R,R,R,R,R,R), -- 1W 11R
minitext = cmd(R,R,R,R,R),
ldist = cmd(W),
ldist = cmd(W,R,R),
lineintersect = cmd(R,R,R,R,R,R,R,R,R,R,W,W,W,W), -- 10R 4W
rayintersect = cmd(R,R,R,R,R,R,R,R,R,R,W,W,W,W), -- 10R 4W
loadmapstate = cmd(),
@ -564,25 +565,85 @@ local Cif = {
}
----==== Tracing and reporting ====----
local string = require("string")
-- newlineidxs will contain the 1-based file offsets to "\n" characters
local newlineidxs = {}
local function printf(fmt, ...)
print(string.format(fmt, ...))
end
-- Returns index into the sorted table tab such that
-- tab[index] <= searchelt < tab[index+1].
-- Preconditions:
-- tab[i] < tab[i+1] for 1 <= i < #tab
-- tab[1] <= searchelt < tab[#tab]
-- If tab has less than 2 elements, returns nil.
local function bsearch(tab, searchelt)
-- printf("bsearch(tab, %d)", searchelt)
local l, r = 1, #tab
local i
if (r <= 1) then
return
end
while (l ~= r) do
i = l + math.ceil((r-l)/2) -- l < i <= r
assert(l < i and i <= r)
local elt = tab[i]
-- printf("l=%d tab[%d]=%d r=%d", l, i, elt, r)
if (searchelt == elt) then
return i
end
if (searchelt < elt) then
r = i-1
else -- (searchelt > elt)
l = i
end
end
-- printf("return tab[%d]=%d", l, tab[l])
return l
end
local function getlinecol(pos)
local line = bsearch(newlineidxs, pos)
local col = pos-newlineidxs[line]
return line, col
end
-- A generic trace function, prints a position together with the match content
-- A non-existing 'doit' means 'true'.
function TraceFunc(pat, doit)
local function TraceFunc(pat, label, doit)
pat = Pat(pat)
if (doit==nil or doit) then
pat = lpeg.Cmt(pat, function (subj, pos, a) print(pos..":"..a); return true; end)
local function tfunc(subj, pos, a)
local line, col = getlinecol(pos)
printf("%d,%d:%s:%s", line, col, label, a)
return true
end
pat = lpeg.Cmt(pat, tfunc)
end
return pat
end
-- These are tracers for specific patterns which can be disabled
-- if desired.
local function Keyw(kwname) return TraceFunc(kwname, false) end
local function Stmt(cmdpat) return TraceFunc(cmdpat, false) end
local function Keyw(kwname) return TraceFunc(kwname, "kw", true) end
local function NotKeyw(text) return TraceFunc(text, "!kw", true) end
local function Ident(idname) return TraceFunc(idname, "id", true) end
local function Stmt(cmdpat) return TraceFunc(cmdpat, "st", true) end
----==== Translator continued ====----
-- attach the command names at the front!
function attachnames(kwtab)
local function attachnames(kwtab)
for cmdname,cmdpat in pairs(kwtab) do
kwtab[cmdname] = Keyw(cmdname) * cmdpat
end
@ -596,7 +657,7 @@ attachnames(Cif)
-- Takes one or more tables and +'s all its patterns together in the order of
-- appearance.
-- The tables must map command names to their patterns.
function all_alt_pattern(...)
local function all_alt_pattern(...)
local pat = Pat(false)
local args = {...}
for argi=1,#args do
@ -614,9 +675,11 @@ local function warn_on_lonely_else(subj, pos)
return true
end
-- About prefixes: I think it's not a problem if e.g. "getactor" comes before
-- "getactorvar", because the pattern for the former will fail eventually in
-- the ordered choice if fed with the latter.
-- About prefixes: I think it's not a problem *here* if e.g. "getactor" comes
-- before "getactorvar", because the pattern for the former will fail
-- eventually in the ordered choice if fed with the latter. However, it DOES
-- matter in the keyword list, see NotKeyw() trace function and comment in
-- con_lang.lua.
local con_outer_command = all_alt_pattern(Co)
local con_inner_command = all_alt_pattern(Ci)
local con_if_begs = all_alt_pattern(Cif)
@ -668,7 +731,7 @@ local Grammar = Pat{
-- getactor[THISACTOR].x x
-- getactor [THISACTOR].y y
-- This is in need of cleanup!
t_identifier = -(con_keyword * (sp1 + "[")) * t_identifier_all,
t_identifier = -NotKeyw(con_keyword * (sp1 + "[")) * Ident(t_identifier_all),
t_define = Pat("-")^-1 * sp0 * (t_identifier + t_number),
t_arrayexp = t_identifier * arraypat * memberpat^-1,
@ -698,47 +761,15 @@ local Grammar = Pat{
stmt_list = Var("single_stmt") * (sp1 * Var("single_stmt"))^0,
}
local math = require("math")
local string = require("string")
local function printf(fmt, ...)
print(string.format(fmt, ...))
local function setup_newlineidxs(contents)
newlineidxs = {}
for i in string.gmatch(contents, "()\n") do
newlineidxs[#newlineidxs+1] = i
end
-- Returns index into the sorted table tab such that
-- tab[index] <= searchelt < tab[index+1].
-- Preconditions:
-- tab[i] < tab[i+1] for 1 <= i < #tab
-- tab[1] <= searchelt < tab[#tab]
-- If tab has less than 2 elements, returns nil.
local function bsearch(tab, searchelt)
-- printf("bsearch(tab, %d)", searchelt)
local l, r = 1, #tab
local i
if (r <= 1) then
return
end
while (l ~= r) do
i = l + math.ceil((r-l)/2) -- l < i <= r
assert(l < i and i <= r)
local elt = tab[i]
-- printf("l=%d tab[%d]=%d r=%d", l, i, elt, r)
if (searchelt == elt) then
return i
end
if (searchelt < elt) then
r = i-1
else -- (searchelt > elt)
l = i
end
end
-- printf("return tab[%d]=%d", l, tab[l])
return l
newlineidxs[#newlineidxs+1] = #contents+1 -- dummy newline
end
---=== stand-alone: ===---
@ -749,14 +780,9 @@ if (not EDUKE32_LUNATIC) then
assert(filename)
local contents = io.open(filename):read("*all")
local idx = lpeg.match(Grammar, contents)
setup_newlineidxs(contents)
-- newlineidxs will contain the 1-based file offsets to "\n" characters
local newlineidxs = {}
for i in string.gmatch(contents, "()\n") do
newlineidxs[#newlineidxs+1] = i
end
newlineidxs[#newlineidxs+1] = #contents+1 -- dummy newline
local idx = lpeg.match(Grammar, contents)
if (not idx) then
print("Match failed.")
@ -768,10 +794,12 @@ if (not EDUKE32_LUNATIC) then
return
end
printf("Match succeeded up to %d (len=%d)", idx, #contents)
local i = bsearch(newlineidxs, idx)
local i, col = getlinecol(idx)
local bi, ei = newlineidxs[i]+1, newlineidxs[i+1]-1
printf("Line goes from %d to %d", bi, ei)
printf("Match succeeded up to %d (line %d, col %d; len=%d)",
idx, i, col, #contents)
-- printf("Line goes from %d to %d", bi, ei)
print(string.sub(contents, bi, ei))
end