import java_cup.runtime.*; import java.util.*; /* Copyright Andrew Tolmach 2004. All rights reserved. */ parser code {: /** We can't use the usual setScanner/getScanner mechanism, because our lexer doesn't quite match the Scanner interface. */ Yylex jlexer; Parser(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("Error at line " + current.left + ": Syntax error",current); } public void report_fatal_error(String message, java_cup.runtime.Symbol info) throws ParseError { done_parsing(); throw new ParseError(message); } :} scan with {: return jlexer.yylex(); :} terminal String ID, STRING, REAL; terminal Integer INTEGER; terminal AND, ARRAY, BEGIN, BY, DIV, DO, ELSE, ELSIF, END, EXIT, FOR, IF, IS, LOOP; terminal MOD, NOT, OF, OR, PROCEDURE, PROGRAM, READ, RECORD, RETURN, THEN, TO, TYPE, VAR, WHILE, WRITE; terminal ASGN, PLUS, MINUS, TIMES, SLASH, LT, LEQ, GT, GEQ, EQ, NEQ, COLON, SEMI, COMMA, DOT; terminal LPAREN, RPAREN, LSQBRA, RSQBRA, LCUBRA, RCUBRA; non terminal Ast.Program program; non terminal Ast.Body body; non terminal List decgroups; /* contains Ast.Decs */ non terminal Ast.Decs decgroup; non terminal List var_decs; /* contains Ast.VarDec */ non terminal Ast.VarDec var_dec; non terminal List ids; /* contains String */ non terminal String typename; non terminal List statements; /* contains Ast.St */ non terminal Ast.St statements_st, statement; non terminal Ast.Exp expr; non terminal Ast.Lvalue lvalue; precedence left PLUS; precedence left TIMES; program ::= PROGRAM:p IS body:b SEMI {: RESULT = new Ast.Program(pleft,b); :} ; body ::= decgroups:ds BEGIN statements_st:ss END {: RESULT = new Ast.Body(dsleft,ds,ss); :} ; decgroups ::= {: RESULT = new ArrayList(); :} | decgroups:ds decgroup:d {: ds.add(d); RESULT = ds; :} ; decgroup ::= VAR:v var_decs:vds {: RESULT = new Ast.VarDecs(vleft,vds); :} ; var_decs ::= var_dec:d {: {ArrayList list = new ArrayList(); list.add(d); RESULT = list;} :} | var_decs:ds var_dec:d {: ds.add(d); RESULT = ds; :} ; var_dec ::= ids:ids COLON typename:t ASGN expr:e SEMI {: RESULT = new Ast.VarDec(idsleft,ids,t,e); :} | ids:ids ASGN expr:e SEMI {: RESULT = new Ast.VarDec(idsleft,ids,null,e); :} ; ids ::= ID:id {: {ArrayList list = new ArrayList(); list.add(id); RESULT = list;} :} | ids:ids COMMA ID:id {: ids.add(id); RESULT = ids; :} ; typename ::= ID:id {: RESULT = id; :} ; statements ::= {: RESULT = new ArrayList(); :} | statements:ss statement:s {: ss.add(s); RESULT = ss; :} ; statements_st ::= statements:ss {: RESULT = new Ast.SequenceSt(ssleft,ss); :} ; statement ::= lvalue:lv ASGN expr:e SEMI {: RESULT = new Ast.AssignSt(lvleft,lv,e); :} | LOOP:l statements_st:s END SEMI {: RESULT = new Ast.LoopSt(lleft,s); :} | EXIT:e SEMI {: RESULT = new Ast.ExitSt(eleft); :} ; expr ::= lvalue:lv {: RESULT = new Ast.LvalExp(lvleft,lv); :} | expr:e1 PLUS expr:e2 {: RESULT = new Ast.BinOpExp(e1left,Ast.PLUS,e1,e2); :} | expr:e1 TIMES expr:e2 {: RESULT = new Ast.BinOpExp(e1left,Ast.TIMES,e1,e2); :} ; lvalue ::= ID:id {: RESULT = new Ast.VarLvalue(idleft,id); :} ;