package code.loop.parser; import java_cup.runtime.*; import java.util.*; import code.term.*; import code.table.*; import code.symbols.*; parser code {: /** We can't use the usual setScanner/getScanner mechanism, because our lexer doesn't quite match the Lexer interface. */ Yylex jlexer; public AstParser(Yylex jlexer) { super(); this.jlexer = jlexer; } public void syntax_error(java_cup.runtime.Symbol current) {} // override default message public void unrecovered_syntax_error(java_cup.runtime.Symbol current) throws ParseError { report_fatal_error("Parse Syntax error at charPos: "+current.left, current); } public void report_fatal_error(String message, java_cup.runtime.Symbol info) throws ParseError { done_parsing(); throw new ParseError(message); } :} action code {: :} scan with {: return jlexer.yylex(); :} terminal String PREFIXID, INFIXID, STRING; terminal Integer INTEGER; terminal Float FLOAT; terminal Character CHAR; terminal IF, THEN, ELSE, WHERE, FREE; terminal MINUS, UMINUS; terminal DOUBLEDOT, COMMA, LPAREN, RPAREN, LSQBRA, RSQBRA, BACKQUOTE; non terminal Ast.Term term; non terminal Ast.WhereTail wheretail; non terminal Vector variablelist; non terminal Ast.Expr expr; non terminal Ast.IfExpr ifexpr; non terminal Ast.InfixOperation infixop; non terminal Ast.FunctionExpr functexpr; non terminal Ast.Uminus uminus; non terminal Ast.BasicExpr basicexpr; non terminal Ast.Literal literal; non terminal Ast.Tuple tuple; non terminal Vector tuplelisting; non terminal Ast.List list; non terminal Vector listlisting; non terminal Ast.ArithSeq arithseq; /* Precedence */ /*to reduce the conflicts between infixop and ifexpr and infixop itself*/ precedence left INFIXID, MINUS, BACKQUOTE; precedence left UMINUS; term ::= expr:e wheretail:w {: RESULT = new Ast.Term(e, w); :} ; wheretail ::= {: RESULT = new Ast.WhereTail(new Vector()); :} | WHERE variablelist:l FREE {: RESULT = new Ast.WhereTail(l); :} ; variablelist ::= PREFIXID:id {: Vector v = new Vector(); v.add(id); RESULT = v; :} | PREFIXID:id COMMA variablelist:l {: l.insertElementAt(id,0); RESULT = l; :} ; expr ::= ifexpr:e {: RESULT = e; :} | infixop:e {: RESULT = e; :} | functexpr:e {: RESULT = e; :} | uminus:e {: RESULT = e; :} ; //conflicting with infixop at ELSE (*) !!!??? //Avoided by increase the precedence of infixop ??? ifexpr ::= IF expr:e1 THEN expr:e2 ELSE expr:e3 {: RESULT = new Ast.IfExpr(e1,e2,e3); :} ; //conflicting with itself(default is right associative) and ifexpr at ELSE (*) !!!??? //Avoided by increase the precedence of infixop and give it left assoc??? infixop ::= expr:e1 INFIXID:id expr:e2 {: Ast.InfixOperation returnObj = null; if (e1 instanceof Ast.InfixOperation) returnObj = ((Ast.InfixOperation)e1).reconstruct(id,e2); else returnObj = new Ast.InfixOperation(e1,id,e2); RESULT = returnObj; :} | expr:e1 BACKQUOTE PREFIXID:id BACKQUOTE expr:e2 {: Ast.InfixOperation returnObj = null; if (e1 instanceof Ast.InfixOperation) returnObj = ((Ast.InfixOperation)e1).reconstruct(id,e2); else returnObj = new Ast.InfixOperation(e1,id,e2); RESULT = returnObj; :} | expr:e1 MINUS expr:e2 {: Ast.InfixOperation returnObj = null; if (e1 instanceof Ast.InfixOperation) returnObj = ((Ast.InfixOperation)e1).reconstruct("-",e2); else returnObj = new Ast.InfixOperation(e1,"-",e2); RESULT = returnObj; :} ; functexpr ::= functexpr:f basicexpr:b {: Vector basics = f.basics; basics.add(b); RESULT = f; :} | basicexpr:e {: Vector bv = new Vector(); bv.add(e); RESULT = new Ast.FunctionExpr(bv); :} ; uminus ::= MINUS expr:e {: RESULT = new Ast.Uminus(e); :} %prec UMINUS ; basicexpr ::= PREFIXID:id {: RESULT = new Ast.PrefixId(id); :} | LPAREN INFIXID:id RPAREN {: RESULT = new Ast.InfixId(id); :} | LPAREN MINUS RPAREN {: RESULT = new Ast.InfixId("-"); :} | literal:l {: RESULT = l; :} | LPAREN expr:e RPAREN {: RESULT = new Ast.ParenExpr(e); :} | tuple:t {: RESULT = t; :} | list:l {: RESULT = l; :} | arithseq:s {: RESULT = s; :} | LPAREN expr:e INFIXID:id RPAREN {: RESULT = new Ast.LeftSection(e,id); :} | LPAREN expr:e MINUS RPAREN {: RESULT = new Ast.LeftSection(e,"-"); :} | LPAREN INFIXID:id expr:e RPAREN {: RESULT = new Ast.RightSection(id,e); :} /* (-expr) is considered as a uminus or negation, the result is an int value, not a partial function, if user type: map (-1) [2,3], the type (-1) is wrong !!! LPAREN MINUS expr:e RPAREN {: RESULT = new Ast.RightSection("-",e); :} */ ; literal ::= INTEGER:i {: RESULT = new Ast.IntLit(i.intValue()); :} | CHAR:c {: RESULT = new Ast.CharLit(c.charValue()); :} | STRING:s {: RESULT = new Ast.StringLit(s); :} | FLOAT:f {: RESULT = new Ast.FloatLit(f.floatValue()); :} ; tuple ::= LPAREN expr:e COMMA tuplelisting:l RPAREN {: l.insertElementAt(e,0); RESULT = new Ast.Tuple(l); :} | LPAREN RPAREN {: RESULT = new Ast.Tuple(new Vector()); :} ; tuplelisting ::= expr:e {: Vector v = new Vector(); v.add(e); RESULT = v; :} | expr:e COMMA tuplelisting:l {: l.insertElementAt(e,0); RESULT = l; :} ; list ::= LSQBRA listlisting:l RSQBRA {: RESULT = new Ast.List(l); :} | LSQBRA RSQBRA {: RESULT = new Ast.List(new Vector()); :} ; listlisting ::= expr:e {: Vector v = new Vector(); v.add(e); RESULT = v; :} | expr:e COMMA listlisting:l {: l.insertElementAt(e,0); RESULT = l; :} ; arithseq ::= LSQBRA expr:e1 DOUBLEDOT RSQBRA {: RESULT = new Ast.ArithSeq(e1, null, null); :} | LSQBRA expr:e1 COMMA expr:e2 DOUBLEDOT RSQBRA {: RESULT = new Ast.ArithSeq(e1, e2, null); :} | LSQBRA expr:e1 DOUBLEDOT expr:e3 RSQBRA {: RESULT = new Ast.ArithSeq(e1, null, e3); :} | LSQBRA expr:e1 COMMA expr:e2 DOUBLEDOT expr:e3 RSQBRA {: RESULT = new Ast.ArithSeq(e1, e2, e3); :} ;