SaffronCG.ThreeC4
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Shoup, August 7, 1986 4:37:43 pm PDT
Bill Jackson (bj) April 27, 1987 5:21:12 pm PDT
Lucy Hederman July 17, 1987 3:30:10 pm PDT
Include [SaffronBaseDecls, SaffronAG];
SaffronCentral: Control Module;
SaffronCG1: Module = Begin
{
"TC"
"ABS" "ALL" "AND" "ANY" "APPLY" "ARRAY"
"BASE" "BEGIN" "BROADCAST"
"CEDAR" "CHECKED" "CODE" "COMPUTED" "CONS" "CONTINUE"
"DECREASING" "DEFINITIONS" "DEPENDENT" "DESCRIPTOR" "DIRECTORY" "DO"
"ELSE" "ENABLE" "END" "ENDCASE" "ENDLOOP" "ENTRY" "ERROR" "EXIT" "EXITS" "EXPORTS"
"FINISHED" "FIRST" "FOR" "FORK" "FRAME" "FREE" "FROM"
"GO" "GOTO"
"IF" "IMPORTS" "IN" "INLINE" "INTERNAL" "ISTYPE"
"JOIN"
"LAST" "LENGTH" "LIST" "LOCKS" "LONG" "LOOP" "LOOPHOLE"
"MACHINE" "MAX" "MIN" "MOD" "MONITOR" "MONITORED"
"NARROW" "NEW" "NIL" "NOT" "NOTIFY" "NULL"
"OF" "OPEN" "OR" "ORD" "ORDERED" "OVERLAID"
"PACKED" "PAINTED" "POINTER" "PORT" "PRED" "PRIVATE" "PROC" "PROCEDURE" "PROCESS" "PROGRAM" "PUBLIC"
"READONLY" "RECORD" "REF" "REJECT" "RELATIVE" "REPEAT" "RESTART" "RESUME" "RETRY" "RETURN" "RETURNS"
"SAFE" "SELECT" "SEQUENCE" "SHARES" "SIGNAL" "SIZE" "START" "STATE" "STOP" "SUCC"
"THEN" "THROUGH" "TO" "TRANSFER" "TRASH" "TRUSTED" "TYPE"
"UNCHECKED" "UNCOUNTED" "UNSAFE" "UNTIL" "USING"
"VAL" "VAR"
"WAIT" "WHILE" "WITH"
"ZONE"
"!" "#" "(" ")" "*" "+" "," "-" "." ".." "/" ":" ";" "<" "<=" "=" "=>" ">" ">=" "@"
"[" "]" "^" "←" "{" "|" "}" "~"
} : SimpleTokens;
maingoal: NonTerminal Builds Top;
for maingoal ← top
Buildtop;
top: NonTerminal Builds Top;
for top.modulep ← goal
BuildTop.modulep[goal];
for top.scope ← "BEGIN" scope "END"
BuildTop.scope[scope];
new grammar production
for top.scope ← "TC" typeCons
BuildTop.tc[typeCons];
goal: NonTerminal Builds ModuleP;
for goal.a ← module "."
Buildmodule;
for goal.b ← module ".."
Buildmodule;
module: NonTerminal Builds ModuleP;
for module.impl ← directory identlist cedar proghead trusted checked block
BuildModuleP.impl[directory, identlist, cedar, proghead, checked, block];
for module.def ← directory identlist cedar defhead defbody
BuildModuleP.def[directory, identlist, cedar, defhead, defbody];
directory: NonTerminal Builds Directory;
for directory.a ← "DIRECTORY" ";"
BuildDirectory.empty[];
for directory.b ← "DIRECTORY" includelist ";"
Buildincludelist;
for directory.c ← -- << empty >>
BuildDirectory.empty[];
includelist: NonTerminal Builds Directory;
for includelist.a ← includeitem
BuildDirectory.more[Directory.empty[[includeitem, includeitem)], includeitem];
for includelist.b ← includelist "," includeitem
BuildDirectory.more[includelist, includeitem];
includeitem: NonTerminal Builds IncludeItem;
for includeitem.a ← id ":" "FROM" string using
BuildIncludeItem.fromp[id, string, using];
for includeitem.b ← id ":" "TYPE" using
BuildIncludeItem.type[id, using];
for includeitem.c ← id using
BuildIncludeItem.plain[id, using];
for includeitem.d ← id.local ":" "TYPE" id.global using
BuildIncludeItem.typeandid[id.local, id.global, using];
using: NonTerminal Builds Using;
for using.nothing ← "USING" "[" "]"
BuildUsing.nothing[];
for using.restricted ← "USING" "[" idlist "]"
BuildUsing.restricted[idlist];
for using.unrestricted ← -- << empty >>
BuildUsing.unrestricted[];
defbody: NonTerminal Builds DefBody;
for defbody.a ← "BEGIN" open declist "END"
BuildDefBody[open, declist];
for defbody.b ← "BEGIN" open declist ";" "END"
BuildDefBody[open, declist];
for defbody.c ← "{" open declist "}"
BuildDefBody[open, declist];
for defbody.d ← "{" open declist ";" "}"
BuildDefBody[open, declist];
defhead: NonTerminal Builds DefHead;
for defhead ← definitions locks imports shares tilde public
BuildDefHead[locks, imports, shares, public];
definitions: NonTerminal Builds Junk;
for definitions ← "DEFINITIONS"
BuildJunk[];
cedar: NonTerminal Builds Cedar;
for cedar.yes ← "CEDAR"
BuildCedar.yes[];
for cedar.no ← -- << empty >>
BuildCedar.no[];
proghead: NonTerminal Builds ProgHead;
for proghead ← resident safe class arguments locks interface tilde public
BuildProgHead[safe, class, arguments, locks, interface, public];
resident: NonTerminal Builds Junk;
for resident ← -- << empty >>
BuildJunk[];
class: NonTerminal Builds Class;
for class.program ← "PROGRAM"
BuildClass.program[];
for class.monitor ← "MONITOR"
BuildClass.monitor[];
interface: NonTerminal Builds Interface;
for interface ← imports exports shares
BuildInterface[imports, exports, shares];
exports: NonTerminal Builds ModuleList;
for exports.a ← "EXPORTS"
BuildModuleList.empty[];
for exports.b ← "EXPORTS" modulelist
Buildmodulelist;
for exports.c ← -- << empty >>
BuildModuleList.empty[];
binditem: NonTerminal Builds BindItem;
for binditem.a ← exp
BuildBindItem.unnamed[exp];
for binditem.b ← id ":" exp
BuildBindItem.named[id, exp];
for binditem.c ← id "~" "~" exp
BuildBindItem.named[id, exp];
caselabel: NonTerminal Builds SelectLabel;
for caselabel.type ← ident typeexp
BuildSelectLabel.type[ident, typeexp];
for caselabel.test ← caselabelP
BuildSelectLabel.test[caselabelP];
caselabelP: NonTerminal Builds SelectTestList;
for caselabelP.one ← casetest
BuildSelectTestList.one[casetest];
for caselabelP.more ← caselabelP "," casetest
BuildSelectTestList.more[caselabelP, casetest];
casetest: NonTerminal Builds Relation;
for casetest.a ← optrelation
Buildoptrelation;
for casetest.b ← exp
BuildRelation.positive[RelationTail.relop[Relop.eq[[exp, exp)], exp]];
insert position info ???
block: NonTerminal Builds Block;
for block.a ← "BEGIN" scope exits "END"
BuildBlock[scope, exits];
for block.b ← "{" scope exits "}"
BuildBlock[scope, exits];
exits: NonTerminal Builds ExitList;
for exits.list ← "EXITS" exitlist
Buildexitlist;
for exits.empty ←
BuildExitList.empty[];
public: NonTerminal Builds Access;
for public.public ← "PUBLIC"
BuildAccess.public[];
for public.private ← "PRIVATE"
BuildAccess.private[];
for public.empty ← -- << empty >>
BuildAccess.empty[];
End;
SaffronCG2: Module = Begin
bounds: NonTerminal Builds Bounds;
for bounds ← exp.lower ".." exp.upper
BuildBounds[Bound[exp.lower], Bound[exp.upper]];
checked: NonTerminal Builds Checked;
for checked.empty ← -- << empty >>
BuildChecked.empty[];
for checked.checked ← "CHECKED"
BuildChecked.checked[];
for checked.trusted ← "TRUSTED"
BuildChecked.trusted[];
for checked.unchecked ← "UNCHECKED"
BuildChecked.unchecked[];
default: NonTerminal Builds Default;
for default.a ← "←" defaultopt
Builddefaultopt;
for default.empty ← -- << empty >>
BuildDefault.empty[];
positionP: NonTerminal Builds Position;
for positionP ← "(" exp optbits ")"
BuildPosition[exp, optbits];
optbits: NonTerminal Builds OptBits;
for optbits.present ← ":" bounds
BuildOptBits.present[bounds];
for optbits.absent ← -- << empty >>
BuildOptBits.absent[];
sum: NonTerminal Builds Exp;
for sum.sum ← sum addop product
BuildExp.sum[sum, addop, product];
for sum.product ← product
Buildproduct;
product: NonTerminal Builds Exp;
for product.product ← product multop factor
BuildExp.product[product, multop, factor];
for product.factor ← factor
Buildfactor;
multop: NonTerminal Builds MultOp;
for multop.times ← "*"
BuildMultOp.times[];
for multop.divide ← "/"
BuildMultOp.divide[];
for multop.mod ← "MOD"
BuildMultOp.mod[];
factor: NonTerminal Builds Exp;
for factor.unarysum ← addop primary
BuildExp.unarysum[addop, primary];
for factor.primary ← primary
Buildprimary;
addop: NonTerminal Builds AddOp;
for addop.plus ← "+"
BuildAddOp.plus[];
for addop.minus ← "-"
BuildAddOp.minus[];
readonly: NonTerminal Builds ReadOnly;
for readonly.yes ← "READONLY"
BuildReadOnly.yes[];
for readonly.no ← -- << empty >>
BuildReadOnly.no[];
catchany: NonTerminal Builds CatchAny;
for catchany ← "ANY" "=>" statement
BuildCatchAny.present[statement];
interval: NonTerminal Builds Interval;
for interval.cc ← "[" bounds "]"
BuildInterval.cc[bounds];
for interval.oc ← "(" bounds "]"
BuildInterval.oc[bounds];
for interval.co ← "[" bounds ")"
BuildInterval.co[bounds];
for interval.oo ← "(" bounds ")"
BuildInterval.oo[bounds];
exp: NonTerminal Builds Exp;
for exp.ifthenelse ← "IF" exp.cond "THEN" exp.thenpart "ELSE" exp.elsepart
BuildExp.ifthenelse[exp.cond, exp.thenpart, exp.elsepart];
for exp.select ← casehead caseexplist "ENDCASE" "=>" exp
BuildExp.select[casehead, caseexplist, exp];
for exp.assign ← lhs "←" exp
BuildExp.assign[lhs, exp];
for exp.multiassign ← "[" explist "]" "←" exp
BuildExp.multiassign[explist, exp];
for exp.error ← "ERROR"
BuildExp.error[];
for exp.transfer ← transferop lhs
BuildExp.transfer[transferop, lhs];
for exp.disjunct ← disjunct
Builddisjunct;
caseexplist: NonTerminal Builds SelectExpList;
for caseexplist.empty ← -- << empty >>
BuildSelectExpList.empty[];
for caseexplist.b ← caseexplistP
BuildcaseexplistP;
for caseexplist.c ← caseexplistP ","
BuildcaseexplistP;
caseexplistP: NonTerminal Builds SelectExpList;
for caseexplistP.a ← caseexpitem
BuildSelectExpList.more[
SelectExpList.empty[[caseexpitem, caseexpitem)],
caseexpitem
];
for caseexplistP.b ← caseexplistP "," caseexpitem
BuildSelectExpList.more[caseexplistP, caseexpitem];
caseexpitem: NonTerminal Builds SelectExpItem;
for caseexpitem ← caselabel "=>" exp
BuildSelectExpItem[caselabel, exp]
End;
SaffronCG3: Module = Begin
transferop: NonTerminal Builds TransferOp;
for transferop.signal ← "SIGNAL"
BuildTransferOp.signal[];
for transferop.error ← "ERROR"
BuildTransferOp.error[];
for transferop.start ← "START"
BuildTransferOp.start[];
for transferop.join ← "JOIN"
BuildTransferOp.join[];
for transferop.new ← "NEW"
BuildTransferOp.new[];
for transferop.fork ← "FORK"
BuildTransferOp.fork[];
disjunct: NonTerminal Builds Exp;
for disjunct.or ← disjunct "OR" conjunct
BuildExp.or[disjunct, conjunct];
for disjunct.conjunct ← conjunct
Buildconjunct;
conjunct: NonTerminal Builds Exp;
for conjunct.and ← conjunct "AND" negation
BuildExp.and[conjunct, negation];
for conjunct.negation ← negation
Buildnegation;
negation: NonTerminal Builds Exp;
for negation.a ← "~" relation
BuildExp.not[relation];
for negation.b ← "NOT" relation
BuildExp.not[relation];
for negation.relation ← relation
Buildrelation;
relation: NonTerminal Builds Exp;
for relation.relation ← sum optrelation
BuildExp.relation[sum, optrelation];
for relation.sum ← sum
Buildsum;
catchlist: NonTerminal Builds Catch;
for catchlist.a ← catchhead catchcase
BuildCatch[
CatchCaseList.more[catchhead, catchcase],
CatchAny.absent[(catchcase, catchcase]]
];
for catchlist.b ← catchhead
BuildCatch[catchhead,
CatchAny.absent[(catchhead, catchhead]]
];
for catchlist.c ← catchhead catchany
BuildCatch[catchhead, catchany];
for catchlist.d ← catchhead catchany ";"
BuildCatch[catchhead, catchany];
catchhead: NonTerminal Builds CatchCaseList;
for catchhead.empty ← -- << empty >>
BuildCatchCaseList.empty[];
for catchhead.more ← catchhead catchcase ";"
BuildCatchCaseList.more[catchhead, catchcase];
ident: NonTerminal Builds Ident;
for ident.idposition ← id positionP ":"
BuildIdent.idposition[id, positionP];
for ident.id ← id ":"
BuildIdent.id[id];
typeop: NonTerminal Builds TypeOp;
for typeop.code ← "CODE"
BuildTypeOp.code[];
for typeop.first ← "FIRST"
BuildTypeOp.first[];
for typeop.last ← "LAST"
BuildTypeOp.last[];
for typeop.nil ← "NIL"
BuildTypeOp.nil[];
idlist: NonTerminal Builds IdList;
for idlist ← idlistP
BuildidlistP;
idlistP: NonTerminal Builds IdList;
for idlistP.one ← id
BuildIdList.one[id];
for idlistP.more ← id "," idlistP
BuildIdList.more[id, idlistP];
arguments: NonTerminal Builds Arguments;
for arguments ← arglist returnlist
BuildArguments[arglist, returnlist];
arglist: NonTerminal Builds ParameterList;
for arglist.any ← "ANY"
BuildParameterList.any[];
for arglist.fieldlist ← fieldlist
Buildfieldlist;
for arglist.empty ← -- << empty >>
BuildParameterList.empty[];
returnlist: NonTerminal Builds ParameterList;
for returnlist.any ← "RETURNS" "ANY"
BuildParameterList.any[];
for returnlist.fieldlist ← "RETURNS" fieldlist
Buildfieldlist;
for returnlist.empty ← -- << empty >>
BuildParameterList.empty[];
fieldlist: NonTerminal Builds ParameterList;
for fieldlist.empty ← "[" "]"
BuildParameterList.empty[];
for fieldlist.pairlist ← "[" pairlist "]"
BuildParameterList.pairlist[pairlist];
for fieldlist.typelist ← "[" typelist "]"
BuildParameterList.typelist[typelist];
typeexp: NonTerminal Builds TypeExp;
for typeexp.a ← id
BuildTypeExp.typeid[TypeId.id[id]];
for typeexp.b ← typeid
BuildTypeExp.typeid[typeid];
for typeexp.c ← typecons
Buildtypecons;
the following nonterminal was added to handle the several varieties of numbers recognized by IO.GetCedarToken
num: NonTerminal Builds Num;
for num.decimal ← decimalnum
BuildNum.decimal[decimalnum];
for num.octal ← octalnum
BuildNum.octal[octalnum];
for num.hex ← hexnum
BuildNum.hex[hexnum];
lhs: NonTerminal Builds Exp;
for lhs.id ← id
BuildExp.id[id];
for lhs.num ← num -- several cases here
BuildExp.num[num];
for lhs.string ← string
BuildExp.string[string];
for lhs.lnum ← lnum shouldn't be a lexical entity
BuildExp.lnum[lnum];
for lhs.flnum ← flnum
BuildExp.flnum[flnum];
for lhs.char ← char
BuildExp.char[char];
for lhs.lstring ← lstring can't recognize due to IO.GetCedarToken limitation
BuildExp.lstring[lstring];
for lhs.atom ← atom
BuildExp.atom[atom];
for lhs.narrow ← "NARROW" "[" exp opttype optcatch "]"
BuildExp.narrow[exp, opttype, optcatch];
for lhs.loophole ← "LOOPHOLE" "[" exp opttype "]"
BuildExp.loophole[exp, opttype];
for lhs.apply ← "APPLY" "[" exp.rator "," exp.rand optcatch "]"
BuildExp.apply[exp.rator, exp.rand, optcatch];
for lhs.exp ← "(" exp ")"
Buildexp;
for lhs.qualifier ← lhs qualifier
BuildExp.qualifier[lhs, qualifier];
qualifier: NonTerminal Builds Qualifier;
for qualifier.prefixop ← "." prefixop
BuildQualifier.prefixop[prefixop];
for qualifier.typeop ← "." typeop
BuildQualifier.typeop[typeop];
for qualifier.size ← "." "SIZE"
BuildQualifier.size[];
for qualifier.apply ← "[" explist optcatch "]"
BuildQualifier.apply[explist, optcatch];
for qualifier.select ← "." id
BuildQualifier.select[id];
for qualifier.indirect ← "^"
BuildQualifier.indirect[];
exitlist: NonTerminal Builds ExitList;
for exitlist.empty ← -- << empty >>
BuildExitList.empty[];
for exitlist.b ← exitlistP
BuildexitlistP;
for exitlist.c ← exitlistP ";"
BuildexitlistP;
exitlistP: NonTerminal Builds ExitList;
for exitlistP.a ← exititem
BuildExitList.more[ExitList.empty[[exititem, exititem)], exititem];
for exitlistP.b ← exitlistP ";" exititem
BuildExitList.more[exitlistP, exititem];
exititem: NonTerminal Builds ExitItem;
for exititem ← idlist "=>" statement
BuildExitItem[idlist, statement];
optexp: NonTerminal Builds OptExp;
for optexp.trash ← trash
BuildOptExp.trash[];
for optexp.exp ← exp
BuildOptExp.exp[exp];
for optexp.empty ← -- << empty >>
BuildOptExp.empty[];
catchcase: NonTerminal Builds CatchCase;
for catchcase ← lhslist "=>" statement
BuildCatchCase[lhslist, statement];
lhslist: NonTerminal Builds SignalList;
for lhslist.one ← lhs
BuildSignalList.one[lhs];
for lhslist.more ← lhslist "," lhs
BuildSignalList.more[lhslist, lhs];
initialization: NonTerminal Builds Initialization;
for initialization.empty ← -- << empty >>
BuildInitialization.empty[];
for initialization.assignment ← "←" initvalue
BuildInitialization.assignment[initvalue];
for initialization.binding ← tilde initvalue
BuildInitialization.binding[initvalue];
initvalue: NonTerminal Builds InitialValue;
for initvalue.block ← procaccess trusted checked inline block
BuildInitialValue.block[checked, inline, block];
for initvalue.code ← "CODE"
BuildInitialValue.code[];
for initvalue.c ← procaccess trusted checked
"MACHINE" "CODE" "BEGIN" codelist "END"
BuildInitialValue.machinecode[checked, codelist];
for initvalue.d ← procaccess trusted checked
"MACHINE" "CODE" "{" codelist "}"
BuildInitialValue.machinecode[checked, codelist];
for initvalue.trash ← trash
BuildInitialValue.trash[];
for initvalue.exp ← exp
BuildInitialValue.exp[exp];
procaccess: NonTerminal Builds Junk;
for procaccess ← -- << empty >>
BuildJunk[];
inline: NonTerminal Builds Inline;
for inline.yes ← "INLINE"
BuildInline.yes[];
for inline.no ← -- << empty >>
BuildInline.no[];
codelist: NonTerminal Builds CodeList;
for codelist.one ← orderlist
BuildCodeList.one[orderlist];
for codelist.more ← codelist ";" orderlist
BuildCodeList.more[codelist, orderlist]
End;
SaffronCG4: Module = Begin
range: NonTerminal Builds Range;
for range.a ← id
BuildRange.typeid[TypeId.id[id]];
for range.b ← id interval
BuildRange.subrange[Subrange.named[TypeId.id[id], interval]];
for range.c ← typeid interval
BuildRange.subrange[Subrange.named[typeid, interval]];
for range.d ← interval
BuildRange.subrange[Subrange.unnamed[interval]];
for range.e ← typeid
BuildRange.typeid[typeid];
trash: NonTerminal Builds Junk;
for trash.trash ← "TRASH"
BuildJunk[];
for trash.null ← "NULL"
BuildJunk[];
defaultopt: NonTerminal Builds Default;
for defaultopt.getstrash ← trash
BuildDefault.getstrash[];
for defaultopt.getsexportrash ← exp "|" trash
BuildDefault.getsexportrash[exp];
for defaultopt.gets ← -- << empty >>
BuildDefault.gets[];
for defaultopt.getsexp ← exp
BuildDefault.getsexp[exp];
orderlist: NonTerminal Builds OrderList;
for orderlist.one ← optexp
BuildOrderList.one[optexp];
for orderlist.more ← orderlist "," optexp
BuildOrderList.more[orderlist, optexp];
trusted: NonTerminal Builds Junk;
for trusted ← -- << empty >>
BuildJunk[];
optrelation: NonTerminal Builds Relation;
for optrelation.negative ← "NOT" relationtail
BuildRelation.negative[relationtail];
for optrelation.positive ← relationtail
BuildRelation.positive[relationtail];
relationtail: NonTerminal Builds RelationTail;
for relationtail.range ← "IN" range
BuildRelationTail.range[range];
for relationtail.relop ← relop sum
BuildRelationTail.relop[relop, sum];
relop: NonTerminal Builds Relop;
for relop.eq ← "="  BuildRelop.eq[];
for relop.ne ← "#" BuildRelop.ne[];
for relop.lt ← "<" BuildRelop.lt[];
for relop.le ← "<=" BuildRelop.le[];
for relop.gt ← ">" BuildRelop.gt[];
for relop.ge ← ">=" BuildRelop.ge[];
shares: NonTerminal Builds Shares;
for shares.present ← "SHARES" idlist
BuildShares.present[idlist];
for shares.absent ← -- << empty >>
BuildShares.absent[];
statement: NonTerminal Builds Statement;
for statement.ifthen ← "IF" exp "THEN" statement
BuildStatement.ifthen[exp, statement];
for statement.ifthenelse ← "IF" exp "THEN" balstmt "ELSE" statement
BuildStatement.ifthenelse[exp, balstmt, statement];
for statement.select ← casehead casestmtlist "ENDCASE" "=>" statement
BuildStatement.select[casehead, casestmtlist, OptStatement.present[statement]];
for statement.basicstmt ← basicstmt
Buildbasicstmt;
balstmt: NonTerminal Builds Statement;
for balstmt.ifthenelse ← "IF" exp "THEN" balstmt.thenpart "ELSE" balstmt.elsepart
BuildStatement.ifthenelse[exp, balstmt.thenpart, balstmt.elsepart];
for balstmt.select ← casehead casestmtlist "ENDCASE" "=>" balstmt
BuildStatement.select[casehead, casestmtlist, OptStatement.present[balstmt]];
for balstmt.basicstmt ← basicstmt
Buildbasicstmt;
basicstmt: NonTerminal Builds Statement;
for basicstmt.exp ← lhs
BuildStatement.exp[lhs];
for basicstmt.assign ← lhs "←" exp
BuildStatement.assign[lhs, exp];
for basicstmt.multiassign ← "[" explist "]" "←" exp
BuildStatement.multiassign[explist, exp];
for basicstmt.block ← trusted checked block
BuildStatement.block[checked, block];
for basicstmt.select ← casehead casestmtlist "ENDCASE"
BuildStatement.select[casehead, casestmtlist,
OptStatement.absent[(casestmtlist, casestmtlist]]];
for basicstmt.loopcontrol ← forclause dotest "DO" scope doexit "ENDLOOP"
BuildStatement.loopcontrol[forclause, dotest, scope, doexit];
for basicstmt.exit ← "EXIT"
BuildStatement.exit[];
for basicstmt.loop ← "LOOP"
BuildStatement.loop[];
for basicstmt.i ← "GOTO" id
BuildStatement.goto[id];
for basicstmt.j ← "GO" "TO" id
BuildStatement.goto[id];
for basicstmt.return ← "RETURN" optargs
BuildStatement.return[optargs];
for basicstmt.transfer ← transfer lhs
BuildStatement.transfer[transfer, lhs];
for basicstmt.free ← free "[" exp optcatch "]"
BuildStatement.free[free, exp, optcatch];
for basicstmt.wait ← "WAIT" lhs
BuildStatement.wait[lhs];
for basicstmt.error ← "ERROR"
BuildStatement.error[];
for basicstmt.stop ← "STOP"
BuildStatement.stop[];
for basicstmt.null ← "NULL"
BuildStatement.null[];
for basicstmt.resume ← "RESUME" optargs
BuildStatement.resume[optargs];
for basicstmt.reject ← "REJECT"
BuildStatement.reject[];
for basicstmt.continue ← "CONTINUE"
BuildStatement.continue[];
for basicstmt.retry ← "RETRY"
BuildStatement.retry[];
for basicstmt.getstate ← lhs "←" "STATE"
BuildStatement.getstate[lhs];
for basicstmt.setstate ← "STATE" "←" exp
BuildStatement.setstate[exp];
forclause: NonTerminal Builds ForClause;
for forclause.assignation ← "FOR" controlid "←" exp.initial "," exp.next
BuildForClause.assignation[controlid, exp.initial, exp.next];
for forclause.iteration ← "FOR" controlid direction "IN" range
BuildForClause.iteration[controlid, direction, range];
for forclause.repetition ← "THROUGH" range
BuildForClause.repetition[range];
for forclause.empty ← -- << empty >>
BuildForClause.empty[];
controlid: NonTerminal Builds ControlId;
for controlid.new ← ident typeexp
BuildControlId.new[ident, typeexp];
for controlid.old ← id
BuildControlId.old[id];
direction: NonTerminal Builds Decreasing;
for direction.yes ← "DECREASING"
BuildDecreasing.yes[];
for direction.no ← -- << empty >>
BuildDecreasing.no[];
doexit: NonTerminal Builds DoExit;
for doexit.a ← -- << empty >>
BuildDoExit[ExitList.empty[], OptStatement.absent[]];
for doexit.b ← "REPEAT" exitlist
BuildDoExit[exitlist, OptStatement.absent[(exitlist, exitlist]]];
for doexit.c ← "REPEAT" exitlist "FINISHED" "=>" statement
BuildDoExit[exitlist, OptStatement.present[statement]];
for doexit.d ← "REPEAT" exitlist "FINISHED" "=>" statement ";"
BuildDoExit[exitlist, OptStatement.present[statement]];
transfer: NonTerminal Builds Transfer;
for transfer.signal ← "SIGNAL"
BuildTransfer.signal[];
for transfer.error ← "ERROR"
BuildTransfer.error[];
for transfer.returnwitherror ← "RETURN" "WITH" "ERROR"
BuildTransfer.returnwitherror[];
for transfer.start ← "START"
BuildTransfer.start[];
for transfer.restart ← "RESTART"
BuildTransfer.restart[];
for transfer.join ← "JOIN"
BuildTransfer.join[];
for transfer.notify ← "NOTIFY"
BuildTransfer.notify[];
for transfer.broadcast ← "BROADCAST"
BuildTransfer.broadcast[];
for transfer.transferwith ← "TRANSFER" "WITH"
BuildTransfer.transferwith[];
for transfer.returnwith ← "RETURN" "WITH"
BuildTransfer.returnwith[]
End;
SaffronCG5: Module = Begin
dotest: NonTerminal Builds DoTest;
for dotest.until ← "UNTIL" exp
BuildDoTest.until[exp];
for dotest.while ← "WHILE" exp
BuildDoTest.while[exp];
for dotest.empty ← -- << empty >>
BuildDoTest.empty[];
optargs: NonTerminal Builds OptArgs;
for optargs.explist ← "[" explist "]"
BuildOptArgs.explist[explist];
for optargs.empty ← -- << empty >>
BuildOptArgs.empty[];
for optargs.exp ← lhs
BuildOptArgs.exp[lhs];
free: NonTerminal Builds Free;
for free.plain ← "FREE"
BuildFree.plain[];
for free.zoned ← lhs "." "FREE"
BuildFree.zoned[lhs];
casestmtlist: NonTerminal Builds SelectStmtList;
for casestmtlist.empty ← -- << empty >>
BuildSelectStmtList.empty[];
for casestmtlist.b ← casestmtlistP
BuildcasestmtlistP;
for casestmtlist.c ← casestmtlistP ";"
BuildcasestmtlistP;
casestmtlistP: NonTerminal Builds SelectStmtList;
for casestmtlistP.a ← casestmtitem
BuildSelectStmtList.more[
SelectStmtList.empty[[casestmtitem, casestmtitem)],
casestmtitem];
for casestmtlistP.b ← casestmtlistP ";" casestmtitem
BuildSelectStmtList.more[casestmtlistP, casestmtitem];
casestmtitem: NonTerminal Builds SelectStmtItem;
for casestmtitem ← caselabel "=>" statement
BuildSelectStmtItem[caselabel, statement];
declist: NonTerminal Builds DecList;
for declist.one ← declaration
BuildDecList.one[declaration];
for declist.many ← declist ";" declaration
BuildDecList.many[declist, DecList.one[declaration]];
declaration: NonTerminal Builds Declaration;
for declaration.value ← identlist public entry readonly typeexp initialization
BuildDeclaration.value[identlist, public, entry, readonly, typeexp, initialization];
for declaration.type ← identlist public.id "TYPE" tilde public.type typeexp default
BuildDeclaration.type[identlist, public.id, public.type, typeexp, default];
for declaration.opaquetype ← identlist public "TYPE" optsize
BuildDeclaration.opaquetype[identlist, public, optsize];
entry: NonTerminal Builds Entry;
for entry.entry ← "ENTRY"
BuildEntry.entry[];
for entry.internal ← "INTERNAL"
BuildEntry.internal[];
for entry.empty ← -- << empty >>
BuildEntry.empty[];
optsize: NonTerminal Builds OptSize;
for optsize.present ← "[" exp "]"
BuildOptSize.present[exp];
for optsize.absent ← -- << empty >>
BuildOptSize.absent[];
primary: NonTerminal Builds Exp;
for primary.explist ← "[" explist "]"
BuildExp.explist[explist];
for primary.prefixop ← prefixop "[" orderlist "]"
BuildExp.prefixop[prefixop, orderlist];
for primary.val ← "VAL" "[" orderlist "]"
BuildExp.val[orderlist];
for primary.all ← "ALL" "[" orderlist "]"
BuildExp.all[orderlist];
for primary.new ← new "[" typeexp initialization optcatch "]"
BuildExp.new[new, typeexp, initialization, optcatch];
for primary.cons ← cons "[" explist optcatch "]"
BuildExp.cons[cons, explist, optcatch];
for primary.listcons ← listcons "[" explist "]"
BuildExp.listcons[listcons, explist];
for primary.nil ← "NIL"
BuildExp.nil[];
for primary.typeop ← typeop "[" typeexp "]"
BuildExp.typeop[typeop, typeexp];
for primary.size ← "SIZE" "[" typeexp "]"
BuildExp.size[typeexp];
for primary.size2 ← "SIZE" "[" typeexp "," exp "]"
BuildExp.size2[typeexp, exp];
for primary.istype ← "ISTYPE" "[" exp "," typeexp "]"
BuildExp.istype[exp, typeexp];
for primary.address ← "@" lhs
BuildExp.address[lhs];
for primary.descriptor ← "DESCRIPTOR" "[" desclist "]"
BuildExp.descriptor[desclist];
for primary.lhs ← lhs
Buildlhs;
new: NonTerminal Builds New;
for new.plain ← "NEW"
BuildNew.plain[];
for new.zoned ← lhs "." "NEW"
BuildNew.zoned[lhs];
cons: NonTerminal Builds Cons;
for cons.plain ← "CONS"
BuildCons.plain[];
for cons.zoned ← lhs "." "CONS"
BuildCons.zoned[lhs];
listcons: NonTerminal Builds ListCons;
for listcons.plain ← "LIST"
BuildListCons.plain[];
for listcons.zoned ← lhs "." "LIST"
BuildListCons.zoned[lhs];
desclist: NonTerminal Builds DescList;
for desclist.explicit ← exp.base "," exp.length opttype
BuildDescList.explicitlength[exp.base, exp.length, opttype];
for desclist.default ← exp
BuildDescList.defaultlength[exp];
optcatch: NonTerminal Builds Catch;
for optcatch.catchlist ← "!" catchlist
Buildcatchlist;
for optcatch.empty ← -- << empty >>
BuildCatch[CatchCaseList.empty[], CatchAny.absent[]];
identlist: NonTerminal Builds IdentList;
for identlist ← identlistP
BuildidentlistP;
identlistP: NonTerminal Builds IdentList;
for identlistP.a ← id ":"
BuildIdentList.one[Ident.id[id]];
for identlistP.b ← id positionP ":"
BuildIdentList.one[Ident.idposition[id, positionP]];
for identlistP.c ← id "," identlistP
BuildIdentList.many[IdentList.one[Ident.id[id]], identlistP];
for identlistP.d ← id positionP "," identlistP
BuildIdentList.many[IdentList.one[Ident.idposition[id, positionP]], identlistP];
prefixop: NonTerminal Builds PrefixOp;
for prefixop.long ← "LONG"
BuildPrefixOp.long[];
for prefixop.abs ← "ABS"
BuildPrefixOp.abs[];
for prefixop.pred ← "PRED"
BuildPrefixOp.pred[];
for prefixop.succ ← "SUCC"
BuildPrefixOp.succ[];
for prefixop.ord ← "ORD"
BuildPrefixOp.ord[];
for prefixop.min ← "MIN"
BuildPrefixOp.min[];
for prefixop.max ← "MAX"
BuildPrefixOp.max[];
for prefixop.base ← "BASE"
BuildPrefixOp.base[];
for prefixop.length ← "LENGTH"
BuildPrefixOp.length[]
End;
SaffronCG6: Module = Begin
typecons: NonTerminal Builds TypeExp;
for typecons.a ← interval
BuildTypeExp.subrange[Subrange.unnamed[interval]];
for typecons.b ← id interval
BuildTypeExp.subrange[Subrange.named[TypeId.id[id], interval]];
for typecons.c ← typeid interval
BuildTypeExp.subrange[Subrange.named[typeid, interval]];
for typecons.enum ← dependent "{" elementlist "}"
BuildTypeExp.enum[dependent, elementlist];
for typecons.record ← dependent monitored "RECORD" reclist
BuildTypeExp.record[dependent, monitored, reclist];
for typecons.pointer ← ordered base pointertype
BuildTypeExp.pointer[ordered, base, pointertype];
for typecons.var ← "VAR" typeexp
BuildTypeExp.var[typeexp];
for typecons.ref ← "REF" readonly typeexp
BuildTypeExp.ref[readonly, typeexp];
for typecons.refany ← "REF" readonly "ANY"
BuildTypeExp.refany[readonly];
for typecons.refunspecified ← "REF"
BuildTypeExp.refunspecified[];
for typecons.list ← "LIST" "OF" readonly typeexp
BuildTypeExp.list[readonly, typeexp];
for typecons.array ← packed "ARRAY" indextype "OF" typeexp
BuildTypeExp.array[packed, indextype, typeexp];
for typecons.descriptor ← "DESCRIPTOR" "FOR" readonly typeexp
BuildTypeExp.descriptor[readonly, typeexp];
for typecons.transfer ← safe transfermode arguments
BuildTypeExp.transfer[safe, transfermode, arguments];
for typecons.o ← id "RELATIVE" typeexp
BuildTypeExp.relative[TypeId.id[id], typeexp];
for typecons.p ← typeid "RELATIVE" typeexp
BuildTypeExp.relative[typeid, typeexp];
for typecons.zone ← heap "ZONE"
BuildTypeExp.zone[heap];
for typecons.long ← "LONG" typeexp
BuildTypeExp.long[typeexp];
for typecons.frame ← "FRAME" "[" id "]"
BuildTypeExp.frame[id];
for typecons.t ← id "PAINTED" typeexp
BuildTypeExp.painted[TypeId.id[id], typeexp];
for typecons.u ← typeid "PAINTED" typeexp
BuildTypeExp.painted[typeid, typeexp];
for typecons.typeapply ← typeappl
BuildTypeExp.typeapply[typeappl];
dependent: NonTerminal Builds MachineDependent;
for dependent.yes ← "MACHINE" "DEPENDENT"
BuildMachineDependent.yes[];
for dependent.no ← -- << empty >>
BuildMachineDependent.no[];
monitored: NonTerminal Builds Monitored;
for monitored.yes ← "MONITORED"
BuildMonitored.yes[];
for monitored.no ← -- << empty >>
BuildMonitored.no[];
ordered: NonTerminal Builds Ordered;
for ordered.yes ← "ORDERED"
BuildOrdered.yes[];
for ordered.no ← -- << empty >>
BuildOrdered.no[];
base: NonTerminal Builds Base;
for base.yes ← "BASE"
BuildBase.yes[];
for base.no ← -- << empty >>
BuildBase.no[];
pointertype: NonTerminal Builds PointerType;
for pointertype.unspecified ← pointerprefix
BuildPointerType.unspecified[pointerprefix];
for pointertype.specified ← pointerprefix "TO" readonly typeexp
BuildPointerType.specified[pointerprefix, readonly, typeexp];
pointerprefix: NonTerminal Builds OptInterval;
for pointerprefix.absent ← "POINTER"
BuildOptInterval.absent[];
for pointerprefix.present ← "POINTER" interval
BuildOptInterval.present[interval];
indextype: NonTerminal Builds OptType;
for indextype.present ← typeexp
BuildOptType.present[typeexp];
for indextype.absent ← -- << empty >>
BuildOptType.absent[];
transfermode: NonTerminal Builds TransferMode;
for transfermode.a ← "PROCEDURE"
BuildTransferMode.proc[];
for transfermode.b ← "PROC"
BuildTransferMode.proc[];
for transfermode.port ← "PORT"
BuildTransferMode.port[];
for transfermode.signal ← "SIGNAL"
BuildTransferMode.signal[];
for transfermode.error ← "ERROR"
BuildTransferMode.error[];
for transfermode.process ← "PROCESS"
BuildTransferMode.process[];
for transfermode.program ← "PROGRAM"
BuildTransferMode.program[];
elementlist: NonTerminal Builds ElementList;
for elementlist.empty ← -- << empty >>
BuildElementList.empty[];
for elementlist.b ← elementlistP
BuildelementlistP;
elementlistP: NonTerminal Builds ElementList;
for elementlistP.a ← element
BuildElementList.more[ElementList.empty[[element, element)], element];
for elementlistP.b ← elementlistP "," element
BuildElementList.more[elementlistP, element];
element: NonTerminal Builds Element;
for element.idwithrep ← id "(" exp ")"
BuildElement.idwithrep[id, exp];
for element.anon ← "(" exp ")"
BuildElement.anonymousrep[exp];
for element.id ← id
BuildElement.id[id];
heap: NonTerminal Builds Uncounted;
for heap.yes ← "UNCOUNTED"
BuildUncounted.yes[];
for heap.no ← -- << empty >>
BuildUncounted.no[];
typeappl: NonTerminal Builds TypeApply;
for typeappl.a ← typeappl "." id
BuildTypeApply.moreids[typeappl, id];
for typeappl.b ← id lengthP
BuildTypeApply.one[TypeId.id[id], lengthP];
for typeappl.c ← typeid lengthP
BuildTypeApply.one[typeid, lengthP];
for typeappl.d ← typeappl lengthP
BuildTypeApply.morelengths[typeappl, lengthP];
lengthP: NonTerminal Builds Exp;
for lengthP ← "[" exp "]"
Buildexp;
reclist: NonTerminal Builds RecList;
for reclist.a ← "[" "]"
BuildRecList.empty[];
for reclist.b ← "NULL"
BuildRecList.empty[];
for reclist.c ← "[" pairlist "]"
BuildRecList.pairlist[pairlist];
for reclist.d ← "[" typelist "]"
BuildRecList.typelist[typelist];
for reclist.e ← "[" pairlist "," variantpair "]"
BuildRecList.pairlist[PairList.many[pairlist, PairList.one[variantpair]]];
for reclist.f ← "[" variantpart default "]"
BuildRecList.typelist[TypeList.one[TypeItem[variantpart, default]]];
for reclist.g ← "[" variantpair "]"
BuildRecList.pairlist[PairList.one[variantpair]];
variantpair: NonTerminal Builds PairItem;
for variantpair ← identlist public variantpart default
BuildPairItem[identlist, public, variantpart, default];
variantpart: NonTerminal Builds TypeExp;
for variantpart.a ← "SELECT" vcasehead "FROM" variantlist "ENDCASE"
BuildTypeExp.union[vcasehead, variantlist];
for variantpart.b ← "SELECT" vcasehead "FROM" variantlist "," "ENDCASE"
BuildTypeExp.union[vcasehead, variantlist];
for variantpart.c ← packed "SEQUENCE" vcasehead "OF" typeexp
BuildTypeExp.sequence[packed, vcasehead, typeexp];
vcasehead: NonTerminal Builds Tag;
for vcasehead.ident ← ident public tagtype
BuildTag.ident[ident, public, tagtype];
for vcasehead.computed ← "COMPUTED" tagtype
BuildTag.computed[tagtype];
for vcasehead.overlaid ← "OVERLAID" tagtype
BuildTag.overlaid[tagtype];
tagtype: NonTerminal Builds TagType;
for tagtype.star ← "*"
BuildTagType.star[];
for tagtype.typeexp ← typeexp
BuildTagType.typeexp[typeexp];
variantlist: NonTerminal Builds VariantList;
for variantlist.one ← variantitem
BuildVariantList.one[variantitem];
for variantlist.more ← variantlist "," variantitem
BuildVariantList.more[variantlist, variantitem];
variantitem: NonTerminal Builds VariantItem;
for variantitem ← idlist "=>" reclist
BuildVariantItem[idlist, reclist];
packed: NonTerminal Builds Packed;
for packed.yes ← "PACKED"
BuildPacked.yes[];
for packed.no ← -- << empty >>
BuildPacked.no[];
imports: NonTerminal Builds ModuleList;
for imports.a ← "IMPORTS"
BuildModuleList.empty[];
for imports.b ← "IMPORTS" modulelist
Buildmodulelist;
for imports.c ← -- << empty >>
BuildModuleList.empty[];
opttype: NonTerminal Builds OptType;
for opttype.present ← "," typeexp
BuildOptType.present[typeexp];
for opttype.absent ← -- << empty >>
BuildOptType.absent[]
End;
SaffronCG7: Module = Begin
typelist: NonTerminal Builds TypeList;
for typelist.a ← typecons default
BuildTypeList.one[TypeItem[
typecons, default]];
for typelist.b ← typeid default
BuildTypeList.one[TypeItem[
TypeExp.typeid[typeid], default]];
for typelist.c ← id
BuildTypeList.one[TypeItem[
TypeExp.typeid[TypeId.id[id]], Default.empty[(id,id]]]];
for typelist.d ← id "←" defaultopt
BuildTypeList.one[TypeItem[
TypeExp.typeid[TypeId.id[id]], defaultopt]];
for typelist.e ← typecons default "," typelist
BuildTypeList.many[TypeList.one[TypeItem[
typecons, default]], typelist];
for typelist.f ← typeid default "," typelist
BuildTypeList.many[TypeList.one[TypeItem[
TypeExp.typeid[typeid], default]], typelist];
for typelist.g ← id "," typelist
BuildTypeList.many[TypeList.one[TypeItem[
TypeExp.typeid[TypeId.id[id]], Default.empty[(id,id]]]], typelist];
for typelist.h ← id "←" defaultopt "," typelist
BuildTypeList.many[TypeList.one[TypeItem[
TypeExp.typeid[TypeId.id[id]], defaultopt]], typelist];
modulelist: NonTerminal Builds ModuleList;
for modulelist.a ← moduleitem
BuildModuleList.more[ModuleList.empty[[moduleitem, moduleitem)], moduleitem];
for modulelist.b ← modulelist "," moduleitem
BuildModuleList.more[modulelist, moduleitem];
moduleitem: NonTerminal Builds ModuleItem;
for moduleitem.one ← id
BuildModuleItem.one[id];
for moduleitem.two ← id.record ":" id.type
BuildModuleItem.two[id.record, id.type];
tilde: NonTerminal Builds Junk;
for tilde.a ← "~"
BuildJunk[];
for tilde.b ← "="
BuildJunk[];
pairlist: NonTerminal Builds PairList;
for pairlist.one ← pairitem
BuildPairList.one[pairitem];
for pairlist.many ← pairlist "," pairitem
BuildPairList.many[pairlist, PairList.one[pairitem]];
pairitem: NonTerminal Builds PairItem;
for pairitem ← identlist public typeexp default
BuildPairItem[identlist, public, typeexp, default];
typeid: NonTerminal Builds TypeId;
for typeid.a ← id.a id.b
BuildTypeId.qualifier[TypeId.id[id.b], id.a];
for typeid.b ← id typeid
BuildTypeId.qualifier[typeid, id];
for typeid.c ← typeidP
BuildtypeidP;
typeidP: NonTerminal Builds TypeId;
for typeidP.a ← id.a "." id.b
BuildTypeId.qualifier[TypeId.id[id.a], id.b];
for typeidP.b ← typeidP "." id
BuildTypeId.qualifier[typeidP, id];
explist: NonTerminal Builds ExpList;
for explist.orderlist ← orderlist
BuildExpList.orderlist[orderlist];
for explist.keylist ← keylist
BuildExpList.keylist[keylist];
keylist: NonTerminal Builds KeyList;
for keylist.one ← keyitem
BuildKeyList.one[keyitem];
for keylist.more ← keylist "," keyitem
BuildKeyList.more[keylist, keyitem];
keyitem: NonTerminal Builds KeyItem;
for keyitem.a ← id "~" optexp
BuildKeyItem[id, optexp];
for keyitem.b ← id ":" optexp
BuildKeyItem[id, optexp];
locks: NonTerminal Builds Locks;
for locks.present ← "LOCKS" primary lambda
BuildLocks.present[primary, lambda];
for locks.absent ← -- << empty >>
BuildLocks.absent[];
lambda: NonTerminal Builds Lambda;
for lambda.present ← "USING" ident typeexp
BuildLambda.present[ident, typeexp];
for lambda.absent ← -- << empty >>
BuildLambda.absent[];
open: NonTerminal Builds BindList;
for open.bindlist ← "OPEN" bindlist ";"
Buildbindlist;
for open.empty ← -- << empty >>
BuildBindList.empty[];
bindlist: NonTerminal Builds BindList;
for bindlist.item ← binditem
BuildBindList.more[BindList.empty[[binditem, binditem)], binditem];
for bindlist.list ← bindlist "," binditem
BuildBindList.more[bindlist, binditem];
casehead: NonTerminal Builds SelectHead;
for casehead.plain ← "SELECT" exp "FROM"
BuildSelectHead.plain[exp];
for casehead.discrim ← "WITH" binditem "SELECT" optexp "FROM"
BuildSelectHead.discriminating[binditem, optexp];
scope: NonTerminal Builds Scope;
for scope.a ← open enables statementlist
BuildScope[open, enables, OptDecList.absent[[statementlist, statementlist)], statementlist];
for scope.b ← open enables declist ";" statementlist
BuildScope[open, enables, OptDecList.present[declist], statementlist];
enables: NonTerminal Builds Catch;
for enables.a ← "ENABLE" catchcase ";"
BuildCatch[
CatchCaseList.more[CatchCaseList.empty[[catchcase, catchcase)], catchcase], CatchAny.absent[(catchcase, catchcase]
]];
for enables.b ← "ENABLE" catchany ";"
BuildCatch[CatchCaseList.empty[[catchany, catchany)], catchany];
for enables.c ← "ENABLE" "BEGIN" catchlist "END" ";"
Buildcatchlist;
for enables.d ← "ENABLE" "{" catchlist "}" ";"
Buildcatchlist;
for enables.e ← -- << empty >>
BuildCatch[CatchCaseList.empty[], CatchAny.absent[]];
statementlist: NonTerminal Builds StatementList;
for statementlist.empty ← -- << empty >>
BuildStatementList.empty[];
for statementlist.b ← statementlistP
BuildstatementlistP;
for statementlist.c ← statementlistP ";"
BuildstatementlistP;
statementlistP: NonTerminal Builds StatementList;
for statementlistP.a ← statement
BuildStatementList.more[StatementList.empty[[statement, statement)], statement];
for statementlistP.b ← statementlistP ";" statement
BuildStatementList.more[statementlistP, statement];
safe: NonTerminal Builds Safe;
for safe.empty ← -- << empty >>
BuildSafe.empty[];
for safe.no ← "UNSAFE"
BuildSafe.no[];
for safe.yes ← "SAFE"
BuildSafe.yes[]
End.
eof...