function parser:tree; const applicpriority=7; var lineno :integer; { state vars for parser} ch:char; sy:symbol; theword:alfa; theint:integer; oprpriority:array[symbol]of integer; startsexp, unoprs, binoprs, rightassoc :set of symbol; sym :symbol; function newnode(k:SyntaxClass):tree; var p:tree; begin new(p); p^.tag:=k; newnode:=p end; procedure error(m:alfa); begin writeln; writeln('error:', m, ' lineno=', lineno:1, ' ch=<', ch, '>(', ord(ch):1, ') sy=', ord(sy):1, ' last word=<', theword, '>'); writeln; write('skip :'); while not eof do if eoln then begin readln; writeln; write('skip :') end else begin read(ch); write(ch) end; goto 99 {error abort} end{error}; #include "lex.insym.P" {Lexical Analysis Routines} procedure check(s:symbol; m:alfa); begin if sy=s then insymbol else error(m) end; function syis(s:symbol):boolean; begin if sy=s then begin syis:=true; insymbol end else syis:=false end; function expression:tree; { --- parse an expression --- } function param:tree; var p:tree; begin if sy=word then { lambda x .... } begin p:=newnode(ident); p^.id:=theword end else if sy=empty then { lambda () ... } p:=newnode(emptycon) else error('f param '); insymbol; param:=p end; function pdecs:tree; { [rec] , , ... in exp } var d:tree; isrec:boolean; function cons( isrec:boolean; h,t:tree):tree; var p:tree; begin p:=newnode(declist); p^.recursive:=isrec; p^.hd:=h; p^.tl:=t; cons:=p end; function pdeclist(isrec:boolean) :tree; { ,, ... } var d:tree; function pdec:tree; { = } var d:tree; begin if sy=word then begin d:=newnode(decln); d^.name:=theword; insymbol; check(eq,'= expected'); d^.val :=expression end else error('dec, no id'); pdec:=d end{pdec}; begin {pdeclist dec, dec, ..., dec } d:=pdec; if syis(comma) then pdeclist:=cons(isrec,d,pdeclist(isrec)) else pdeclist:=cons(isrec,d,nil) end{pdeclist}; begin {pdecs} isrec:=syis(recsy); { [rec] pdeclist in exp } d:=newnode(block); d^.decs:=pdeclist(isrec); check(insy, 'in expectd'); d^.exp := expression; pdecs := d end{pdecs}; function exp(priority:integer):tree; var e, a :tree; begin {exp} if priority < applicpriority then begin e := exp( priority+1 ); if (sy in binoprs*rightassoc)and(oprpriority[sy]=priority) then begin a:=e; e:=newnode(binexp); e^.binopr:=sy; insymbol; e^.left:=a; e^.right:=exp(priority) end else while (sy in binoprs-rightassoc) and (oprpriority[sy]=priority) do begin a:=e; e:=newnode(binexp); e^.binopr:=sy; insymbol; e^.left:=a; e^.right:= exp(priority+1) end end else if priority=applicpriority then {application f g h x} begin e:=exp(priority+1); while sy in startsexp - binoprs do {need () in f(-3)} begin a:=e; e:=newnode(application); e^.fun:=a; e^.aparam:=exp(priority+1) end end else {operands}if sy in unoprs then begin e:=newnode(unexp); e^.unopr:=sy; insymbol; e^.unarg:=exp(priority) end else if sy in startsexp then case sy of word: begin e:=newnode(ident); e^.id:=theword; insymbol end; numeral:begin e:=newnode(intcon); e^.n:=theint; insymbol end; charliteral:begin e:=newnode(charcon); e^.ch:=theword[1]; insymbol end; empty: begin insymbol; e:=newnode(emptycon) end; nilsy: begin insymbol; e:=newnode(nilcon) end; chansy: begin insymbol; e:=newnode(newchan) end; truesy: begin e:=newnode(boolcon); e^.b:=true; insymbol end; falsesy:begin e:=newnode(boolcon); e^.b:=false; insymbol end; open: begin insymbol; e:=expression; check(close,') expected') end; letsy: begin insymbol; e:=pdecs end; ifsy:begin insymbol; e:=newnode(ifexp); e^.e1:=expression; check(thensy,'no then '); e^.e2:=expression; check(elsesy,'no else '); e^.e3:=expression end; lambdasy:begin insymbol; e:=newnode(lambdaexp); e^.fparam:=param; check(dot,'. expected'); e^.body:=expression end; end{case} else error('bad opernd'); exp:=e end {exp}; begin{expression} expression:=exp({priority=}-3) end{expression}; begin {parser} unoprs := [minus, hdsy, tlsy, nullsy, notsy]; binoprs := [sequencesy..over]; rightassoc := [conssy, sequencesy]; startsexp := unoprs + [word..falsesy, open, letsy, ifsy, lambdasy, chansy]; for sym:=word to eofsy do oprpriority[sym]:=0; oprpriority[parallelsy]:=-3; oprpriority[choicesy]:=-2; {process operators} oprpriority[sequencesy]:=-1; oprpriority[inputsy] := 0; oprpriority[outputsy]:= 0; oprpriority[conssy]:=1; oprpriority[orsy]:=2; oprpriority[andsy]:=3; for sym:=eq to ge do oprpriority[sym]:=4; oprpriority[plus]:=5; oprpriority[minus]:=5; oprpriority[times]:=6; oprpriority[over]:=6; lineno := 1; writeln(' Simple Parallel Functional Language L.A. Monash Comp Sci 8/4/93'); write(lineno:3, ': '); ch:=' '; theword := '-start----'; theint:=maxint; insymbol; parser := expression; {a program is a single expression} check(eofsy, 'prog+junk '); writeln end{parser}; {\fB Parser for Parallel Functional Language. \fP} { Do not remove: This program is released under Gnu `copyleft' General } { Public Licence (GPL) -- L.Allison, CSSE, Monash Uni., .au, 7/2004 }