%%% %%% Authors: %%% Leif Kornstaedt <kornstae@ps.uni-sb.de> %%% Andreas Sundstroem <andreas@sics.se> %%% %%% Copyright: %%% Leif Kornstaedt, 1998 %%% Andreas Sundstroem, 1998 %%% %%% Last change: %%% $Date: 1999-03-26 16:37:16 +0100 (Fri, 26 Mar 1999) $Author: %%% $Revision: %%% %%% This file is part of Mozart, an implementation of Oz 3: %%% http://www.mozart-oz.org %%% %%% See the file "LICENSE" or %%% http://www.mozart-oz.org/LICENSE.html %%% for information on usage and redistribution %%% of this file, and for a DISCLAIMER OF ALL %%% WARRANTIES. %%% OzParser GP = GumpParser.'class' fun {MakeLongPos Pos1 Pos2} pos(Pos1.1 Pos1.2 Pos1.3 Pos2.1 Pos2.2 Pos2.3) end parser OzParser from GP feat Reporter Scanner attr allowDeprecated meth init(allowDeprecated:AllowDeprecated 'scanner':Scan reporter:Report) self.Reporter = Report self.Scanner = Scan allowDeprecated <- AllowDeprecated GP, init(Scan) end meth checkDeprecated(Coord) Msg = 'use `if\' instead of `case\' for boolean conditionals' in if @allowDeprecated then OzParser, reportWarning(Coord 'deprecation warning' Msg) else OzParser, reportError(Coord 'deprecation error' Msg) end end meth error(VS) OzParser, reportError({self.Scanner parseErrorCoordinates($)} 'parse error' VS) end meth reportError(C K M) {self.Reporter error(coord:C kind:K msg:M)} end meth reportWarning(C K M) {self.Reporter warn(coord:C kind:K msg:M)} end %----------------------------------------------------------------- % Token Declarations and Precedences %----------------------------------------------------------------- token % compiler directives: 'switch' 'pushSwitches' 'popSwitches' 'localSwitches' 'SWITCHNAME' 'ATOM' 'ATOM()' 'FLOAT' 'INT' 'STRING' 'VARIABLE' 'VARIABLE()' '<=' '[]' '...' 'at' 'attr' 'case' 'catch' 'choice' 'class' 'cond' 'declare' 'define' 'dis' 'else' 'elsecase' 'elseif' 'elseof' 'end' 'export' 'fail' 'false' 'false()' 'feat' 'finally' 'from' 'fun' 'functor' 'if' 'in' 'import' 'local' 'lock' 'meth' 'not' 'of' 'or' 'proc' 'prop' 'prepare' 'raise' 'require' 'self' 'skip' 'then' 'thread' 'true' 'true()' 'try' 'unit' 'unit()' '=': rightAssoc(100) '<-': rightAssoc(200) 'orelse': rightAssoc(300) 'andthen': rightAssoc(400) 'Compare': nonAssoc(500) 'FdCompare': nonAssoc(500) 'FdIn': leftAssoc(600) '|': rightAssoc(700) % '#': rightAssoc(800) % not needed: hard coded 'Add': leftAssoc(900) 'FdMul': leftAssoc(1000) 'OtherMul': leftAssoc(1000) ',': rightAssoc(1100) '~': leftAssoc(1200) '.': leftAssoc(1300) '^': leftAssoc(1300) '@': leftAssoc(1400) '!!': leftAssoc(1400) 'REGEX' '=>' '//' 'lex' 'mode' 'parser' 'prod' 'scanner' 'syn' 'token' %-------------------------------------------------------------------- % The Syntax Rules %-------------------------------------------------------------------- syn file($) Queries($) end syn Queries($) Sequence(S) Queries1(Qs) => S|Qs [] Ps=( ProdClause($) )+ Queries1(Qs) => fSynTopLevelProductionTemplates(Ps)|Qs [] Queries1($) [] ThisCoord(C1) FDs = ( FunctorDescriptor($) )+ Queries1(Qs) => fFunctor(fDollar(C1) FDs C1)|Qs end syn Queries1($) Directive(D) Queries(Qs) => D|Qs [] 'declare'(C) Sequence(S) 'in' ThisCoord(C2) Queries1(Qs) => fDeclare(S fSkip(C2) C)|Qs [] 'declare'(C) Sequence(S1) 'in' Sequence(S2) Queries1(Qs) => fDeclare(S1 S2 C)|Qs [] 'declare'(C1) Sequence(S) ThisCoord(C2) Queries1(Qs) => fDeclare(S fSkip(C2) C1)|Qs [] skip => nil end syn Directive($) 'switch' Ss=Switch($)* => dirSwitch(Ss) [] 'pushSwitches' => dirPushSwitches [] 'popSwitches' => dirPopSwitches [] 'localSwitches' => dirLocalSwitches end syn Switch($) '+' ThisCoord(C) 'SWITCHNAME'(S) => case S of 'gump' then {self.Scanner gumpSyntax(on)} [] 'allowdeprecated' then allowDeprecated <- true else skip end on(S C) [] '-' ThisCoord(C) 'SWITCHNAME'(S) => case S of 'gump' then {self.Scanner gumpSyntax(off)} [] 'allowdeprecated' then allowDeprecated <- false else skip end off(S C) end syn Sequence($) Phrase($) [] Phrase(P) Sequence(S) => fAnd(P S) end syn Phrase($) Phrase(P1) '='(C) Phrase(P2) => fEq(P1 P2 C) [] Phrase(P1) '<-'(C) Phrase(P2) => fAssign(P1 P2 C) [] Phrase(P1) 'orelse'(C) Phrase(P2) => fOrElse(P1 P2 C) [] Phrase(P1) 'andthen'(C) Phrase(P2) => fAndThen(P1 P2 C) [] Phrase(P1) 'Compare'(Op) Coord(C) Phrase(P2) => fOpApply(Op [P1 P2] C) [] Phrase(P1) 'FdCompare'(Op) Coord(C) Phrase(P2) => fFdCompare(Op P1 P2 C) [] Phrase(P1) 'FdIn'(Op) Coord(C) Phrase(P2) => fFdIn(Op P1 P2 C) [] Phrase(P1) '|'(C) Phrase(P2) => fRecord(fAtom('|' C) [P1 P2]) [] Phrase2($) [] Phrase2(P1) '#'(C) Pr=( Phrase2($) // '#' )+ => fRecord(fAtom('#' C) P1|Pr) end syn Phrase2($) Phrase2(P1) 'Add'(Op) Coord(C) Phrase2(P2) => fOpApply(Op [P1 P2] C) [] Phrase2(P1) 'FdMul'(Op) Coord(C) Phrase2(P2) => fOpApply(Op [P1 P2] C) [] Phrase2(P1) 'OtherMul'(Op) Coord(C) Phrase2(P2) => fOpApply(Op [P1 P2] C) [] Phrase2(P1) ','(C) Phrase2(P2) => fObjApply(P1 P2 C) [] '~'(C) Phrase2(P) => fOpApply('~' [P] C) [] Phrase2(P1) '.'(C) Phrase2(P2) => fOpApply('.' [P1 P2] C) [] Phrase2(P1) '^'(C) Phrase2(P2) => fOpApply('^' [P1 P2] C) [] '@'(C) Phrase2(P) => fAt(P C) [] '!!'(C) Phrase2(P) => fOpApply('!!' [P] C) [] '(' InSequence(S) ')' => S [] Atom($) [] Variable($) [] '_'(C) => fWildcard(C) [] 'unit'(C) => fAtom(unit C) [] 'true'(C) => fAtom(true C) [] 'false'(C) => fAtom(false C) [] 'self'(C) => fSelf(C) [] '$'(C) => fDollar(C) [] String($) [] Int($) [] Float($) [] Label(L) '(' RecordArguments(As) ')'(C2) => case L of fAtom(A C1) then fRecord(fAtom(A {MakeLongPos C1 C2}) As) [] fVar(V C1) then fRecord(fVar(V {MakeLongPos C1 C2}) As) end [] Label(L) '(' RecordArguments(As) '...' ')'(C2) => case L of fAtom(A C1) then fOpenRecord(fAtom(A {MakeLongPos C1 C2}) As) [] fVar(V C1) then fOpenRecord(fVar(V {MakeLongPos C1 C2}) As) end [] '['(C1) Ps=( Phrase($) )+ ']'(C2) => {FoldR Ps fun {$ P In} fRecord(fAtom('|' {MakeLongPos C1 C2}) [P In]) end fAtom('nil' {MakeLongPos C1 C2})} [] '{'(C1) Phrase(P) Ps=Phrase($)* '}'(C2) => fApply(P Ps {MakeLongPos C1 C2}) [] 'proc'(C1) ProcFlags=( Atom($) )* '{' Phrase(P1) Ps=Phrase($)* '}' InSequence(S) 'end'(C2) => fProc(P1 Ps S ProcFlags {MakeLongPos C1 C2}) [] 'fun'(C1) ProcFlags=( Atom($) )* '{' Phrase(P1) Ps=Phrase($)* '}' InSequence(S) 'end'(C2) => fFun(P1 Ps S ProcFlags {MakeLongPos C1 C2}) [] 'functor'(C1) P = ( Phrase($) [] ThisCoord(C3) => fDollar(C3)) FDs = ( FunctorDescriptor($) )* 'end'(C2) => fFunctor(P FDs {MakeLongPos C1 C2}) [] Class($) [] 'local'(C) Sequence(S1) 'in' Sequence(S2) 'end' => fLocal(S1 S2 C) [] 'if'(C) IfMain(C $) [] 'case'(C) CaseMain(C $) [] 'lock'(C1) InSequence(S) 'end'(C2) => fLock(S {MakeLongPos C1 C2}) [] 'lock'(C) ThisCoord(_) Phrase(P) 'then' InSequence(S) 'end' => fLockThen(P S C) [] 'thread'(C) InSequence(S) 'end' => fThread(S C) [] 'try'(C) InSequence(S) Catch=( 'catch'(C) Cs=( CaseClause($) // '[]' )+ => fCatch(Cs C) [] skip => fNoCatch ) Finally=( 'finally' InSequence($) [] skip => fNoFinally ) 'end' => fTry(S Catch Finally C) [] 'raise'(C) InSequence(S) 'end' => fRaise(S C) [] 'skip'(C) => fSkip(C) [] 'fail'(C) => fFail(C) [] 'not'(C1) InSequence(S) 'end'(C2) => fNot(S {MakeLongPos C1 C2}) [] 'cond'(C) CondMain(C $) [] 'or'(C1) OrClauseList(Cs) 'end'(C2) => fOr(Cs {MakeLongPos C1 C2}) [] 'dis'(C1) OrClauseList(Cs) 'end'(C2) => fDis(Cs {MakeLongPos C1 C2}) [] 'choice'(C1) ChoiceClauseList(Cs) 'end'(C2) => fChoice(Cs {MakeLongPos C1 C2}) [] ScannerSpecification($) [] ParserSpecification($) end syn InSequence($) ThisCoord(C) Sequence(S1) 'in' Sequence(S2) => fLocal(S1 S2 C) [] ThisCoord(_) Sequence($) end syn Label($) 'ATOM()'(X) Coord(C) => fAtom(X C) [] 'VARIABLE()'(X) Coord(C) => fVar(X C) [] 'unit()'(C) => fVar('`unit`' C) [] 'true()'(C) => fVar('`true`' C) [] 'false()'(C) => fVar('`false`' C) end syn RecordArguments($) ( Phrase($) [] Feature(F) ':' Phrase(P) => fColon(F P) )* end syn Feature($) Atom($) [] NakedVariable($) [] Int($) [] 'unit'(C) => fVar('`unit`' C) [] 'true'(C) => fVar('`true`' C) [] 'false'(C) => fVar('`false`' C) end syn IfMain(C1 $) Sequence(S1) 'then' InSequence(S2) IfRest(P) Coord(C2) => fBoolCase(S1 S2 P {MakeLongPos C1 !C2}) end syn IfRest($) 'elseif'(C) IfMain(C $) [] 'elsecase'(C) CaseMain(C $) [] 'else' InSequence(S) 'end' => S [] 'end'(C) => fSkip(C) end syn CaseMain(C1 $) Sequence(S1) 'then'(C3) InSequence(S2) CaseRest(P) Coord(C2) => OzParser, checkDeprecated(C3) fBoolCase(S1 S2 P {MakeLongPos C1 C2}) [] Sequence(S) 'of' Cs = ( CaseClause($) // ( '[]' [] 'elseof' ) )+ CaseRest(P) Coord(C2) => fCase(S Cs P {MakeLongPos C1 C2}) end syn CaseRest($) 'elseif'(C) IfMain(C $) [] 'elsecase'(C) CaseMain(C $) [] 'else' InSequence(S) 'end' => S [] 'end'(C) => fNoElse(C) end syn CaseClause($) SideCondition(S1) 'then' InSequence(S2) => fCaseClause(S1 S2) end syn SideCondition($) Pattern($) [] Pattern(P) 'andthen'(C) Sequence(S) => fSideCondition(P fSkip(C) S C) [] Pattern(P) 'andthen'(C) Sequence(S1) 'in' Sequence(S2) => fSideCondition(P S1 S2 C) end syn Pattern($) Pattern(P1) '='(C) Pattern(P2) => fEq(P1 P2 C) [] Pattern(P1) '|'(C) Pattern(P2) => fRecord(fAtom('|' C) [P1 P2]) [] Phrase2($) [] Phrase2(P) '#'(C) Hs = ( Phrase2($) // '#' )+ => fRecord(fAtom('#' C) P|Hs) end syn Atom($) 'ATOM'(X) Coord(C) => fAtom(X C) end syn NakedVariable($) 'VARIABLE'(X) Coord(C) => fVar(X C) end syn Variable($) NakedVariable($) [] '!'(C1) 'VARIABLE'(X) Coord(C2) => fEscape(fVar(X C2) C1) end syn String($) 'STRING'(S) Coord(C) => {FoldR S fun {$ X In} fRecord(fAtom('|' C) [fInt(X C) In]) end fAtom('nil' C)} end syn Int($) 'INT'(X) Coord(C) => fInt(X C) end syn Float($) 'FLOAT'(X) Coord(C) => fFloat(X C) end syn ThisCoord($) skip => {self.Scanner getCoordinates($)} end syn Coord($) skip => {self.Scanner getSavedCoordinates($)} end %-------------------------------------------------------------------- % Class Extensions %-------------------------------------------------------------------- syn Class($) 'class'(C1) PhraseOpt(P) Ds=ClassDescriptor($)* Ms=Meth($)* 'end'(C2) => fClass(P Ds Ms {MakeLongPos C1 C2}) end syn PhraseOpt($) Phrase($) [] ThisCoord(C) => fDollar(C) end syn ClassDescriptor($) 'from'(C) Ps=Phrase($)+ => fFrom(Ps C) [] 'attr'(C) As=AttrFeat($)+ => fAttr(As C) [] 'feat'(C) Fs=AttrFeat($)+ => fFeat(Fs C) [] 'prop'(C) Ps=Phrase($)+ => fProp(Ps C) end syn AttrFeat($) F=( Atom($) [] Variable($) [] Int($) [] 'unit'(C) => fEscape(fVar('`unit`' C) C) [] 'true'(C) => fEscape(fVar('`true`' C) C) [] 'false'(C) => fEscape(fVar('`false`' C) C) ) ( skip => F [] ':' Phrase(P) => F#P ) end syn Meth($) 'meth'(C) MethHead(H) InSequence(S) 'end' => fMeth(H S C) end syn MethHead($) MethHead1($) [] MethHead1(H) '='(C) NakedVariable(V) => fEq(H V C) end syn MethHead1($) Atom($) [] Variable($) [] 'unit'(C) => fEscape(fVar('`unit`' C) C) [] 'true'(C) => fEscape(fVar('`true`' C) C) [] 'false'(C) => fEscape(fVar('`false`' C) C) [] MethHeadLabel(L) '(' Fs = ( MethFormal($) )* Open = ( skip => false [] '...' => true ) ')' => if Open then fOpenRecord(L Fs) else fRecord(L Fs) end end syn MethHeadLabel($) 'ATOM()'(X) Coord(C) => fAtom(X C) [] 'VARIABLE()'(X) Coord(C) => fVar(X C) [] '!'(C1) 'VARIABLE()'(X) Coord(C2) => fEscape(fVar(X C2) C1) [] 'unit()'(C) => fEscape(fVar('`unit`' C) C) [] 'true()'(C) => fEscape(fVar('`true`' C) C) [] 'false()'(C) => fEscape(fVar('`false`' C) C) end syn MethFormal($) MethFormalTerm(T) D = ( '<='(C) Phrase(P) => fDefault(P C) [] skip => fNoDefault) => fMethArg(T D) [] Feature(F) ':' MethFormalTerm(T) D = ( '<='(C) Phrase(P) => fDefault(P C) [] skip => fNoDefault) => fMethColonArg(F T D) end syn MethFormalTerm($) NakedVariable($) [] '$'(C) => fDollar(C) [] '_'(C) => fWildcard(C) end %-------------------------------------------------------------------- % Functor Extensions %-------------------------------------------------------------------- syn FunctorDescriptor($) 'require'(C) Ds = ( ImportDecl($) )* => fRequire(Ds C) [] 'prepare'(C) Sequence(S1) 'in' Sequence(S2) => fPrepare(S1 S2 C) [] 'prepare'(C) Sequence(S) => fPrepare(S fSkip(C) C) [] 'import'(C) Ds = ( ImportDecl($) )* => fImport(Ds C) [] 'export'(C) Ds = ( ExportDecl($) )* => fExport(Ds C) [] 'define'(C) Sequence(S1) 'in' Sequence(S2) => fDefine(S1 S2 C) [] 'define'(C) Sequence(S) => fDefine(S fSkip(C) C) end syn ImportDecl($) NakedVariable(V) I = ( 'at' Atom(A) => fImportAt(A) [] skip => fNoImportAt) => fImportItem(V nil I) [] 'VARIABLE()'(X) Coord(C) '(' IFs = ( ImportFeature($) )+ ')' I = ( 'at' Atom(A) => fImportAt(A) [] skip => fNoImportAt) => fImportItem(fVar(X C) IFs I) end syn ExportDecl($) NakedVariable(V) => fExportItem(V) [] F = ( Atom($) [] Int($) ) ':' NakedVariable(V) => fExportItem(fColon(F V)) end syn ImportFeature($) ( Atom($) [] Int($) ) [] F = ( Atom($) [] Int($) ) ':' NakedVariable(V) => V#F end %-------------------------------------------------------------------- % Constraint Extensions %-------------------------------------------------------------------- syn CondMain(C1 $) Cs=( CondClause($) // '[]' )+ CondRest(P C2) => fCond(Cs P {MakeLongPos C1 C2}) end syn CondRest(S C) 'else' InSequence(!S) 'end'(!C) [] 'end'(!C) => S = fNoElse(!C) end syn CondClause($) Sequence(S1) ThisCoord(C) 'then' InSequence(S2) => fClause(fSkip(C) S1 S2) [] Sequence(S1) 'in' Sequence(S2) 'then' InSequence(S3) => fClause(S1 S2 S3) end syn OrClauseList($) OrClause(C1) '[]' Cr=( OrClause($) // '[]' )+ => C1|Cr end syn OrClause($) Sequence(S) ThisCoord(C) => fClause(fSkip(C) S fNoThen(C)) [] Sequence(S1) 'in' Sequence(S2) ThisCoord(C) => fClause(S1 S2 fNoThen(C)) [] Sequence(S1) ThisCoord(C) 'then' InSequence(S2) => fClause(fSkip(C) S1 S2) [] Sequence(S1) 'in' Sequence(S2) 'then' InSequence(S3) => fClause(S1 S2 S3) end syn ChoiceClauseList($) ( InSequence($) // '[]' )+ end %-------------------------------------------------------------------- % Gump Extensions %-------------------------------------------------------------------- %-------------------------------------------------------------------- % Application-Specific Production Templates prod $=twoLists:( A // B )+ syn X(Hd1 Tl1 Hd2 Tl2) A(Elem1) => Hd1=Elem1|Tl1 Hd2= Tl2 [] X(!Hd1 Tl10 !Hd2 Tl20) B(Elem2) A(Elem1) => Tl10=Elem1|Tl1 Tl20=Elem2#Tl2 end in X(Hd1 Tl1 Hd2 Tl2) => Tl1=nil Tl2=nil Hd1#{VirtualString.toString Hd2} end prod $=twoLists:( A // B )* twoLists:( A($) // B($) )+ [] skip => nil#"" end %-------------------------------------------------------------------- % Scanner Definition syn ScannerSpecification($) 'scanner'(C1) NakedVariable(V) Ds=ClassDescriptor($)* Ms=Meth($)* Rules=( LexicalAbbreviation($) [] LexicalRule($) [] LexicalMode($) )+ 'end'(C2) => fScanner(V Ds Ms Rules {self.Scanner getScannerPrefix($)} {MakeLongPos C1 C2}) end syn LexicalAbbreviation($) 'lex' Atom(A) '=' R=( 'REGEX'($) [] 'STRING'($) ) 'end' => fLexicalAbbreviation(A R) [] 'lex' NakedVariable(V) '=' R=( 'REGEX'($) [] 'STRING'($) ) 'end' => fLexicalAbbreviation(V R) end syn LexicalRule($) 'lex' R=( 'REGEX'($) [] 'STRING'($) ) InSequence(S) 'end' => fLexicalRule(R S) end syn LexicalMode($) 'mode' NakedVariable(V) Fs=[ 'from' NakedVariable($)+ ] Ds=( LexicalRule($) [] LexicalMode($) )* 'end' => fMode(V Ds) end %-------------------------------------------------------------------- % Parser Definition syn ParserSpecification($) 'parser'(C1) NakedVariable(V) Ds=ClassDescriptor($)* Ms=Meth($)* TokenClause(Token) Rules=ParserDescriptor($)+ 'end'(C2) => fParser(V Ds Ms Token Rules {self.Scanner getParserExpect($)} {MakeLongPos C1 C2}) end syn TokenClause($) 'token' Xs=( Atom($) [] Atom(A) ':' Phrase(P) => A#P )+ => fToken(Xs) [] skip => fToken(nil) end syn ParserDescriptor($) SynClause($) [] ProdClause($) end syn ProdClause($) 'prod' ProdHead(Key Vs ReturnVariable) Rs=[ Rs=SynClause($)+ 'in' => Rs ] SynAlt(A) 'end' => fProductionTemplate(Key Vs Rs A ReturnVariable) end syn ProdHead(Key Vs ReturnVariable) NakedVariable(!ReturnVariable) '=' ProdHeadRest(HKey !Vs) => Key=HKey.1#(&=|HKey.2) [] '$' Coord(C) '=' ProdHeadRest(HKey !Vs) => Key=HKey.1#(&=|HKey.2) ReturnVariable=fDollar(C) [] ProdHeadRest(!Key !Vs) => ReturnVariable=none end syn ProdHeadRest($ Vs) NakedVariable(V) TerminatorOp(TKey) => Vs=[V] none#TKey [] Atom(A) ':' NakedVariable(V) TKey=( TerminatorOp($) [] skip => "" ) => Vs=[V] A#TKey [] Label=( Atom(A) ':' => A [] skip => none ) PKey=( '(' ProdParams(!Vs SKey) ')' => &(|SKey [] '[' ProdParams(!Vs SKey) ']' => &[|SKey [] '{' ProdParams(!Vs SKey) '}' => &{|SKey ) Key=( TerminatorOp(TKey) => {Append PKey TKey} [] skip => PKey ) => Label#Key end syn ProdParams(Vs Key) Res=twoLists:( NakedVariable($) [] '_' Coord(C) => fWildcard(C) // SeparatorOp($) )* => Res=Vs#Key end syn SeparatorOp($) '//' => "//" end syn TerminatorOp($) 'Add'(X) => [{Atom.toString X}.1] [] 'FdMul'(X) => [{Atom.toString X}.1] end syn SynClause($) 'syn' SynHead(F Ps) SynAlt(A) 'end' => fSyntaxRule(F Ps A) end syn SynHead(F Ps) Atom(!F) => Ps=nil [] NakedVariable(!F) => Ps=nil [] !F=( 'ATOM()'(X) Coord(C) => fAtom(X C) [] 'VARIABLE()'(X) Coord(C) => fVar(X C) ) '(' !Ps=( NakedVariable($) [] '$' Coord(C) => fDollar(C) [] '_' Coord(C) => fWildcard(C) )* ')' end syn SynAlt($) As=( SynSeq($) // '[]' )+ => fSynAlternative(As) end syn SynSeq($) NonEmptySeq(nil ?Ds ?Es) => fSynSequence(Ds Es) [] 'skip' OptSynAction(A) => fSynSequence(nil A) end syn OptSynAction($) skip => nil [] '=>' InSequence(S) => [fSynAction(S)] end syn NonEmptySeq(Vs ?Ds $) NakedVariable(V) NonEmptySeq(V|Vs !?Ds $) [] NakedVariable(V) ThisCoord(C) TerminatorOp(Key) SynPrims(Ps) => Ds = nil {FoldL Vs fun {$ In V} fSynApplication(V nil)|In end fSynTemplateInstantiation(none#Key [fSynApplication(V nil)] C)|Ps} [] NakedVariable(V) '=' SynPrimNoAssign(E) SynPrims(Ps) => Ds = nil {FoldL Vs fun {$ In V} fSynApplication(V nil)|In end fSynAssignment(V E)|Ps} [] 'in' SynPrims(Ps) => Ds = Vs Ps [] SynPrimNoVar(P) SynPrims(Ps) => Ds = nil {FoldL Vs fun {$ In V} fSynApplication(V nil)|In end P|Ps} [] OptSynAction(A) => Ds = nil {FoldL Vs fun {$ In V} fSynApplication(V nil)|In end A} end syn SynPrims($) OptSynAction($) [] SynPrim(P) SynPrims(Ps) => P|Ps end syn SynPrim($) Variable(V) '=' SynPrimNoAssign(E) => fSynAssignment(V E) [] SynPrimNoAssign($) end syn SynPrimNoAssign($) NakedVariable(V) => fSynApplication(V nil) [] NakedVariable(V) ThisCoord(C) TerminatorOp(Key) => fSynTemplateInstantiation(none#Key [fSynApplication(V nil)] C) [] SynPrimNoVarNoAssign($) end syn SynPrimNoVar($) '!'(C) NakedVariable(V) '=' SynPrimNoAssign(E) => fSynAssignment(fEscape(V C) E) [] SynPrimNoVarNoAssign($) end syn SynPrimNoVarNoAssign($) SynInstTerm($) [] Atom(A) Coord(C) ':' SynInstTerm(E0) Key=[ TerminatorOp($) ] => fSynTemplateInstantiation(A#Key [E0] C) [] SynInstTerm(E0) ThisCoord(C) TerminatorOp(Key) => fSynTemplateInstantiation(none#Key [E0] C) [] As C in Label=( Atom(A) Coord(!C) ':' => A [] ThisCoord(!C) => none ) PKey=( '(' SynProdCallParams(!As XKey) ')' => &(|XKey [] '[' SynProdCallParams(!As XKey) ']' => &[|XKey [] '{' SynProdCallParams(!As XKey) '}' => &{|XKey ) Key=( TerminatorOp(TKey) => {Append PKey TKey} [] skip => PKey ) => fSynTemplateInstantiation(Label#Key As C) end syn SynInstTerm($) Atom(C) => fSynApplication(C nil) [] 'ATOM()'(X) Coord(C) '(' Ps=Phrase($)+ ')' => fSynApplication(fAtom(X C) Ps) [] 'VARIABLE()'(X) Coord(C) '(' Ps=Phrase($)* ')' => fSynApplication(fVar(X C) Ps) end syn SynProdCallParams(As Key) Res=twoLists:( SynAlt($) // SeparatorOp($) )+ => Res=As#Key end end