Last active
November 30, 2015 19:23
-
-
Save VenturaDelMonte/b9bd693eb43856e1d728 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* file name: cool.cup | |
* authors: Bonaventura Del Monte, Antonio Cesarano | |
* last edit: 04/05/2014 | |
* Parser definition for the COOL language. | |
* | |
*/ | |
import java_cup.runtime.*; | |
/* Stuff enclosed in {: :} is copied verbatim to the class containing | |
all parser actions. All the extra variables/functions you want to use | |
in the semantic actions should go here. Don't remove or modify anything | |
that was there initially. */ | |
action code {: | |
int curr_lineno() { | |
return ((CoolTokenLexer)parser.getScanner()).curr_lineno(); | |
} | |
AbstractSymbol curr_filename() { | |
return ((CoolTokenLexer)parser.getScanner()).curr_filename(); | |
} | |
int line = 0; | |
int tmp_line = 0; | |
void update_line() | |
{ | |
line = curr_lineno(); | |
} | |
:} | |
/************************************************************************/ | |
/* DONT CHANGE ANYTHING IN THIS SECTION */ | |
parser code {: | |
int omerrs = 0; | |
public void syntax_error(Symbol cur_token) { | |
int lineno = action_obj.curr_lineno(); | |
String filename = action_obj.curr_filename().getString(); | |
System.err.print("\"" + filename + "\", line " + lineno + | |
": syntax error at or near "); | |
Utilities.printToken(cur_token); | |
omerrs++; | |
if (omerrs>50) { | |
System.err.println("More than 50 errors"); | |
System.exit(1); | |
} | |
} | |
public void unrecovered_syntax_error(Symbol cur_token) { | |
} | |
:} | |
/* Declare the terminals; a few have types for associated lexemes. The | |
token ERROR is never used in the parser; thus, it is a parse error when | |
the lexer returns it. */ | |
terminal CLASS, ELSE, FI, IF, IN, INHERITS, LET, LET_STMT, LOOP, POOL, THEN, WHILE; | |
terminal CASE, ESAC, OF, DARROW, NEW, ISVOID; | |
terminal ASSIGN, NOT, LE, ERROR; | |
terminal PLUS, DIV, MINUS, MULT, EQ, LT, DOT, NEG, COMMA, SEMI, COLON; | |
terminal LPAREN, RPAREN, AT, LBRACE, RBRACE; | |
terminal AbstractSymbol STR_CONST, INT_CONST; | |
terminal Boolean BOOL_CONST; | |
terminal AbstractSymbol TYPEID, OBJECTID; | |
/* DON'T CHANGE ANYTHING ABOVE THIS LINE, OR YOUR PARSER WONT WORK */ | |
/**************************************************************************/ | |
/* Complete the nonterminal list below, giving a type for the semantic | |
value of each non terminal. (See the CUP documentation for details. */ | |
nonterminal Integer dummy; | |
nonterminal Program program; | |
nonterminal Classes class_list; | |
nonterminal Class_ class; | |
nonterminal Expression expression; | |
nonterminal Expressions expression_list_semi; | |
nonterminal Expressions expression_list_comma; | |
nonterminal Formal formal; | |
nonterminal Formals formal_list; | |
nonterminal Feature feature; | |
nonterminal Features feature_list; | |
nonterminal Cases case_list; | |
nonterminal Case single_case; | |
nonterminal let nested_let; | |
nonterminal block _block; | |
/* Non terminal wrappers for terminals */ | |
nonterminal Integer _class, _else, _fi, _if, _in, _inherits, _let, _loop, _pool, _then, _while; | |
nonterminal Integer _case, _esac, _of, _darrow, _new, _isvoid; | |
nonterminal Integer _assign, _not, _le; | |
nonterminal Integer _plus, _div, _minus, _mult, _eq, _lt, _dot, _neg, _comma, _semi, _colon; | |
nonterminal Integer _lparen, _rparen, _at, _lbrace, _rbrace; | |
/* Precedence declarations */ | |
precedence right ASSIGN; | |
precedence left NOT; | |
precedence nonassoc LT, LE, EQ; | |
precedence left PLUS, MINUS; | |
precedence left MULT, DIV; | |
precedence left ISVOID; | |
precedence left NEG; | |
precedence left AT; | |
precedence left DOT; | |
program | |
::= dummy:l class_list:cl | |
{: RESULT = new programc(l, cl); update_line(); :} | |
; | |
dummy // token for getting the program correct line | |
::= | |
{: RESULT = curr_lineno(); update_line(); :} | |
; | |
class_list | |
::= | |
/* single class */ | |
class:c _semi:_line | |
{: RESULT = (new Classes(_line)).appendElement(c); update_line(); :} | |
/* several classes */ | |
| class_list:cl class:c _semi {: RESULT = cl.appendElement(c); :} | |
| error RBRACE SEMI | |
; | |
/* NON TERMINAL WRAPPERS FOR TERMINALS: needed for tracking correct line numbers */ | |
_class ::= CLASS {: RESULT = line; update_line(); :}; | |
_else ::= ELSE {: RESULT = line; update_line(); :}; | |
_fi ::= FI {: RESULT = line; update_line(); :}; | |
_if ::= IF {: RESULT = line; update_line(); :}; | |
_in ::= IN {: RESULT = line; update_line(); :}; | |
_inherits ::= INHERITS {: RESULT = line; update_line(); :}; | |
_let ::= LET {: RESULT = line; update_line(); :}; | |
_loop ::= LOOP {: RESULT = line; update_line(); :}; | |
_pool ::= POOL {: RESULT = line; update_line(); :}; | |
_then ::= THEN {: RESULT = line; update_line(); :}; | |
_while ::= WHILE {: RESULT = line; update_line(); :}; | |
_case ::= CASE {: RESULT = line; update_line(); :}; | |
_esac ::= ESAC {: RESULT = line; update_line(); :}; | |
_of ::= OF {: RESULT = line; update_line(); :}; | |
_darrow ::= DARROW {: RESULT = line; update_line(); :}; | |
_new ::= NEW {: RESULT = line; update_line(); :}; | |
_isvoid ::= ISVOID {: RESULT = line; update_line(); :}; | |
_assign ::= ASSIGN {: RESULT = line; update_line(); :}; | |
_not ::= NOT {: RESULT = line; update_line(); :}; | |
_le ::= LE {: RESULT = line; update_line(); :}; | |
_plus ::= PLUS {: RESULT = line; update_line(); :}; | |
_div ::= DIV {: RESULT = line; update_line(); :}; | |
_minus ::= MINUS {: RESULT = line; update_line(); :}; | |
_mult ::= MULT {: RESULT = line; update_line(); :}; | |
_eq ::= EQ {: RESULT = line; update_line(); :}; | |
_lt ::= LT {: RESULT = line; update_line(); :}; | |
_dot ::= DOT {: RESULT = line; update_line(); :}; | |
_neg ::= NEG {: RESULT = line; update_line(); :}; | |
_comma ::= COMMA {: RESULT = line; update_line(); :}; | |
_semi ::= SEMI {: RESULT = line; update_line(); :}; | |
_colon ::= COLON {: RESULT = line; update_line(); :}; | |
_lparen ::= LPAREN {: RESULT = line; update_line(); :}; | |
_rparen ::= RPAREN {: RESULT = line; update_line(); :}; | |
_at ::= AT {: RESULT = line; update_line(); :}; | |
_lbrace ::= LBRACE {: RESULT = line; update_line(); :}; | |
_rbrace ::= RBRACE {: RESULT = line; update_line(); :}; | |
class | |
::= | |
/* class TYPE { } */ | |
_class:_line TYPEID:n _lbrace _rbrace | |
{: RESULT = new class_c(_line, n, AbstractTable.idtable.addString("Object"), new Features (_line), curr_filename()); update_line(); :} | |
/* class TYPE [inherits TYPE] { [[feature; ]] ∗ } */ | |
| _class:_line TYPEID:n _inherits TYPEID:p _lbrace _rbrace | |
{: RESULT = new class_c(_line, n, p, new Features (_line), curr_filename()); update_line(); :} | |
/* class TYPE { [[feature; ]] ∗ } */ | |
| _class:_line TYPEID:n _lbrace feature_list:fl _rbrace | |
{: RESULT = new class_c(_line, n, AbstractTable.idtable.addString("Object"), fl, curr_filename()); update_line(); :} | |
/* class TYPE [inherits TYPE] { [[feature; ]] ∗ } */ | |
| _class:_line TYPEID:n _inherits TYPEID:p _lbrace feature_list:fl _rbrace | |
{: RESULT = new class_c(_line, n, p, fl, curr_filename()); update_line(); :} | |
; | |
feature | |
/* ID( ) : TYPE { expr } */ | |
::= OBJECTID:id _lparen:_line _rparen _colon TYPEID:type _lbrace expression:e _rbrace | |
{: RESULT = new method(_line, id, new Formals(_line),type,e); update_line(); :} | |
/* ID( [ formal [[, formal]] ∗ ] ) : TYPE { expr } */ | |
| OBJECTID:id _lparen:_line formal_list:fl _rparen _colon TYPEID:type _lbrace expression:e _rbrace | |
{: RESULT = new method(_line, id, fl, type, e); update_line(); :} | |
/* ID : TYPE */ | |
| OBJECTID:id _colon:_line TYPEID:type | |
{: RESULT = new attr(_line, id, type, new no_expr (0) ); update_line(); :} | |
/* ID : TYPE [ <- expr ] */ | |
| OBJECTID:id _colon:_line TYPEID:type _assign expression:e | |
{: RESULT = new attr(_line, id, type, e ); update_line(); :} | |
; | |
feature_list | |
::= | |
feature:f _semi:_line | |
{: RESULT = (new Features(_line)).appendElement(f); update_line(); :} | |
| feature_list:fl feature:f _semi | |
{: RESULT = fl.appendElement(f); :} | |
| error _semi | |
{: RESULT = new Features(0); update_line(); :} | |
; | |
formal | |
::= | |
/* ID : TYPE */ | |
OBJECTID:id _colon:_line TYPEID:type | |
{: RESULT = new formalc (_line, id, type) ; update_line(); :} | |
; | |
formal_list | |
::= formal:f | |
{: RESULT = (new Formals(line)).appendElement(f); update_line(); :} | |
| formal_list:fl _comma formal:f | |
{: RESULT = fl.appendElement(f); :} | |
| error _semi | |
{: RESULT = new Formals(0); update_line(); :} | |
| error | |
{: RESULT = new Formals(0); update_line(); :} | |
; | |
expression_list_semi | |
/* single expression */ | |
::= expression:e _semi:_line | |
{: RESULT = (new Expressions(e.getLineNumber())).appendElement(e); update_line(); :} | |
/* multiple expressions */ | |
| expression_list_semi:el expression:e _semi:_line | |
{: RESULT = el.appendElement(e); :} | |
; | |
expression_list_comma | |
::= expression:e | |
{: RESULT = (new Expressions(e.getLineNumber())).appendElement(e); update_line(); :} | |
| expression_list_comma:el _comma:_line expression:e | |
{: RESULT = el.appendElement(e); :} | |
; | |
nested_let | |
::= | |
/* , ID : TYPE <- expr in expr */ | |
_comma OBJECTID:id _colon:_line TYPEID:type _assign expression:e1 _in expression:e2 | |
{: RESULT = new let(_line, id, type, e1, e2); update_line(); :} | |
/* , ID : TYPE in expr */ | |
| _comma OBJECTID:id _colon:_line TYPEID:type _in expression:e | |
{: RESULT = new let(_line, id, type, new no_expr(0), e); update_line(); :} | |
/* , ID : TYPE <- expr , ... */ | |
| _comma OBJECTID:id _colon:_line TYPEID:type _assign expression:e1 nested_let:e2 | |
{: RESULT = new let(_line, id, type, e1, e2); update_line(); :} | |
/* , ID : TYPE , ... */ | |
| _comma OBJECTID:id _colon:_line TYPEID:type nested_let:e | |
{: RESULT = new let(_line, id, type, new no_expr(0), e); update_line(); :} | |
/* error handling */ | |
| error nested_let:e2 | |
{: update_line(); :} | |
| error _in | |
{: update_line(); :} | |
| error _assign expression nested_let:e | |
{: update_line(); :} | |
| error _assign expression _in expression:e | |
{: update_line(); :} | |
| error _colon _assign expression nested_let:e | |
{: update_line(); :} | |
| error _colon _assign expression _in expression:e | |
{: update_line(); :} | |
| _comma error nested_let:e2 | |
{: update_line(); :} | |
| _comma error _in | |
{: update_line(); :} | |
| _comma error _assign expression nested_let:e | |
{: update_line(); :} | |
| _comma error _assign expression _in expression:e | |
{: update_line(); :} | |
| _comma error _colon _assign expression nested_let:e | |
{: update_line(); :} | |
| _comma error _colon _assign expression _in expression:e | |
{: update_line(); :} | |
| _comma OBJECTID:id error nested_let:e | |
{: update_line(); :} | |
| _comma OBJECTID:id error _in | |
{: update_line(); :} | |
; | |
single_case | |
::= | |
/* ID : TYPE => expr; */ | |
OBJECTID:id _colon:_line TYPEID:type _darrow expression:e _semi | |
{: RESULT = new branch(_line, id, type, e); update_line(); :} | |
; | |
case_list | |
/* Single case */ | |
::= single_case:sc | |
{: RESULT = (new Cases(sc.getLineNumber())).appendElement(sc); update_line(); :} | |
/* multiple cases */ | |
| case_list:cl single_case:sc | |
{: RESULT = cl.appendElement(sc); :} | |
; | |
_block | |
::= | |
/* { [[expr; ]] + } */ | |
_lbrace:_line expression_list_semi:els _rbrace | |
{: RESULT = new block(_line, els); update_line(); :} | |
/* error handling */ | |
| error | |
{: RESULT = new block(0, new Expressions(0)); update_line(); :} | |
; | |
expression | |
::= | |
/* ID <- expr */ | |
OBJECTID:id _assign:_line expression:e | |
{: RESULT = new assign(_line, id, e) ; update_line(); :} | |
/* expr.ID() */ | |
| expression:e1 _dot:_line OBJECTID:id _lparen:_line1 _rparen | |
{: RESULT = new dispatch(_line, e1, id, new Expressions(_line1) ) ; update_line(); :} | |
/* expr@TYPE.ID() */ | |
| expression:e1 _at TYPEID:type _dot:_line OBJECTID:id _lparen:_line1 _rparen | |
{: RESULT = new static_dispatch(_line, e1, type, id, new Expressions(_line1)); update_line(); :} | |
/* expr.ID([[ expr ]]+ ) */ | |
| expression:e1 _dot:_line OBJECTID:id _lparen expression_list_comma:el _rparen | |
{: RESULT = new dispatch(_line, e1, id, el); update_line(); :} | |
/* expr@TYPE.ID([[ expr ]]+ ) */ | |
| expression:e1 _at TYPEID:type _dot:_line OBJECTID:id _lparen expression_list_comma:el _rparen | |
{: RESULT = new static_dispatch(_line, e1, type, id, el); update_line(); :} | |
/* ID() */ | |
| OBJECTID:id _lparen:_line _rparen | |
{: RESULT = new dispatch(_line, new object(_line, AbstractTable.idtable.addString("self")), id, new Expressions(_line)); update_line(); :} | |
/* ID([[ expr ]]+ ) */ | |
| OBJECTID:id _lparen:_line expression_list_comma:el _rparen | |
{: RESULT = new dispatch(_line, new object(_line, AbstractTable.idtable.addString("self")), id, el); update_line(); :} | |
/* IF expr THEN expr ELSE expr FI */ | |
| _if:_line expression:e1 _then expression:e2 _else expression:e3 _fi | |
{: RESULT = new cond(_line, e1,e2,e3); update_line(); :} | |
/* WHILE expr LOOP expr POOL */ | |
| _while:_line expression:e1 _loop expression:e2 _pool | |
{: RESULT = new loop(_line, e1, e2); update_line(); :} | |
/* { [[expr; ]] + } */ | |
| _block:b | |
{: RESULT = b; update_line(); :} | |
/* LET ID : TYPE <- expr in expr */ | |
| _let OBJECTID:id _colon:_line TYPEID:type _assign expression:e1 _in expression:e2 | |
{: RESULT = new let(_line, id, type, e1, e2); update_line(); :} | |
/* LET ID : TYPE in expr */ | |
| _let OBJECTID:id _colon:_line TYPEID:type _in expression:e | |
{: RESULT = new let(_line, id, type, new no_expr(0), e); update_line(); :} | |
/* LET ID : TYPE <- expr [[ NESTED_LET ]]+ */ | |
| _let OBJECTID:id _colon:_line TYPEID:type _assign expression:e1 nested_let:e2 | |
{: RESULT = new let(_line, id, type, e1, e2); update_line(); :} | |
/* LET ID : TYPE [[ NESTED_LET ]]+ */ | |
| _let OBJECTID:id _colon:_line TYPEID:type nested_let:e | |
{: RESULT = new let(_line, id, type, new no_expr(0), e); update_line(); :} | |
/* error handling */ | |
| _let error _in | |
{: update_line(); :} | |
| _let error nested_let:e | |
{: update_line(); :} | |
| error _assign expression nested_let:e | |
{: update_line(); :} | |
/* CASE expr OF [[ID : TYPE => expr; ]]+ ESAC */ | |
| _case:_line expression:e _of case_list:cl _esac | |
{: RESULT = new typcase (_line, e, cl); update_line(); :} | |
/* | |
we need %prec OPER because we need to define precedence among symbols w/ equal precedence | |
for example: | |
let consider: a - d * (a / d) = 0 | |
this expr should produce the following sub-tree: | |
EQ | |
|____SUB | |
| |_____ a | |
| |_____ MUL | |
| |_____ d | |
| |_____ DIV | |
| |______ a | |
| |______ d | |
| | |
|____ 0 | |
but w/o %prec it would produce this wrong sub-tree: | |
SUB | |
|____MUL | |
| |_____ d | |
| |_____ EQ | |
| |_____ 0 | |
| |_____ DIV | |
| |______ a | |
| |______ d | |
| | |
|____ a | |
But why? | |
* To each production that contains at least one terminal | |
defined as operator, Cup associates the precedence and | |
associativity of the rightmost operator. | |
* If the rule is followed by the keyword %prec, the | |
precedence and associativity are those of the specified | |
operator. | |
* In the case of a shift-reduce conflict, the action | |
corresponding to the highest precedence production is | |
executed. | |
* In the case of a shift-reduce conflict, the action | |
corresponding to the highest precedence production is | |
executed. | |
*/ | |
/* expr + expr */ | |
| expression:e1 _plus:_line expression:e2 | |
{: RESULT = new plus (_line, e1, e2); update_line(); :} | |
%prec PLUS | |
/* expr - expr */ | |
| expression:e1 _minus:_line expression:e2 | |
{: RESULT = new sub (_line, e1, e2) ; update_line(); :} | |
%prec MINUS | |
/* expr * expr */ | |
| expression:e1 _mult:_line expression:e2 | |
{: RESULT = new mul (_line, e1, e2) ; update_line(); :} | |
%prec MULT | |
/* expr / expr */ | |
| expression:e1 _div:_line expression:e2 | |
{: RESULT = new divide (_line, e1, e2); update_line(); :} | |
%prec DIV | |
/* expr < expr */ | |
| expression:e1 _lt:_line expression:e2 | |
{: RESULT = new lt (_line, e1, e2); update_line(); :} | |
/* expr <= expr */ | |
| expression:e1 _le:_line expression:e2 | |
{: RESULT = new leq (_line, e1, e2); update_line(); :} | |
/* expr = expr */ | |
| expression:e1 _eq:_line expression:e2 | |
{: RESULT = new eq (_line, e1, e2); update_line(); :} | |
/* ~ expr */ | |
| _neg:_line expression:e | |
{: RESULT = new neg (_line, e); update_line(); :} | |
%prec NEG | |
/* NOT expr */ | |
| _not:_line expression:e | |
{: RESULT = new comp(_line, e); update_line(); :} | |
%prec NOT | |
/* (expr) */ | |
| _lparen:_line expression:e _rparen | |
{: RESULT = e; update_line(); :} | |
/* ID */ | |
| OBJECTID:id | |
{: RESULT = new object(line, id); update_line(); :} | |
| error OBJECTID:id | |
{: RESULT = new object(line, id); update_line(); :} | |
/* integer const */ | |
| INT_CONST:i | |
{: RESULT = new int_const(line, i); update_line(); :} | |
/* string const */ | |
| STR_CONST:string | |
{: RESULT = new string_const(line, string); update_line(); :} | |
/* true|false */ | |
| BOOL_CONST:b | |
{: RESULT = new bool_const(line, b); update_line(); :} | |
/* ISVOID expr */ | |
| _isvoid:_line expression:e | |
{: RESULT = new isvoid (_line, e); update_line(); :} | |
/* NEW TYPE */ | |
| _new:_line TYPEID:type | |
{: RESULT = new new_(_line, type); update_line(); :} | |
; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment