Skip to content

Instantly share code, notes, and snippets.

@korniltsev
Last active August 29, 2015 14:02
Show Gist options
  • Select an option

  • Save korniltsev/23ada2f438a0c4f5a7f9 to your computer and use it in GitHub Desktop.

Select an option

Save korniltsev/23ada2f438a0c4f5a7f9 to your computer and use it in GitHub Desktop.
cool.cup 70
/*
* cool.cup
* 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();
}
int c() {
return curr_lineno();
}
AbstractSymbol curr_filename() {
return ((CoolTokenLexer)parser.getScanner()).curr_filename();
}
:}
/************************************************************************/
/* DONT CHANGE ANYTHING IN THIS SECTION */
parser code {:
int omerrs = 0;
public void syntax_error(Symbol cur_token) {
int lineno = action_obj.c();
String filename = action_obj.curr_filename().getString();
System.err.print("\"" + filename + "\", line " + lineno +
": parse 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 programc program;
nonterminal Classes class_list;
nonterminal class_c class;
nonterminal Features feature_list;
nonterminal attr attribute;
nonterminal method method_;
nonterminal let let_;
nonterminal Expressions dispatch_arg_list;
nonterminal Expressions expression_list;
nonterminal Expression expr;
nonterminal Formal formal;
nonterminal Formals formal_list;
nonterminal Cases case_list;
/* Precedence declarations go here. */
precedence left ASSIGN;
precedence nonassoc LE, LT, EQ;
precedence left PLUS, MINUS;
precedence left MULT, DIV;
precedence left ISVOID;
precedence left NEG;
precedence left AT;
precedence left DOT;
program
::= class_list:cl
{: RESULT = new programc(c(), cl); :}
;
class_list
/* single class */
::= class:c
{: RESULT = (new Classes(c())).appendElement(c); :}
/* several classes */
| class_list:cl class:c
{: RESULT = cl.appendElement(c); :}
;
/* If no parent is specified, the class inherits from the Object class */
class
::= CLASS TYPEID:n LBRACE feature_list:f RBRACE SEMI
{: RESULT = new class_c(c(), n,
AbstractTable.idtable.addString("Object"),
f, curr_filename()); :}
| CLASS TYPEID:n INHERITS TYPEID:p LBRACE feature_list:f RBRACE SEMI
{: RESULT = new class_c(c(), n, p, f, curr_filename()); :}
| error SEMI
;
/* Feature list may be empty, but no empty features in list. */
feature_list
::= /* empty */
{: RESULT = new Features(c()); :}
| attribute:a
{: RESULT = new Features(c()).appendElement(a); :}
| method_:m
{: RESULT = new Features(c()).appendElement(m); :}
| feature_list:fs attribute:a
{: RESULT = fs.appendElement(a);:}
| feature_list:fs method_:m
{: RESULT = fs.appendElement(m);:}
;
method_
::= OBJECTID:o LPAREN formal_list:fs RPAREN COLON TYPEID:t LBRACE expr:e RBRACE SEMI
{: RESULT = new method(c(), o, fs, t, e); :}
| error SEMI
;
formal_list
::= /* empty */
{: RESULT = new Formals(c()); :}
| formal:f
{: RESULT = new Formals(c()).appendElement(f); :}
| formal_list:fs COMMA formal:f
{: RESULT = fs.appendElement(f); :}
;
formal
::= OBJECTID:o COLON TYPEID:t
{: RESULT = new formalc(c(), o, t);:}
;
attribute
::= OBJECTID:o COLON TYPEID:t SEMI
{: RESULT = new attr(c(),o,t, new no_expr(c())); :}
| OBJECTID:o COLON TYPEID:t ASSIGN expr:e SEMI
{: RESULT = new attr(c(),o,t, e ); :}
| error SEMI
;
expr
::= OBJECTID:o ASSIGN expr:e
{: RESULT = new assign(c(), o, e); :}
| OBJECTID:o ASSIGN error
| expr:e DOT OBJECTID:m LPAREN dispatch_arg_list:as RPAREN
{: RESULT = new dispatch(c(), e , m, as); :}
| OBJECTID:m LPAREN dispatch_arg_list:as RPAREN
{: RESULT = new dispatch(c(), new object(c(), AbstractTable.idtable.addString("self")) , m, as); :}
| expr:e AT TYPEID:t DOT OBJECTID:m LPAREN dispatch_arg_list:as RPAREN
{: RESULT = new static_dispatch(c(), e,t, m, as); :}
| IF expr:p THEN expr:t ELSE expr:e FI
{: RESULT = new cond(c(), p, t, e); :}
| WHILE expr:pred LOOP expr:body POOL
{: RESULT = new loop(c(), pred, body); :}
| CASE expr:e OF case_list:cs ESAC
{: RESULT = new typcase(c(), e, cs); :}
| LPAREN expr:e RPAREN
{: RESULT = e; :}
| LBRACE expression_list:es RBRACE
{: RESULT = new block(c(), es); :}
| LET let_:l
{: RESULT = l; :}
| expr:e1 PLUS expr:e2
{: RESULT = new plus(c(), e1, e2); :}
| expr:e1 MINUS expr:e2
{: RESULT = new sub(c(), e1, e2); :}
| expr:e1 MULT expr:e2
{: RESULT = new mul(c(), e1, e2); :}
| expr:e1 DIV expr:e2
{: RESULT = new divide(c(), e1, e2); :}
| NEG expr:e
{: RESULT = new neg(c(), e); :}
| expr:e1 EQ expr:e2
{: RESULT = new eq(c(), e1, e2); :}
| expr:e1 LT expr:e2
{: RESULT = new lt(c(), e1, e2); :}
| expr:e1 LE expr:e2
{: RESULT = new leq(c(), e1, e2); :}
| NOT expr:e
{: RESULT = new comp(c(), e); :}
| STR_CONST:s
{: RESULT = new string_const(c(), AbstractTable.stringtable.addString(s.getString()));:}
| INT_CONST:i
{: RESULT = new int_const(c(), AbstractTable.inttable.addString(i.getString()));:}
| BOOL_CONST:b
{: RESULT = new bool_const(c(), b); :}
| NEW TYPEID:t
{: RESULT = new new_(c(), t); :}
| ISVOID expr:e
{: RESULT = new isvoid(c(), e); :}
| OBJECTID:o
{: RESULT = new object(c(), o); :}
;
let_
::= OBJECTID:o COLON TYPEID:t ASSIGN expr:e IN expr:body
{: RESULT = new let(c(), o,t,e,body); :}
| OBJECTID:o COLON TYPEID:t IN expr:body
{: RESULT = new let(c(), o,t,new no_expr(c()),body); :}
| OBJECTID:o COLON TYPEID:t COMMA let_:l
{: RESULT = new let(c(), o,t,new no_expr(c()), l); :}
| OBJECTID:o COLON TYPEID:t ASSIGN expr:e COMMA let_:l
{: RESULT = new let(c(), o,t,e, l); :}
| error COMMA let_
;
expression_list
::= expr:e SEMI
{: RESULT = new Expressions(c()).appendElement(e); :}
| expression_list:es expr:e SEMI
{: RESULT = es.appendElement(e); :}
| error SEMI
{: RESULT = new Expressions(c()); :}
;
dispatch_arg_list
::= /**/
{: RESULT = new Expressions(c()); :}
| expr:e
{: RESULT = new Expressions(c()).appendElement(e); :}
| dispatch_arg_list:as COMMA expr:e
{: RESULT = as.appendElement(e); :}
;
case_list
::= OBJECTID:o COLON TYPEID:t DARROW expr:e SEMI
{: RESULT = new Cases(c()).appendElement(new branch(c(), o,t,e)); :}
| case_list:cs OBJECTID:o COLON TYPEID:t DARROW expr:e SEMI
{: RESULT = cs.appendElement(new branch(c(),o,t,e)); :}
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment