package IC.Parser; import IC.Lexer.*; import IC.Error.*; import java_cup.runtime.*; import IC.Hierarchy.*; parser code {: public void syntax_error(java_cup.runtime.Symbol curToken) throws SyntaxError { Token token = (Token) curToken; throw new SyntaxError("Syntax Error: Unexpected "+(token.value==null ? "" : "\""+token.value.toString()+"\""), token.m_line, token.left, token.right); } :} //Terminals returned by the lexer terminal String IDENTIFIER; terminal PLUS; terminal MINUS; terminal STAR; terminal FORWARDSLASH; terminal PERCENT; terminal AND; terminal OR; terminal LESS; terminal LESSEQUAL; terminal GREATEREQUAL; terminal GREATER; terminal EQUAL; terminal ASSIGN; terminal NOTEQUAL; terminal BANG; terminal COMMENTDOUBLESLASH; terminal COMMENTSTARSLASH; terminal QUOTE; terminal BACKSLASH; terminal QUOTEESCAPE; terminal BACKSLASHESCAPE; terminal TAB; terminal NEWLINE; terminal CLASS; terminal RETURN; terminal THIS; terminal EXTENDS; terminal IF; terminal NEW; terminal VOID; terminal ELSE; terminal LENGTH; terminal INT; terminal WHILE; terminal TRUE; terminal BOOLEAN; terminal BREAK; terminal FALSE; terminal STRING; terminal CONTINUE; terminal NULL; terminal RPAREN; terminal LPAREN; terminal RBRACKET; terminal LBRACKET; terminal RBRACE; terminal LBRACE; terminal COMMA; terminal SEMICOLON; terminal PERIOD; terminal Long NUMBER; terminal String TEXT; terminal ERROR; //Non-terminals non terminal Node program; non terminal Node classDecls_opt; non terminal Node classDecls; non terminal Node classDecl; non terminal Node super_opt; non terminal Node super; non terminal Node class_body; non terminal Node class_body_decls_opt; non terminal Node class_body_decls; non terminal Node class_body_decl; non terminal Node fieldDecl; non terminal Node field_variable_declarators_opt; non terminal Node field_variable_declarators; non terminal Node field_variable_declarator; non terminal Node methDecl; non terminal Node meth_header; non terminal Node meth_body; non terminal Node method_declarator; non terminal Node formals_opt; non terminal Node formals; non terminal Node formals_list_opt; non terminal Node formals_list; non terminal Node formal_parameter; non terminal Node type; non terminal Node primitive_type; non terminal Node reference_type; non terminal Node array_type; non terminal Node block; non terminal Node block_statements_opt; non terminal Node block_statements; non terminal Node block_statement; non terminal Node varDecl; non terminal Node variable_declarators; non terminal Node variable_declarator; non terminal Node stmt; non terminal Node stmt_without_trailing_substatement; non terminal Node continue_statement; non terminal Node break_statement; non terminal Node return_statement; non terminal Node expr_opt; non terminal Node assign_statement; non terminal Node if_then_statement; non terminal Node if_then_else_statement; non terminal Node stmt_no_short_if; non terminal Node if_then_else_statement_no_short_if; non terminal Node while_statement; non terminal Node while_statement_no_short_if; non terminal Node assign; non terminal Node assignment_expression; //non terminal Node location; non terminal Node field_access; non terminal Node array_access; non terminal Node call; non terminal Node actuals_opt; non terminal Node method; non terminal Node actuals; non terminal Node expr; non terminal Node no_new_array_expr; non terminal Node array_creation_expr; non terminal Node binary_expr; non terminal Node unary_expr; non terminal Node literal; //Newly added non terminal Node assignment; non terminal Node primary_expr; non terminal Node unary_expr_not_minus_bang; non terminal Node name; non terminal Node simple_name; non terminal Node qualified_name; non terminal Node call_statement; non terminal Node varDecls_opt; non terminal Node varDecls; non terminal Node stmts_opt; non terminal Node stmts; //Precedences //precedence ASSIGN; precedence left OR; precedence left AND; precedence left EQUAL, NOTEQUAL; precedence left LESS, LESSEQUAL, GREATER, GREATEREQUAL; precedence left PLUS, MINUS; precedence left STAR, FORWARDSLASH, PERCENT; precedence left BANG; precedence left LPAREN, LBRACKET, PERIOD; // program ::= classDecls_opt:c {:RESULT = new Program(c);:}; classDecls_opt ::= {:RESULT = null;:} | classDecls:c {:RESULT = c;:} ; classDecls ::= classDecl:c {:RESULT = new ClassDecls(c,null);:} | classDecls:cs classDecl:c {:RESULT = new ClassDecls(c,cs);:} ; //Class declaration classDecl ::= CLASS IDENTIFIER:i super_opt:s class_body:c {:RESULT = new ClassDecl(new Id(i.toString()),s,c);:}; super_opt ::= {:RESULT = null;:} | super:s {:RESULT = s;:} ; super ::= EXTENDS IDENTIFIER:i {:RESULT = new Id(i.toString());:}; class_body ::= LBRACE class_body_decls_opt:c RBRACE {:RESULT = c;:}; class_body_decls_opt ::= {:RESULT = null;:} | class_body_decls:f {:RESULT = f;:} ; class_body_decls ::= class_body_decl:f {:RESULT = new FieldOrMethodDecls(f,null);:} | class_body_decls:fs class_body_decl:f {:RESULT = new FieldOrMethodDecls(f,fs);:} ; class_body_decl ::= fieldDecl:f {:RESULT = new FieldOrMethodDecl(f,null);:} | methDecl:m {:RESULT = new FieldOrMethodDecl(null,m);:} ; //Field declaration fieldDecl ::= type:t IDENTIFIER:i field_variable_declarators_opt:f SEMICOLON {:RESULT = new FieldDecl(t,new Id(i.toString()),f);:}; field_variable_declarators_opt ::= {:RESULT = null;:} | field_variable_declarators:f {:RESULT = f;:} ; field_variable_declarators ::= field_variable_declarator:f {:RESULT = new FieldDeclVars(f,null);:} | field_variable_declarators:fs field_variable_declarator:f {:RESULT = new FieldDeclVars(f,fs);:} ; field_variable_declarator ::= COMMA IDENTIFIER:i {:RESULT = new Id(i.toString());:}; //Method Declaration: methDecl ::= meth_header:m meth_body:b {:RESULT = new MethDecl(((MethDecl)m).t,((MethDecl)m).i,((MethDecl)m).f,b);:}; meth_header ::= type:t method_declarator:m {:RESULT = new MethDecl(t,((MethDecl)m).i,((MethDecl)m).f,((MethDecl)m).b);:} | VOID method_declarator:m {:RESULT = m;:} ; method_declarator ::= IDENTIFIER:i LPAREN formals_opt:f RPAREN {:RESULT = new MethDecl(null,new Id(i.toString()),f,null);:}; formals_opt ::= {:RESULT = null;:} | formals:f {:RESULT = f;:} ; meth_body ::= block:b {:RESULT = b;:}; formals ::= formal_parameter:f {:RESULT = f;:} | formals:fs COMMA formal_parameter:fp {:RESULT = new Formals(((Formals)fp).t,((Formals)fp).i,fs);:} ; formal_parameter ::= type:t IDENTIFIER:i {:RESULT = new Formals(t,new Id(i.toString()));:}; //Types type ::= primitive_type:t {:RESULT = t;:} | reference_type:t {:RESULT = t;:} ; primitive_type ::= INT {:RESULT = new IntType();:} | BOOLEAN {:RESULT = new BoolType();:} | STRING {:RESULT = new StringType();:} ; reference_type ::= simple_name:s {:RESULT = new IdType(s);:} | array_type:a {:RESULT = a;:} ; array_type ::= type:t LBRACKET RBRACKET {:RESULT = new ArrayType(t);:}; block ::= LBRACE varDecls:v stmts_opt:s RBRACE {:RESULT = new Block(v,s);:} | LBRACE stmts_opt:s RBRACE {:RESULT = new Block(null,s);:} ; varDecls ::= varDecl:v {:RESULT = new VarDeclMulti(v);:} | varDecls:vs varDecl:v {:RESULT = new VarDeclMulti(v,vs);:} ; stmts_opt ::= {:RESULT = null;:} | stmts:s {:RESULT = s;:} ; stmts ::= stmt:st {:RESULT = new Stmts(st);:} | stmts:sts stmt:st {:RESULT = new Stmts(st,sts);:} ; //Variable Declaration varDecl ::= type:t variable_declarators:v SEMICOLON {:RESULT = new VarDecl(t,v);:}; variable_declarators ::= variable_declarator:v {:RESULT = new VarDecls(((VarDecls)v).i,((VarDecls)v).e);:} | variable_declarators:vs COMMA variable_declarator:v {:RESULT = new VarDecls(((VarDecls)v).i,((VarDecls)v).e,vs);:} ; variable_declarator ::= IDENTIFIER:i {:RESULT = new VarDecls(new Id(i.toString()),null);:} | IDENTIFIER:i ASSIGN expr:e {:RESULT = new VarDecls(new Id(i.toString()),e);:} ; //Statements stmt ::= stmt_without_trailing_substatement:s {:RESULT = s;:} | if_then_statement:s {:RESULT = s;:} | if_then_else_statement:s {:RESULT = s;:} | while_statement:s {:RESULT = s;:} ; stmt_without_trailing_substatement ::= block:b {:RESULT = b;:} | continue_statement:s {:RESULT = s;:} | break_statement:s {:RESULT = s;:} | return_statement:s {:RESULT = s;:} | assign_statement:s {:RESULT = s;:} | call_statement:s {:RESULT = s;:} ; continue_statement ::= CONTINUE SEMICOLON {:RESULT = new ContinueStmt();:}; break_statement ::= BREAK SEMICOLON {:RESULT = new BreakStmt();:}; return_statement ::= RETURN expr_opt:e SEMICOLON {:RESULT = new ReturnStmt(e);;:}; expr_opt ::= {:RESULT = null;:} | expr:e {:RESULT = e;:} //WAS CHANGED ; assign_statement ::= assignment:a SEMICOLON {:RESULT = new AssignStmt(a);:}; call_statement ::= call:c SEMICOLON {:RESULT = new CallStmt(c);:}; if_then_statement ::= IF LPAREN expr:e RPAREN stmt:s {:RESULT = new IfStmt(e,s);:}; //WAS CHANGED if_then_else_statement ::= IF LPAREN expr:e RPAREN stmt_no_short_if:s1 ELSE stmt:s2 {:RESULT = new IfElseStmt(e,s1,s2);:}; //WAS CHANGED stmt_no_short_if ::= stmt_without_trailing_substatement:s {:RESULT = s;:} | if_then_else_statement_no_short_if:s {:RESULT = s;:} | while_statement_no_short_if:s {:RESULT = s;:} ; if_then_else_statement_no_short_if ::= IF LPAREN expr:e RPAREN stmt_no_short_if:s1 ELSE stmt_no_short_if:s2 {:RESULT = new IfElseStmt(e,s1,s2);:} //WAS CHANGED ; while_statement ::= WHILE LPAREN expr:e RPAREN stmt:s {:RESULT = new WhileStmt(e,s);:} //WAS CHANGED ; while_statement_no_short_if ::= WHILE LPAREN expr:e RPAREN stmt_no_short_if:s {:RESULT = new WhileStmt(e,s);:} //WAS CHANGED ; //Method Invocation call ::= IDENTIFIER:i LPAREN actuals_opt:a RPAREN {:RESULT = new Call(new Id(i.toString()),a);:} | primary_expr:e LPAREN actuals_opt:a RPAREN {:RESULT = new Call(e,null,a);:} ; actuals_opt ::= {:RESULT = new Actuals(null);:} | actuals:a {:RESULT = a;:} ; actuals ::= expr:e {:RESULT = new Actuals(e);:} //WAS CHANGED | actuals:a COMMA expr:e {:RESULT = new Actuals(a,e);:} //WAS CHANGED ; //Expressions primary_expr ::= no_new_array_expr:e {:RESULT = e;:} | array_creation_expr:e {:RESULT = e;:} ; no_new_array_expr ::= call:c {:RESULT = c;:} | THIS {:RESULT = new This();:} | NEW IDENTIFIER:i LPAREN RPAREN {:RESULT = new NewIdExpr(new Id(i.toString()));:} | primary_expr:e PERIOD LENGTH {:RESULT = new LengthExpr(e);:} | IDENTIFIER:i PERIOD LENGTH {:RESULT = new LengthExpr(new Id(i.toString()));:} | literal:l {:RESULT = l;:} | LPAREN expr:e RPAREN {:RESULT = e;:} | field_access:f {:RESULT = f;:} | array_access:a {:RESULT = a;:} ; array_creation_expr ::= NEW type:t LBRACKET primary_expr:e RBRACKET {:RESULT = new NewArrayExpr(t,e);:} | NEW type:t LBRACKET IDENTIFIER:i RBRACKET {:RESULT = new NewArrayExpr(t,new Id(i.toString()));:} ; field_access ::= primary_expr:e PERIOD IDENTIFIER:i {:RESULT = new FieldAccess(e,new Id(i.toString()));:} | IDENTIFIER:i1 PERIOD IDENTIFIER:i2 {:RESULT = new FieldAccess(new Id(i1.toString()),new Id(i2.toString()));:} ; //DONE array_access ::= no_new_array_expr:e1 LBRACKET expr:e2 RBRACKET {:RESULT = new ArrayAccess(e1,e2);:} //WAS CHANGED | simple_name:s LBRACKET expr:e RBRACKET {:RESULT = new ArrayAccess(s,e);:} //WAS CHANGED | qualified_name:q LBRACKET expr:e RBRACKET {:RESULT = new ArrayAccess(q,e);:} //WAS CHANGED ; //DONE simple_name ::= IDENTIFIER:i {:RESULT = new Id(i.toString());:}; //DONE qualified_name ::= simple_name:s PERIOD IDENTIFIER:i {:RESULT = new Ids((Id)s,new Ids(new Id(i.toString()),null));:} | qualified_name:q PERIOD IDENTIFIER:i {:RESULT = new Ids(new Id(i.toString()),q);:} ; //DONE binary_expr ::= unary_expr:e {:RESULT = e;:} | binary_expr:e1 PLUS unary_expr:e2 {:RESULT = new Add(e1,e2);:} | binary_expr:e1 MINUS unary_expr:e2 {:RESULT = new Sub(e1,e2);:} | binary_expr:e1 STAR unary_expr:e2 {:RESULT = new Mul(e1,e2);:} | binary_expr:e1 FORWARDSLASH unary_expr:e2 {:RESULT = new Div(e1,e2);:} | binary_expr:e1 PERCENT unary_expr:e2 {:RESULT = new Mod(e1,e2);:} | binary_expr:e1 AND unary_expr:e2 {:RESULT = new And(e1,e2);:} | binary_expr:e1 OR unary_expr:e2 {:RESULT = new Or(e1,e2);:} | binary_expr:e1 LESS unary_expr:e2 {:RESULT = new Less(e1,e2);:} | binary_expr:e1 LESSEQUAL unary_expr:e2 {:RESULT = new LessEqual(e1,e2);:} | binary_expr:e1 GREATER unary_expr:e2 {:RESULT = new Greater(e1,e2);:} | binary_expr:e1 GREATEREQUAL unary_expr:e2 {:RESULT = new GreaterEqual(e1,e2);:} | binary_expr:e1 EQUAL unary_expr:e2 {:RESULT = new Equal(e1,e2);:} | binary_expr:e1 NOTEQUAL unary_expr:e2 {:RESULT = new NotEqual(e1,e2);:} ; //DONE unary_expr ::= MINUS unary_expr:e {:RESULT = new Neg(e);:} | BANG unary_expr:e {:RESULT = new Not(e);:} | unary_expr_not_minus_bang:e {:RESULT = e;:} ; //DONE unary_expr_not_minus_bang ::= primary_expr:e {:RESULT = e;:} | simple_name:s {:RESULT = s;:} // | qualified_name:q {:RESULT = q;:} ; assignment ::= IDENTIFIER:i ASSIGN expr:e {:RESULT = new Assign(new Id(i.toString()),e);:} | field_access:f ASSIGN expr:e {:RESULT = new Assign(f,e);:} | array_access:a ASSIGN expr:e {:RESULT = new Assign(a,e);:} ; //DONE expr ::= binary_expr:e {:RESULT = e;:}; //CHANGED //DONE literal ::= NUMBER:n {: RESULT = new Num(n.longValue()); :} | TEXT:t {: RESULT = new Text(t.toString()); :} | TRUE {: RESULT = new Bool(true);:} | FALSE {: RESULT = new Bool(false);:} | NULL {: RESULT = new Null();:} ;