package Parse; import java_cup.runtime.*; import Lex.Lexer; import IR.Tree.*; /* Java 1.4 parser for CUP. * Copyright (C) 2002-2003 C. Scott Ananian * This program is released under the terms of the GPL; see the file * COPYING for more details. There is NO WARRANTY on this code. */ /* JDK 1.4 Features added: assertion statement. statement_without_trailing_substatement ::= ... | assert_statement ; assert_statement ::= ASSERT expression SEMICOLON | ASSERT expression COLON expression SEMICOLON ; */ parser code {: Lexer lexer; public Parser(Lexer l) { this(); lexer=l; } public void syntax_error(java_cup.runtime.Symbol current) { report_error("Syntax error (" + current.sym + ")", current); } public void report_error(String message, java_cup.runtime.Symbol info) { lexer.errorMsg(message, info); } :}; scan with {: return lexer.nextToken(); :}; terminal BOOLEAN; // primitive_type terminal BYTE, SHORT, INT, LONG, CHAR; // integral_type terminal FLOAT, DOUBLE; // floating_point_type terminal LBRACK, RBRACK; // array_type terminal java.lang.String IDENTIFIER; // name terminal DOT; // qualified_name terminal SEMICOLON, MULT, COMMA, LBRACE, RBRACE, EQ, LPAREN, RPAREN, COLON; terminal PACKAGE; // package_declaration terminal IMPORT; // import_declaration terminal PUBLIC, PROTECTED, PRIVATE; // modifier terminal STATIC; // modifier terminal ABSTRACT, FINAL, NATIVE, SYNCHRONIZED, TRANSIENT, VOLATILE; terminal CLASS; // class_declaration terminal EXTENDS; // super //terminal IMPLEMENTS; // interfaces terminal VOID; // method_header terminal THROWS; // throws terminal THIS, SUPER; // explicit_constructor_invocation //terminal INTERFACE; // interface_declaration terminal IF, ELSE; // if_then_statement, if_then_else_statement terminal SWITCH; // switch_statement terminal CASE, DEFAULT; // switch_label terminal DO, WHILE; // while_statement, do_statement terminal FOR; // for_statement terminal BREAK; // break_statement terminal CONTINUE; // continue_statement terminal RETURN; // return_statement terminal THROW; // throw_statement terminal TRY; // try_statement terminal CATCH; // catch_clause terminal FINALLY; // finally terminal NEW; // class_instance_creation_expression terminal PLUSPLUS; // postincrement_expression terminal MINUSMINUS; // postdecrement_expression terminal PLUS, MINUS, COMP, NOT, DIV, MOD; terminal LSHIFT, RSHIFT, URSHIFT; // shift_expression terminal LT, GT, LTEQ, GTEQ, INSTANCEOF; // relational_expression terminal EQEQ, NOTEQ; // equality_expression terminal AND; // and_expression terminal XOR; // exclusive_or_expression terminal OR; // inclusive_or_expression terminal ANDAND; // conditional_and_expression terminal OROR; // conditional_or_expression terminal QUESTION; // conditional_expression terminal MULTEQ, DIVEQ, MODEQ, PLUSEQ, MINUSEQ; // assignment_operator terminal LSHIFTEQ, RSHIFTEQ, URSHIFTEQ; // assignment_operator terminal ANDEQ, XOREQ, OREQ; // assignment_operator terminal java.lang.Number INTEGER_LITERAL; terminal java.lang.Number FLOATING_POINT_LITERAL; terminal java.lang.Boolean BOOLEAN_LITERAL; terminal java.lang.Character CHARACTER_LITERAL; terminal java.lang.String STRING_LITERAL; terminal NULL_LITERAL; // Reserved but unused: terminal CONST, GOTO; // strictfp keyword, new in Java 1.2 terminal STRICTFP; // assert keyword, new in Java 1.4 terminal ASSERT; // assert_statement // lexer compatibility with Java 1.5 terminal ELLIPSIS; terminal ENUM; // 19.2) The Syntactic Grammar non terminal ParseNode goal; // 19.3) Lexical Structure non terminal ParseNode literal; // 19.4) Types, Values, and Variables non terminal ParseNode type, primitive_type, numeric_type; non terminal ParseNode integral_type, floating_point_type; non terminal ParseNode reference_type; non terminal ParseNode class_or_interface_type; non terminal ParseNode class_type; //non terminal ParseNode interface_type; non terminal ParseNode array_type; // 19.5) Names non terminal ParseNode name, simple_name, qualified_name; // 19.6) Packages non terminal ParseNode compilation_unit; //non terminal ParseNode package_declaration_opt, package_declaration; //non terminal ParseNode import_declarations_opt, import_declarations; non terminal ParseNode type_declarations_opt, type_declarations; //non terminal ParseNode import_declaration; //non terminal ParseNode single_type_import_declaration; //non terminal ParseNode type_import_on_demand_declaration; non terminal ParseNode type_declaration; // 19.7) Productions used only in the LALR(1) grammar non terminal ParseNode modifiers_opt, modifiers, modifier; // 19.8.1) Class Declaration non terminal ParseNode class_declaration, super, super_opt; //non terminal interfaces, interfaces_opt, interface_type_list; non terminal ParseNode class_body; non terminal ParseNode class_body_declarations, class_body_declarations_opt; non terminal ParseNode class_body_declaration, class_member_declaration; // 19.8.2) Field Declarations non terminal ParseNode field_declaration, variable_declarators, variable_declarator; non terminal ParseNode variable_declarator_id; non terminal ParseNode variable_initializer; // 19.8.3) Method Declarations non terminal ParseNode method_declaration, method_header, method_declarator; non terminal ParseNode formal_parameter_list_opt, formal_parameter_list; non terminal ParseNode formal_parameter; //non terminal ParseNode throws_opt; //non terminal ParseNode throws; //non terminal ParseNode class_type_list; non terminal ParseNode method_body; // 19.8.4) Static Initializers //non terminal ParseNode static_initializer; // 19.8.5) Constructor Declarations non terminal ParseNode constructor_declaration, constructor_declarator; non terminal ParseNode constructor_body; //non terminal ParseNode explicit_constructor_invocation; // 19.9.1) Interface Declarations //non terminal ParseNode interface_declaration; //non terminal ParseNode extends_interfaces_opt, extends_interfaces; //non terminal ParseNode interface_body; //non terminal ParseNode interface_member_declarations_opt, interface_member_declarations; //non terminal ParseNode interface_member_declaration, constant_declaration; //non terminal ParseNode abstract_method_declaration; // 19.10) Arrays //non terminal ParseNode array_initializer; //non terminal ParseNode variable_initializers; // 19.11) Blocks and Statements non terminal ParseNode block; non terminal ParseNode block_statements_opt, block_statements, block_statement; non terminal ParseNode local_variable_declaration_statement, local_variable_declaration; non terminal ParseNode statement, statement_no_short_if; non terminal ParseNode statement_without_trailing_substatement; non terminal ParseNode empty_statement; //non terminal ParseNode labeled_statement, labeled_statement_no_short_if; non terminal ParseNode expression_statement, statement_expression; non terminal ParseNode if_then_statement; non terminal ParseNode if_then_else_statement, if_then_else_statement_no_short_if; //non terminal ParseNode switch_statement, switch_block; //non terminal ParseNode switch_block_statement_groups; //non terminal ParseNode switch_block_statement_group; //non terminal ParseNode switch_labels, switch_label; non terminal ParseNode while_statement, while_statement_no_short_if; non terminal ParseNode do_statement; non terminal ParseNode for_statement, for_statement_no_short_if; non terminal ParseNode for_init_opt, for_init; non terminal ParseNode for_update_opt, for_update; non terminal ParseNode statement_expression_list; //non terminal ParseNode identifier_opt; non terminal ParseNode break_statement, continue_statement; non terminal ParseNode return_statement; //non terminal ParseNode throw_statement; //non terminal ParseNode synchronized_statement, try_statement; //non terminal ParseNode catches_opt; //non terminal ParseNode catches, catch_clause; //non terminal ParseNode finally; //non terminal ParseNode assert_statement; // 19.12) Expressions non terminal ParseNode primary, primary_no_new_array; non terminal ParseNode class_instance_creation_expression; non terminal ParseNode argument_list_opt, argument_list; //non terminal ParseNode array_creation_init; non terminal ParseNode array_creation_uninit; non terminal ParseNode dim_exprs, dim_expr; non terminal Integer dims_opt, dims; non terminal ParseNode field_access, method_invocation; non terminal ParseNode array_access; non terminal ParseNode postfix_expression; non terminal ParseNode postincrement_expression, postdecrement_expression; non terminal ParseNode unary_expression, unary_expression_not_plus_minus; non terminal ParseNode preincrement_expression, predecrement_expression; non terminal ParseNode cast_expression; non terminal ParseNode multiplicative_expression, additive_expression; non terminal ParseNode shift_expression, relational_expression, equality_expression; non terminal ParseNode and_expression, exclusive_or_expression, inclusive_or_expression; non terminal ParseNode conditional_and_expression, conditional_or_expression; non terminal ParseNode conditional_expression; non terminal ParseNode assignment_expression; non terminal ParseNode assignment; non terminal ParseNode assignment_operator; non terminal ParseNode expression_opt, expression; //non terminal ParseNode constant_expression; //failure aware computation keywords terminal FLAG; terminal TAG; terminal TASK; terminal TASKEXIT; non terminal ParseNode flag_declaration; non terminal ParseNode task_declaration; non terminal ParseNode task_parameter_list; non terminal ParseNode task_parameter; non terminal ParseNode flag_expression; non terminal ParseNode flag_andexpression; non terminal ParseNode flag_notexpression; non terminal ParseNode task_exitstatement; non terminal ParseNode flag_effects_opt; non terminal ParseNode flag_effects; non terminal ParseNode flag_effect; non terminal ParseNode flag_list; non terminal ParseNode flag_change; start with goal; // Task declarations task_declaration ::= TASK IDENTIFIER:id LPAREN task_parameter_list:tpl RPAREN flag_effects_opt:feo method_body:body {: ParseNode pn=new ParseNode("task_declaration"); pn.addChild("name").addChild(id); pn.addChild(tpl); pn.addChild(feo); pn.addChild("body").addChild(body); RESULT=pn; :}; task_parameter_list ::= task_parameter:fp {: ParseNode pn=new ParseNode("task_parameter_list"); pn.addChild(fp); RESULT=pn; :} | task_parameter_list:fpl COMMA task_parameter:fp {: fpl.addChild(fp); RESULT=fpl; :} ; task_parameter ::= type:type variable_declarator_id:name LBRACE flag_expression:exp RBRACE {: ParseNode pn=new ParseNode("task_parameter"); pn.addChild(type); pn.addChild(name); pn.addChild("flag").addChild(exp); RESULT=pn; :} ; flag_expression ::= flag_andexpression:exp {: RESULT=exp; :} | flag_expression:exp1 OROR flag_andexpression:exp2 {: ParseNode pn=new ParseNode("or"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; flag_andexpression ::= flag_notexpression:exp {: RESULT=exp; :} | flag_notexpression:exp1 ANDAND flag_andexpression:exp2 {: ParseNode pn=new ParseNode("and"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; flag_notexpression ::= NOT flag_notexpression:exp {: ParseNode pn=new ParseNode("not"); pn.addChild(exp); RESULT=pn; :} | LPAREN flag_expression:exp RPAREN {: RESULT=exp; :} | IDENTIFIER:id {: ParseNode pn=new ParseNode("name"); pn.addChild(id); RESULT=pn; :} ; task_exitstatement ::= TASKEXIT flag_effects_opt SEMICOLON{: RESULT=new ParseNode("taskexit"); :}; flag_effects_opt ::= LPAREN flag_effects:fe RPAREN {:RESULT=fe;:} | {: RESULT = null; :} ; flag_effects ::= flag_effect:fe {: ParseNode pn=new ParseNode("flag_effects_list"); pn.addChild(fe); RESULT=pn; :} | flag_effects:fes COMMA flag_effect:fe {: fes.addChild(fe); RESULT=fes; :}; flag_effect ::= IDENTIFIER:id LBRACE flag_list:fl RBRACE {: ParseNode pn=new ParseNode("flag_effect"); pn.addChild("name").addChild(id); pn.addChild(fl); RESULT=pn; :}; flag_list ::= flag_change:fc {: ParseNode pn=new ParseNode("flag_list"); pn.addChild(fc); RESULT=pn; :} | flag_list:fl COMMA flag_change:fc {: fl.addChild(fc); RESULT=fl; :}; flag_change ::= IDENTIFIER:id {: RESULT=new ParseNode("name").addChild(id).getRoot(); :} | NOT IDENTIFIER:id {: RESULT=new ParseNode("not").addChild("name").addChild(id).getRoot(); :}; // 19.2) The Syntactic Grammar goal ::= compilation_unit:cu {: RESULT = cu; :} ; // 19.3) Lexical Structure. literal ::= INTEGER_LITERAL:integer_lit {: ParseNode pn=new ParseNode("literal"); pn.addChild("integer").setLiteral(integer_lit); RESULT=pn; :} | FLOATING_POINT_LITERAL:float_lit {: ParseNode pn=new ParseNode("literal"); pn.addChild("float").setLiteral(float_lit); RESULT=pn; :} | BOOLEAN_LITERAL:boolean_lit {: ParseNode pn=new ParseNode("literal"); pn.addChild("boolean").setLiteral(boolean_lit); RESULT=pn; :} | CHARACTER_LITERAL:char_lit {: ParseNode pn=new ParseNode("literal"); pn.addChild("char").setLiteral(char_lit); RESULT=pn; :} | STRING_LITERAL:string_lit {: ParseNode pn=new ParseNode("literal"); pn.addChild("string").setLiteral(string_lit); RESULT=pn; :} | NULL_LITERAL {: RESULT=(new ParseNode("literal")).addChild("null").getRoot(); :} ; // 19.4) Types, Values, and Variables type ::= primitive_type:type {: RESULT=type; :} | reference_type:type {: RESULT=type; :} ; primitive_type ::= numeric_type:type {: RESULT=type; :} | BOOLEAN {: RESULT=(new ParseNode("type")).addChild("boolean").getRoot(); :} ; numeric_type::= integral_type:type {: RESULT=type; :} | floating_point_type:type {: RESULT=type; :} ; integral_type ::= BYTE {: RESULT=(new ParseNode("type")).addChild("byte").getRoot(); :} | SHORT {: RESULT=(new ParseNode("type")).addChild("short").getRoot(); :} | INT {: RESULT=(new ParseNode("type")).addChild("int").getRoot(); :} | LONG {: RESULT=(new ParseNode("type")).addChild("long").getRoot(); :} | CHAR {: RESULT=(new ParseNode("type")).addChild("char").getRoot(); :} ; floating_point_type ::= FLOAT {: RESULT=(new ParseNode("type")).addChild("float").getRoot(); :} | DOUBLE {: RESULT=(new ParseNode("type")).addChild("double").getRoot(); :} ; reference_type ::= class_or_interface_type:type {: RESULT=type; :} | array_type:type {: RESULT=type; :} ; class_or_interface_type ::= name:name {: RESULT=(new ParseNode("type")).addChild("class").addChild(name).getRoot(); :}; class_type ::= class_or_interface_type:type {: RESULT=type; :}; //interface_type ::= class_or_interface_type; array_type ::= primitive_type:prim dims:dims {: ParseNode pn=(new ParseNode("type")).addChild("array"); pn.addChild("basetype").addChild(prim); pn.addChild("dims").setLiteral(dims); RESULT=pn; :} | name:name dims:dims {: ParseNode pn=(new ParseNode("type")).addChild("array"); pn.addChild("basetype").addChild("type").addChild("class").addChild(name); pn.addChild("dims").setLiteral(dims); RESULT=pn; :} ; // 19.5) Names name ::= simple_name:name {: RESULT=name; :} | qualified_name:name {: RESULT=name; :} ; simple_name ::= IDENTIFIER:id {: RESULT=(new ParseNode("name")).addChild("identifier").addChild(id).getRoot(); :} ; qualified_name ::= name:name DOT IDENTIFIER:id {: ParseNode pn=new ParseNode("name"); pn.addChild("base").addChild(name); pn.addChild("identifier").addChild(id); RESULT=pn; :} ; // 19.6) Packages compilation_unit ::= // package_declaration_opt // import_declarations_opt type_declarations_opt:tdo {: ParseNode pn=new ParseNode("compilation_unit"); pn.addChild(tdo); RESULT=pn; :} ; //package_declaration_opt ::= package_declaration | ; //import_declarations_opt ::= import_declarations | ; type_declarations_opt ::= type_declarations:tds {: RESULT=tds; :} | {: RESULT=new ParseNode("empty"); :} ; //import_declarations ::= // import_declaration // | import_declarations import_declaration // ; type_declarations ::= type_declaration:td {: ParseNode pn=new ParseNode("type_declaration_list"); pn.addChild(td); RESULT=pn; :} | type_declarations:tds type_declaration:td {: tds.addChild(td); RESULT=tds; :} ; //package_declaration ::= // PACKAGE name SEMICOLON // ; //import_declaration ::= // single_type_import_declaration // | type_import_on_demand_declaration // ; //single_type_import_declaration ::= // IMPORT name SEMICOLON // ; //type_import_on_demand_declaration ::= // IMPORT name DOT MULT SEMICOLON // ; type_declaration ::= class_declaration:cd {: RESULT=cd; :} | task_declaration:td {: RESULT=td; :} // | interface_declaration | SEMICOLON {: RESULT=new ParseNode("empty"); :} ; // 19.7) Productions used only in the LALR(1) grammar modifiers_opt::= {: RESULT=new ParseNode("empty"); :} | modifiers:mo {: RESULT=mo; :} ; modifiers ::= modifier:mo {: ParseNode pn=new ParseNode("modifier_list"); pn.addChild(mo); RESULT=pn; :} | modifiers:mos modifier:mo {: mos.addChild(mo); RESULT=mos; :} ; modifier ::= PUBLIC {: RESULT=new ParseNode("public"); :}| PROTECTED {: RESULT=new ParseNode("protected"); :}| PRIVATE {: RESULT=new ParseNode("private"); :}| STATIC {: RESULT=new ParseNode("static"); :} | // ABSTRACT | FINAL {: RESULT=new ParseNode("final"); :}| NATIVE {: RESULT=new ParseNode("native"); :} // SYNCHRONIZED | // TRANSIENT | // VOLATILE | // STRICTFP // note that semantic analysis must check that the // context of the modifier allows strictfp. ; // 19.8) Classes // 19.8.1) Class Declaration: class_declaration ::= modifiers_opt:mo CLASS IDENTIFIER:id super_opt:so //interfaces_opt class_body:body {: ParseNode pn=new ParseNode("class_declaration"); pn.addChild("modifiers").addChild(mo); pn.addChild("name").addChild(id); pn.addChild("super").addChild(so); pn.addChild("classbody").addChild(body); RESULT=pn; :} ; super ::= EXTENDS class_type:classtype {: RESULT=classtype; :} ; super_opt ::= {: RESULT=new ParseNode("empty"); :} | super:su {: RESULT=su; :} ; //interfaces ::= IMPLEMENTS interface_type_list // ; //interfaces_opt::= // | interfaces // ; //interface_type_list ::= // interface_type // | interface_type_list COMMA interface_type // ; class_body ::= LBRACE class_body_declarations_opt:cbdo RBRACE {: RESULT=cbdo; :} ; class_body_declarations_opt ::= {: RESULT=new ParseNode("empty"); :} | class_body_declarations:cbd {: RESULT=cbd; :}; class_body_declarations ::= class_body_declaration:cbd {: ParseNode pn=new ParseNode("class_body_declaration_list"); pn.addChild(cbd); RESULT=pn; :} | class_body_declarations:cbds class_body_declaration:cbd {: cbds.addChild(cbd); RESULT=cbds; :} ; class_body_declaration ::= class_member_declaration:member {: RESULT=(new ParseNode("member")).addChild(member).getRoot(); :} // | static_initializer | constructor_declaration:constructor {: RESULT=(new ParseNode("constructor")).addChild(constructor).getRoot(); :} | block:block {: RESULT=(new ParseNode("block")).addChild(block).getRoot(); :} ; class_member_declaration ::= //failure aware computation flag_declaration:flag {: RESULT=(new ParseNode("flag")).addChild(flag).getRoot(); :} | field_declaration:field {: RESULT=(new ParseNode("field")).addChild(field).getRoot(); :} | method_declaration:method {: RESULT=(new ParseNode("method")).addChild(method).getRoot(); :} /* repeat the prod for 'class_declaration' here: */ // | modifiers_opt CLASS IDENTIFIER super_opt class_body // | interface_declaration | SEMICOLON {: RESULT=new ParseNode("empty"); :} ; //Failure aware computation flag_declaration ::= FLAG IDENTIFIER:id SEMICOLON {: ParseNode pn=new ParseNode("flag_declaration"); pn.addChild("name").addChild(id); RESULT=pn; :} ; // 19.8.2) Field Declarations field_declaration ::= modifiers_opt:mo type:type variable_declarators:var SEMICOLON {: ParseNode pn=new ParseNode("field_declaration"); pn.addChild("modifier").addChild(mo); pn.addChild("type").addChild(type); pn.addChild("variables").addChild(var); RESULT=pn; :} ; variable_declarators ::= variable_declarator:vd {: ParseNode pn=new ParseNode("variable_declarators_list"); pn.addChild(vd); RESULT=pn; :} | variable_declarators:vds COMMA variable_declarator:vd {: vds.addChild(vd); RESULT=vds; :} ; variable_declarator ::= variable_declarator_id:id {: ParseNode pn=new ParseNode("variable_declarator"); pn.addChild(id); RESULT=pn; :} | variable_declarator_id:id EQ variable_initializer:init {: ParseNode pn=new ParseNode("variable_declarator"); pn.addChild(id); pn.addChild("initializer").addChild(init); RESULT=pn; :} ; variable_declarator_id ::= IDENTIFIER:id {: RESULT=(new ParseNode("single")).addChild(id).getRoot();:} | variable_declarator_id:id LBRACK RBRACK {: RESULT=(new ParseNode("array")).addChild(id).getRoot();:} ; variable_initializer ::= expression:exp {: RESULT=exp; :} // | array_initializer ; // 19.8.3) Method Declarations method_declaration ::= method_header:header method_body:body {: ParseNode pn=new ParseNode("method_declaration"); pn.addChild(header); pn.addChild("body").addChild(body); RESULT=pn; :} ; method_header ::= modifiers_opt:mo type:type method_declarator:decl //throws_opt {: ParseNode pn=new ParseNode("method_header"); pn.addChild("modifiers").addChild(mo); pn.addChild("returntype").addChild(type); pn.addChild(decl); RESULT=pn; :} | modifiers_opt:mo VOID method_declarator:decl //throws_opt {: ParseNode pn=new ParseNode("method_header"); pn.addChild("modifiers").addChild(mo); pn.addChild(decl); RESULT=pn; :} ; method_declarator ::= IDENTIFIER:id LPAREN formal_parameter_list_opt:params RPAREN {: ParseNode pn=new ParseNode("method_declarator"); pn.addChild("name").addChild(id); pn.addChild("parameters").addChild(params); RESULT=pn; :} // | method_declarator LBRACK RBRACK // deprecated // be careful; the above production also allows 'void foo() []' ; formal_parameter_list_opt ::= {: RESULT=new ParseNode("empty"); :} | formal_parameter_list:fpl {: RESULT=fpl; :} ; formal_parameter_list ::= formal_parameter:fp {: ParseNode pn=new ParseNode("formal_parameter_list"); pn.addChild(fp); RESULT=pn; :} | formal_parameter_list:fpl COMMA formal_parameter:fp {: fpl.addChild(fp); RESULT=fpl; :} ; formal_parameter ::= type:type variable_declarator_id:name {: ParseNode pn=new ParseNode("formal_parameter"); pn.addChild(type); pn.addChild(name); RESULT=pn; :} // | FINAL type variable_declarator_id ; //throws_opt ::= // | throws // ; //throws ::= THROWS class_type_list // ; //class_type_list ::= // class_type // | class_type_list COMMA class_type // ; method_body ::= block:block {: RESULT=block; :} | SEMICOLON {: RESULT=new ParseNode("empty"); :} ; // 19.8.4) Static Initializers //static_initializer ::= // STATIC block // ; // 19.8.5) Constructor Declarations constructor_declaration ::= modifiers_opt:mo constructor_declarator:cd //throws_opt constructor_body:body {: ParseNode pn=new ParseNode("constructor_declaration"); pn.addChild("modifiers").addChild(mo); pn.addChild(cd); pn.addChild("body").addChild(body); RESULT=pn; :} ; constructor_declarator ::= simple_name:name LPAREN formal_parameter_list_opt:fplo RPAREN {: ParseNode pn=new ParseNode("constructor_declarator"); pn.addChild(name); pn.addChild("parameters").addChild(fplo); RESULT=pn; :} ; constructor_body ::= // LBRACE explicit_constructor_invocation:eci block_statements:bs RBRACE | // LBRACE explicit_constructor_invocation RBRACE | LBRACE block_statements:block RBRACE {: ParseNode pn=new ParseNode("constructor_body"); pn.addChild(block); RESULT=pn; :} | LBRACE RBRACE {: RESULT=new ParseNode("empty"); :} ; //explicit_constructor_invocation ::= // THIS LPAREN argument_list_opt RPAREN SEMICOLON // | SUPER LPAREN argument_list_opt RPAREN SEMICOLON // | primary DOT THIS LPAREN argument_list_opt RPAREN SEMICOLON // | primary DOT SUPER LPAREN argument_list_opt RPAREN SEMICOLON // ; // 19.9) Interfaces // 19.9.1) Interface Declarations //interface_declaration ::= // modifiers_opt INTERFACE IDENTIFIER extends_interfaces_opt // interface_body // ; //extends_interfaces_opt ::= // | extends_interfaces // ; //extends_interfaces ::= // EXTENDS interface_type // | extends_interfaces COMMA interface_type // ; //interface_body ::= // LBRACE interface_member_declarations_opt RBRACE // ; //interface_member_declarations_opt ::= // | interface_member_declarations // ; //interface_member_declarations ::= // interface_member_declaration // | interface_member_declarations interface_member_declaration // ; //interface_member_declaration ::= // constant_declaration // | abstract_method_declaration // | class_declaration // | interface_declaration // | SEMICOLON // ; //constant_declaration ::= // field_declaration // // need to semantically check that modifiers of field declaration // // include only PUBLIC, STATIC, or FINAL. Other modifiers are // // disallowed. // ; //abstract_method_declaration ::= // method_header SEMICOLON // ; // 19.10) Arrays //array_initializer ::= // LBRACE variable_initializers COMMA RBRACE // | LBRACE variable_initializers RBRACE // | LBRACE COMMA RBRACE // | LBRACE RBRACE // ; //variable_initializers ::= // variable_initializer // | variable_initializers COMMA variable_initializer // ; // 19.11) Blocks and Statements block ::= LBRACE block_statements_opt:bso RBRACE {: RESULT=bso; :} ; block_statements_opt ::= {: RESULT=new ParseNode("empty"); :} | block_statements:bs {: RESULT=bs; :} ; block_statements ::= block_statement:bs {: ParseNode pn=new ParseNode("block_statement_list"); pn.addChild(bs); RESULT=pn; :} | block_statements:bss block_statement:bs {: bss.addChild(bs); RESULT=bss; :} ; block_statement ::= local_variable_declaration_statement:lvds {: RESULT=lvds; :} | statement:statement {: RESULT=statement; :} // | class_declaration // | interface_declaration ; local_variable_declaration_statement ::= local_variable_declaration:lvd SEMICOLON {: RESULT=lvd; :} ; local_variable_declaration ::= type:type variable_declarators:var {: ParseNode pn=new ParseNode("local_variable_declaration"); pn.addChild(type); pn.addChild(var); RESULT=pn; :} // | FINAL type variable_declarators ; statement ::= statement_without_trailing_substatement:st {: RESULT=st; :} // | labeled_statement:st {: RESULT=st; :} | if_then_statement:st {: RESULT=st; :} | if_then_else_statement:st {: RESULT=st; :} | while_statement:st {: RESULT=st; :} | for_statement:st {: RESULT=st; :} ; statement_no_short_if ::= statement_without_trailing_substatement:st {: RESULT=st; :} // | labeled_statement_no_short_if:st {: RESULT=st; :} | if_then_else_statement_no_short_if:st {: RESULT=st; :} | while_statement_no_short_if:st {: RESULT=st; :} | for_statement_no_short_if:st {: RESULT=st; :} ; statement_without_trailing_substatement ::= block:st {: RESULT=st; :} | empty_statement:st {: RESULT=st; :} | expression_statement:st {: RESULT=st; :} // | switch_statement | do_statement | break_statement:st {: RESULT=st; :} | continue_statement:st {: RESULT=st; :} | return_statement:st {: RESULT=st; :} | task_exitstatement:st {: RESULT=st; :} // | synchronized_statement // | throw_statement // | try_statement // | assert_statement ; empty_statement ::= SEMICOLON {: RESULT=new ParseNode("nop"); :} ; //labeled_statement ::= // IDENTIFIER COLON statement // ; //labeled_statement_no_short_if ::= // IDENTIFIER COLON statement_no_short_if // ; expression_statement ::= statement_expression:se SEMICOLON {: ParseNode pn=new ParseNode("expression"); pn.addChild(se); RESULT=pn; :} ; statement_expression ::= assignment:st {: RESULT=st; :} | preincrement_expression:st {: RESULT=st; :} | predecrement_expression:st {: RESULT=st; :} | postincrement_expression:st {: RESULT=st; :} | postdecrement_expression:st {: RESULT=st; :} | method_invocation:st {: RESULT=st; :} | class_instance_creation_expression:st {: RESULT=st; :} ; if_then_statement ::= IF LPAREN expression:exp RPAREN statement:st {: ParseNode pn=new ParseNode("ifstatement"); pn.addChild("condition").addChild(exp); pn.addChild("statement").addChild(st); RESULT=pn; :} ; if_then_else_statement ::= IF LPAREN expression:exp RPAREN statement_no_short_if:st ELSE statement:else_st {: ParseNode pn=new ParseNode("ifstatement"); pn.addChild("condition").addChild(exp); pn.addChild("statement").addChild(st); pn.addChild("else_statement").addChild(else_st); RESULT=pn; :} ; if_then_else_statement_no_short_if ::= IF LPAREN expression:exp RPAREN statement_no_short_if:st ELSE statement_no_short_if:else_st {: ParseNode pn=new ParseNode("ifstatement"); pn.addChild("condition").addChild(exp); pn.addChild("statement").addChild(st); pn.addChild("else_statement").addChild(else_st); RESULT=pn; :} ; //switch_statement ::= // SWITCH LPAREN expression RPAREN switch_block // ; //switch_block ::= // LBRACE switch_block_statement_groups switch_labels RBRACE // | LBRACE switch_block_statement_groups RBRACE // | LBRACE switch_labels RBRACE // | LBRACE RBRACE // ; //switch_block_statement_groups ::= // switch_block_statement_group // | switch_block_statement_groups switch_block_statement_group // ; //switch_block_statement_group ::= // switch_labels block_statements // ; //switch_labels ::= // switch_label // | switch_labels switch_label // ; //switch_label ::= // CASE constant_expression COLON // | DEFAULT COLON // ; while_statement ::= WHILE LPAREN expression:exp RPAREN statement:st {: ParseNode pn=new ParseNode("whilestatement"); pn.addChild("condition").addChild(exp); pn.addChild("statement").addChild(st); RESULT=pn; :} ; while_statement_no_short_if ::= WHILE LPAREN expression:exp RPAREN statement_no_short_if:st {: ParseNode pn=new ParseNode("whilestatement"); pn.addChild("condition").addChild(exp); pn.addChild("statement").addChild(st); RESULT=pn; :} ; do_statement ::= DO statement:st WHILE LPAREN expression:exp RPAREN SEMICOLON {: ParseNode pn=new ParseNode("dowhilestatement"); pn.addChild("condition").addChild(exp); pn.addChild("statement").addChild(st); RESULT=pn; :} ; for_statement ::= FOR LPAREN for_init_opt:init SEMICOLON expression_opt:exp SEMICOLON for_update_opt:update RPAREN statement:st {: ParseNode pn=new ParseNode("forstatement"); pn.addChild("initializer").addChild(init); pn.addChild("condition").addChild(exp); pn.addChild("update").addChild(update); pn.addChild("statement").addChild(st); RESULT=pn; :} ; for_statement_no_short_if ::= FOR LPAREN for_init_opt:init SEMICOLON expression_opt:exp SEMICOLON for_update_opt:update RPAREN statement_no_short_if:st {: ParseNode pn=new ParseNode("forstatement"); pn.addChild("initializer").addChild(init); pn.addChild("condition").addChild(exp); pn.addChild("update").addChild(update); pn.addChild("statement").addChild(st); RESULT=pn; :} ; for_init_opt ::= {: RESULT=new ParseNode("empty"); :} | for_init:init {: RESULT=init; :} ; for_init ::= statement_expression_list:list {: RESULT=list; :} | local_variable_declaration:decl {: RESULT=decl; :} ; for_update_opt ::= {: RESULT=new ParseNode("empty"); :} | for_update:update {: RESULT=update; :} ; for_update ::= statement_expression_list:list {: RESULT=list; :} ; statement_expression_list ::= statement_expression:expr {: RESULT=(new ParseNode("statement_expression_list")).addChild(expr).getRoot(); :} | statement_expression_list:list COMMA statement_expression:expr {: list.addChild(expr); RESULT=list; :} ; //identifier_opt ::= // | IDENTIFIER // ; break_statement ::= BREAK //identifier_opt SEMICOLON {: RESULT=new ParseNode("break"); :} ; continue_statement ::= CONTINUE //identifier_opt SEMICOLON {: RESULT=new ParseNode("continue"); :} ; return_statement ::= RETURN expression_opt:exp SEMICOLON {: RESULT=(new ParseNode("return")).addChild(exp).getRoot(); :} ; //throw_statement ::= // THROW expression SEMICOLON // ; //synchronized_statement ::= // SYNCHRONIZED LPAREN expression RPAREN block // ; //try_statement ::= // TRY block catches // | TRY block catches_opt finally // ; //catches_opt ::= // | catches // ; //catches ::= catch_clause // | catches catch_clause // ; //catch_clause ::= // CATCH LPAREN formal_parameter RPAREN block // ; //finally ::= FINALLY block // ; //assert_statement ::= // ASSERT expression SEMICOLON // | ASSERT expression COLON expression SEMICOLON // ; // 19.12) Expressions primary ::= primary_no_new_array:st {: RESULT=st; :} // | array_creation_init:st {: // RESULT=st; // :} | array_creation_uninit:st {: RESULT=st; :} ; primary_no_new_array ::= literal:lit {: RESULT=lit; :} | THIS {: RESULT=new ParseNode("this"); :} | LPAREN expression:exp RPAREN {: RESULT=exp; :} | class_instance_creation_expression:exp {: RESULT=exp; :} | field_access:exp {: RESULT=exp; :} | method_invocation:exp {: RESULT=exp; :} | array_access:exp {: RESULT=exp; :} // | primitive_type DOT CLASS // | VOID DOT CLASS // | array_type DOT CLASS // | name DOT CLASS // | name DOT THIS ; class_instance_creation_expression ::= NEW class_or_interface_type:type LPAREN argument_list_opt:args RPAREN {: ParseNode pn=new ParseNode("createobject"); pn.addChild(type); pn.addChild(args); RESULT=pn; :} // | NEW class_or_interface_type LPAREN argument_list_opt RPAREN class_body // | primary DOT NEW IDENTIFIER // LPAREN argument_list_opt RPAREN {: // // :} // | primary DOT NEW IDENTIFIER // LPAREN argument_list_opt RPAREN class_body // | name DOT NEW IDENTIFIER // LPAREN argument_list_opt RPAREN // | name DOT NEW IDENTIFIER // LPAREN argument_list_opt RPAREN class_body ; argument_list_opt ::= {: RESULT=new ParseNode("empty"); :} | argument_list:args {: RESULT=args; :} ; argument_list ::= expression:exp {: ParseNode pn=new ParseNode("argument_list"); pn.addChild(exp); RESULT=pn; :} | argument_list:list COMMA expression:exp {: list.addChild(exp); RESULT=list; :} ; array_creation_uninit ::= NEW primitive_type:type dim_exprs:dimexpr dims_opt:dims {: ParseNode pn=new ParseNode("createarray"); pn.addChild(type); pn.addChild(dimexpr); pn.addChild("dims_opt").setLiteral(dims); RESULT=pn; :} | NEW class_or_interface_type:type dim_exprs:dimexpr dims_opt:dims {: ParseNode pn=new ParseNode("createarray"); pn.addChild(type); pn.addChild(dimexpr); pn.addChild("dims_opt").setLiteral(dims); RESULT=pn; :} ; //array_creation_init ::= // NEW primitive_type dims array_initializer // | NEW class_or_interface_type dims array_initializer // ; dim_exprs ::= dim_expr:exp {: ParseNode pn=new ParseNode("dim_exprs"); pn.addChild(exp); RESULT=pn; :} | dim_exprs:base dim_expr:exp {: base.addChild(exp); RESULT=base; :} ; dim_expr ::= LBRACK expression:exp RBRACK {: RESULT=exp; :} ; dims_opt ::= {: RESULT=null; :} | dims:dims {: RESULT = dims; :} ; dims ::= LBRACK RBRACK {: RESULT=new Integer(0); :} | dims:dims LBRACK RBRACK {: RESULT=new Integer(dims.intValue()+1); :} ; field_access ::= primary:base DOT IDENTIFIER:id {: ParseNode pn=new ParseNode("fieldaccess"); pn.addChild("base").addChild(base); pn.addChild("field").addChild(id); RESULT=pn; :} // | SUPER DOT IDENTIFIER // | name DOT SUPER DOT IDENTIFIER ; method_invocation ::= name:name LPAREN argument_list_opt:args RPAREN {: ParseNode pn=new ParseNode("methodinvoke1"); pn.addChild(name); pn.addChild(args); RESULT=pn; :} | primary:base DOT IDENTIFIER:name LPAREN argument_list_opt:args RPAREN {: ParseNode pn=new ParseNode("methodinvoke2"); pn.addChild("base").addChild(base); pn.addChild("id").addChild(name); pn.addChild(args); RESULT=pn; :} // | SUPER DOT IDENTIFIER LPAREN argument_list_opt RPAREN // | name DOT SUPER DOT IDENTIFIER LPAREN argument_list_opt RPAREN ; array_access ::= name:name LBRACK expression:exp RBRACK {: ParseNode pn=new ParseNode("arrayaccess"); pn.addChild("base").addChild(name); pn.addChild("index").addChild(exp); RESULT=pn; :} | primary_no_new_array:base LBRACK expression:exp RBRACK {: ParseNode pn=new ParseNode("arrayaccess"); pn.addChild("base").addChild(base); pn.addChild("index").addChild(exp); RESULT=pn; :} // | array_creation_init:init LBRACK expression:exp RBRACK {: // ParseNode pn=new ParseNode("arrayaccess"); // pn.addChild("init").addChild(init); // pn.addChild("index").addChild(exp); // RESULT=pn; // :} ; postfix_expression ::= primary:exp {: RESULT=exp; :} | name:exp {: RESULT=exp; :} | postincrement_expression:exp {: RESULT=exp; :} | postdecrement_expression:exp {: RESULT=exp; :} ; postincrement_expression ::= postfix_expression:exp PLUSPLUS {: RESULT=(new ParseNode("postinc")).addChild(exp).getRoot(); :} ; postdecrement_expression ::= postfix_expression:exp MINUSMINUS {: RESULT=(new ParseNode("postdec")).addChild(exp).getRoot(); :} ; unary_expression ::= preincrement_expression:exp {: RESULT=exp; :} | predecrement_expression:exp {: RESULT=exp; :} | PLUS unary_expression:exp {: RESULT=(new ParseNode("unaryplus")).addChild(exp).getRoot(); :} | MINUS unary_expression:exp {: RESULT=(new ParseNode("unaryminus")).addChild(exp).getRoot(); :} | unary_expression_not_plus_minus:exp {: RESULT=exp; :} ; preincrement_expression ::= PLUSPLUS unary_expression:exp {: RESULT=(new ParseNode("preinc")).addChild(exp).getRoot(); :} ; predecrement_expression ::= MINUSMINUS unary_expression:exp {: RESULT=(new ParseNode("predec")).addChild(exp).getRoot(); :} ; unary_expression_not_plus_minus ::= postfix_expression:exp {: RESULT=exp; :} // | COMP unary_expression | NOT unary_expression:exp {: RESULT=(new ParseNode("not")).addChild(exp).getRoot(); :} | cast_expression:exp {: RESULT=exp; :} ; cast_expression ::= LPAREN primitive_type:type //dims_opt RPAREN unary_expression:exp {: ParseNode pn=new ParseNode("cast1"); pn.addChild("type").addChild(type); pn.addChild("exp").addChild(exp); RESULT=pn; :} | LPAREN expression:type RPAREN unary_expression_not_plus_minus:exp {: ParseNode pn=new ParseNode("cast2"); pn.addChild("type").addChild(type); pn.addChild("exp").addChild(exp); RESULT=pn; :} // | LPAREN name dims RPAREN unary_expression_not_plus_minus ; multiplicative_expression ::= unary_expression:exp {: RESULT=exp; :} | multiplicative_expression:exp1 MULT unary_expression:exp2 {: ParseNode pn=new ParseNode("mult"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} | multiplicative_expression:exp1 DIV unary_expression:exp2 {: ParseNode pn=new ParseNode("div"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} | multiplicative_expression:exp1 MOD unary_expression:exp2 {: ParseNode pn=new ParseNode("mod"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; additive_expression ::= multiplicative_expression:exp {: RESULT=exp; :} | additive_expression:exp1 PLUS multiplicative_expression:exp2 {: ParseNode pn=new ParseNode("add"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} | additive_expression:exp1 MINUS multiplicative_expression:exp2 {: ParseNode pn=new ParseNode("sub"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; shift_expression ::= additive_expression:exp {: RESULT=exp; :} | shift_expression:exp1 LSHIFT additive_expression:exp2 {: ParseNode pn=new ParseNode("leftshift"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} | shift_expression:exp1 RSHIFT additive_expression:exp2 {: ParseNode pn=new ParseNode("rightshift"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} // | shift_expression URSHIFT additive_expression ; relational_expression ::= shift_expression:exp {: RESULT=exp; :} | relational_expression:exp1 LT shift_expression:exp2 {: ParseNode pn=new ParseNode("comp_lt"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} | relational_expression:exp1 GT shift_expression:exp2 {: ParseNode pn=new ParseNode("comp_gt"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} | relational_expression:exp1 LTEQ shift_expression:exp2 {: ParseNode pn=new ParseNode("comp_lte"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} | relational_expression:exp1 GTEQ shift_expression:exp2 {: ParseNode pn=new ParseNode("comp_gte"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} // | relational_expression INSTANCEOF reference_type ; equality_expression ::= relational_expression:exp {: RESULT=exp; :} | equality_expression:exp1 EQEQ relational_expression:exp2 {: ParseNode pn=new ParseNode("equal"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} | equality_expression:exp1 NOTEQ relational_expression:exp2 {: ParseNode pn=new ParseNode("not_equal"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; and_expression ::= equality_expression:exp {: RESULT=exp; :} | and_expression:exp1 AND equality_expression:exp2 {: ParseNode pn=new ParseNode("bitwise_and"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; exclusive_or_expression ::= and_expression:expr {: RESULT=expr; :} | exclusive_or_expression:exp1 XOR and_expression:exp2 {: ParseNode pn=new ParseNode("bitwise_xor"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; inclusive_or_expression ::= exclusive_or_expression:exclor {: RESULT=exclor; :} | inclusive_or_expression:exp1 OR exclusive_or_expression:exp2 {: ParseNode pn=new ParseNode("bitwise_or"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; conditional_and_expression ::= inclusive_or_expression:inclor {: RESULT=inclor; :} | conditional_and_expression:exp1 ANDAND inclusive_or_expression:exp2 {: ParseNode pn=new ParseNode("logical_and"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; conditional_or_expression ::= conditional_and_expression:condand {: RESULT=condand; :} | conditional_or_expression:exp1 OROR conditional_and_expression:exp2 {: ParseNode pn=new ParseNode("logical_or"); pn.addChild(exp1); pn.addChild(exp2); RESULT=pn; :} ; conditional_expression ::= conditional_or_expression:condor {: RESULT=condor; :} // | conditional_or_expression QUESTION expression // COLON conditional_expression ; assignment_expression ::= conditional_expression:expr {: RESULT=expr; :} | assignment:assign {: RESULT=assign; :} ; // semantic check necessary here to ensure a valid left-hand side. // allowing a parenthesized variable here on the lhs was introduced in // JLS 2; thanks to Eric Blake for pointing this out. assignment ::= postfix_expression:lvalue assignment_operator:op assignment_expression:rvalue {: ParseNode pn=new ParseNode("assignment"); pn.addChild("op").addChild(op); ParseNode pnargs=pn.addChild("args"); pnargs.addChild(lvalue); pnargs.addChild(rvalue); RESULT=pn; :} ; assignment_operator ::= EQ {: RESULT=new ParseNode("eq"); :} | MULTEQ {: RESULT=new ParseNode("multeq"); :} | DIVEQ {: RESULT=new ParseNode("diveq"); :} | MODEQ {: RESULT=new ParseNode("modeq"); :} | PLUSEQ {: RESULT=new ParseNode("pluseq"); :} | MINUSEQ {: RESULT=new ParseNode("minuseq"); :} | LSHIFTEQ {: RESULT=new ParseNode("lshifteq"); :} | RSHIFTEQ {: RESULT=new ParseNode("rshifteq"); :} // | URSHIFTEQ {: RESULT=new ParseNode("urshifteq"); :} | ANDEQ {: RESULT=new ParseNode("andeq"); :} | XOREQ {: RESULT=new ParseNode("xoreq"); :} | OREQ {: RESULT=new ParseNode("oreq"); :} ; expression_opt ::= {: RESULT=new ParseNode("empty"); :} | expression:exp {: RESULT=exp; :} ; expression ::= assignment_expression:exp {: RESULT=exp; :} ; //constant_expression ::= // expression // ;