%%% %%% Authors: %%% Gary T. Leavens based on work of... %%% %%% Leif Kornstaedt %%% Andreas Sundstroem %%% %%% Copyright: %%% Leif Kornstaedt, 1998 %%% Andreas Sundstroem, 1998 %%% %%% Last change: %%% $Date: 2010/08/09 21:24:15 $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 % from Conversions.oz, can't seem to insert that here :-( fun {Exp2Pattern Expr} %% ENSURES: Result is an pattern AST that represents the expression Exp case Expr of varIdExp(V POS) then varIdPat(V POS) [] varIdExp(V ...) then varIdPat(V) [] atomExp(A POS) then atomPat(A POS) [] atomExp(A ...) then atomPat(A) [] boolExp(B POS) then boolPat(B POS) [] boolExp(B ...) then boolPat(B) [] recordExp(atomExp(A) FL POS) then recordPat(A FL POS) [] recordExp(atomExp(A) FL ...) then recordPat(A FL) else {Exception.raiseError wrongExpressionForPattern(Expr)} raise Expr end end 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: '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($) Sequence($) end syn Sequence($) Statement($) [] Statement(P) Sequence(Ss) => case Ss of seqStmt(Ls) then seqStmt(P|Ls) else seqStmt(P|Ss|nil) end end syn Statement($) 'skip'(_) => skipStmt [] 'local'(_) VariableId(V) 'in' InStatement(S) 'end' => localStmt(V S) [] VariableId(V) '='(_) Expression(E) => assignStmt(V E) [] 'if'(_) Expression(TestExp) 'then' InStatement(S1) 'else' InStatement(S2) 'end' => ifStmt(TestExp S1 S2) [] 'case'(_) Expression(Expr) 'of' Pattern(P) 'then' InStatement(S1) 'else' InStatement(S2) 'end' => caseStmt(Expr P S1 S2) [] '{'(_) Expression(E) Es=Expression($)* '}'(_) => applyStmt(E Es) [] 'fun'(_) '{' VariableId(Name) Formals=Formal($)* '}' Expression(Body) 'end'(_) => case Name of varIdExp(Nm) then namedFunStmt(Nm Formals Body) else namedFunStmt(Name Formals Body) end [] 'thread'(C) InStatement(S) 'end' => threadStmt(S C) end syn InStatement($) Pattern(Pat) '=' Expression(Exp) 'in' Sequence(Body) => inStmt(Pat Exp Body) [] Sequence($) end syn Expression($) Expression(E1) 'Add'(Op) Expression(E2) => applyExp(varIdExp(Op) [E1 E2]) [] '(' Expression(E) ')' => E [] VariableId($) [] Atom($) [] 'true'(_) => boolExp(true) [] 'false'(_) => boolExp(false) [] 'self'(C) => fSelf(C) [] String($) [] Number($) [] Label(L) '(' RecordArguments(As) ')'(C2) => case L of atomExp(A C1) then recordExp(atomExp(A) As {MakeLongPos C1 C2}) [] varIdExp(V C1) then recordExp(varIdExp(V) As {MakeLongPos C1 C2}) end [] '['(C1) Es=( Expression($) )+ ']'(C2) => recordExp(atomExp('|') {FoldR Es fun {$ E In} posFld(E)|posFld(In) end atomExp('nil')} {MakeLongPos C1 C2}) [] 'case'(C1) Expression(Expr) 'of'(_) Pattern(P) 'then'(_) Expression(E2) 'else' Expression(E3) 'end'(C2) => caseExp(Expr P E2 E3 {MakeLongPos C1 C2}) [] 'proc'(C1) '{' '$' Formals=Formal($)* '}' InSequence(S) 'end'(C2) => procExp(Formals S {MakeLongPos C1 C2}) [] '{'(_) Expression(E) Es=Expression($)* '}'(_) => applyExp(E Es) [] 'thread'(C) Expression(E) 'end' => threadExp(E C) [] Expression(P1) '|'(C) Expression(P2) => recordExp(atomExp('|') {Map [P1 P2] fun {$ E} posFld(E) end} C) [] Expression(P1) '#'(C) Pr=( Expression($) // '#' )+ => recordExp('#' {Map P1|Pr fun {$ E} posFld(E) end} C) end syn InSequence($) ThisCoord(C) Sequence(S1) 'in' Sequence(S2) => localStmt(S1 S2 C) [] ThisCoord(_) Sequence($) end syn Label($) 'ATOM()'(X) Coord(C) => atomExp(X C) [] 'VARIABLE()'(X) Coord(C) => varIdExp(X C) [] 'unit()'(C) => atomExp('`unit`' C) [] 'true()'(C) => boolExp('`true`' C) [] 'false()'(C) => boolExp('`false`' C) end syn RecordArguments($) ( Statement($) [] Feature(F) ':' Statement(P) => colonFld(F P) )* end syn Feature($) Atom($) [] VariableId($) [] Int($) [] 'unit'(C) => atomPat('`unit`' C) [] 'true'(C) => boolPat('`true`' C) [] 'false'(C) => boolPat('`false`' C) end syn Pattern($) Pattern(P1) '|'(C) Pattern(P2) => recordPat('|' [posFld(P1) posFld(P2)] C) [] Expression(P) => {Exp2Pattern P} [] Expression(P) '#'(C) Hs = ( Expression($) // '#' )+ => recordPat('#' {Map P|Hs fun {$ E} posFld(E) end} C) end syn Atom($) 'ATOM'(X) => atomExp(X) end syn VariableId($) 'VARIABLE'(X) => varIdExp(X) end syn String($) 'STRING'(S) => {FoldR S fun {$ X In} recordExp(atomExp('|') [posFld(numExp(X)) posFld(In)]) end atomExp('nil')} end syn Number($) 'INT'(X) => numExp(X) [] 'FLOAT'(X) => numExp(X) end syn ThisCoord($) skip => {self.Scanner getCoordinates($)} end syn Coord($) skip => {self.Scanner getSavedCoordinates($)} end syn Formal($) Formal(P1) '|'(C) Formal(P2) => recordPat('|' [posFld(P1) posFld(P2)] C) [] Formal2($) [] Formal2(P1) '#'(C) Pr=( Formal2($) // '#' )+ => recordPat('#' {Map P1|Pr fun {$ E} posFld(E) end} C) end syn Formal2($) Atom(A) => case A of atomExp(A2) then atomPat(A2) end [] VariableId(V) => case V of varIdExp(V2) then varIdPat(V2) end end syn Int($) 'INT'(X) Coord(C) => fInt(X C) end % syn Float($) % 'FLOAT'(X) Coord(C) => fFloat(X C) % end end