Package pnfg; Helpers letter = [['a' .. 'z']+['A' .. 'Z']]; digit = ['0' .. '9']; any = [0x0 .. 0xfffff]; linechar = [0x0 .. 0x09]|[0x0b .. 0x0c]|[0x0e .. 0xffff]; lf = 0x0a; cr = 0x0d; line_terminator = lf | cr | cr lf; num = '0' |['1' .. '9'](digit)*; Tokens blank = 10 | 10 13 | 9 | ' '; lb = '('; rb = ')'; lbrace = '{'; rbrace = '}'; plus = '+'; plusplus = '++'; minus = '-'; minusminus = '--'; maybeplus = '+?'; maybeminus = '-?'; plusequals = '+='; minusequals = '-='; and = '&&'; or = '||'; not = '!'; toggle = '^'; eq = '='; comma = ','; dollar = '$'; colon = ':'; sc = ';'; period = '.'; bigger = '>'; smaller = '<'; bigger_eq = '>='; smaller_eq = '<='; not_eq = '!='; equals = '=='; contains = 'contains'; move = 'move'; from = 'from'; to = 'to'; object = 'object'; room = 'room'; state = 'state'; counter = 'counter'; timer = 'timer'; number = num; for = 'for'; forall = 'forall'; if = 'if'; elseif = 'elseif'; else = 'else'; start = 'start'; enter = 'enter'; exit = 'exit'; thread = 'thread'; comment = '//' linechar* line_terminator; id = letter(letter|digit|'_')*; string = '"' ([any - '"']|'\"')* '"'; Ignored Tokens comment, blank; Productions program = decls*; decls = {set} set | {object} P.object | {actions} actiondecl | {start} startdecl | {timer} timerdecl | {thread} threaddecl; set = {setsimple}id eq lbrace elementlist rbrace | {setsubtract}id eq lbrace setname minus elementlist rbrace | {setadd}id eq lbrace setname plus elementlist rbrace; setname = id; elementlist = element elementlisttail*; elementlisttail = comma element; element = {include} id | {dontinclude} not id; object = objecthead id lbrace objectdecls* rbrace; objecthead = {object} T.object | {room} T.room; objectdecls = {state} statedecl | {action} actiondecl | {counter} counterdecl | {moveblock} moveblock; moveblock = moveblockhead lbrace cmd* rbrace; moveblockhead = {enter} enter | {exit} exit; statedecl = state lbrace statelist rbrace; statelist = id statelisttail*; statelisttail = comma id; threaddecl = {threadsimple} threadsimpledecl rbrace | {threadcond} threadconddecl rbrace; threadsimpledecl = thread lb rb lbrace cmd*; threadconddecl = thread lb counterconditional rb lbrace cmd*; timerdecl = timer lbrace counterlist rbrace; counterdecl = counter lbrace counterlist rbrace; counterlist = id number counterend counterlisttail*; counterlisttail = comma id number counterend; counterend = number; actiondecl = commandspec lbrace cmd* rbrace; startdecl = start lbrace cmd* rbrace; commandspec = commandspechead id commandspectail? rb; commandspechead = lb varordecl comma; commandspectail = comma varordecl; cmd = {output} outputstmt | {move} movestmt | {set} setstmt | {if} ifstmt | {decl} vardeclstmt | {for} forstmt | {setcounter} counterstmt; ifstmt = ifstmthead rbrace justelse?; ifstmthead = ifstmtheadhead lbrace cmd*; ifstmtheadhead = {cond} if lb conditional rb | {countercond} if lb counterconditional rb; justelse = else lbrace cmd* rbrace; forstmt = forstmthead lbrace cmd* rbrace; forstmthead = {seq} for lb vardecl rb | {par} forall lb vardecl rb; comparisons = {and} and | {or} or; conditional = {infix} condlhs comparisons value | {test} value; condlhs = value; conditionalcomparisons = {condbigger} bigger | {condsmaller} smaller | {condbigger_eq} bigger_eq | {condequals} equals | {condsmaller_eq} smaller_eq | {condnot_eq} not_eq; counterconditional = {comparison} countercondlhs conditionalcomparisons intvalue; countercondlhs = value; intvalue = number; value = {state} objectstate | {var} variable; objectstate = {var} variable period id | {contains} variable contains objectstatetail | {notvar} variable not period id | {notcontains} variable not contains objectstatetail; objectstatetail = variable; outputstmt = string sc; movestmt = movestmthead to variable sc; movestmthead = movestmtheadhead from variable; movestmtheadhead = move variable; setstmt = {set} plus variable period id sc | {unset} minus variable period id sc | {maybeset} maybeplus variable period id sc | {maybeunset} maybeminus variable period id sc | {not} toggle variable period id sc; counterstmt = {set} variable period id eq number sc | {plusplus} variable period id plusplus sc | {minusminus} variable period id minusminus sc | {plusequals} variable period id plusequals number sc | {minusequals} variable period id minusequals number sc; variable = {id} id | {var} dollar id; varordecl = {var} variable | {decl} vardecl; vardeclstmt = vardecl vardeclstmttail* sc; vardecl = vardeclstmttype dollar id; vardeclstmttype = id; vardeclstmttail = comma dollar id;