diff --git a/src/main/grammar/JastAddAspect.bnf b/src/main/grammar/JastAddAspect.bnf index 01b821327f07c06bee036c3e9539d835021ddfbb..8611058fbd123e342d9394f5fb778e53b668c75b 100644 --- a/src/main/grammar/JastAddAspect.bnf +++ b/src/main/grammar/JastAddAspect.bnf @@ -13,15 +13,161 @@ tokenTypeClass="org.jastadd.tooling.aspect.JastAddAspectTokenType" } -jastaddAspectFile ::= (attribute_equation|comment)* +jastaddAspectFile ::= (aspect_declaration|comment)* comment ::= (WHITESPACE | MULTILINECOMMENT | DOCCOMMENT | SINGLELINECOMMENT) -attribute_equation ::= EQ java_block +//attribute_equation ::= EQ java_block +// +//java_block ::= JAVABLOCK +//{ +// implements="org.jastadd.tooling.aspect.psi.JastAddAspectJavaBlockExtension" +// extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectJavaBlockImplExtension" +//} -java_block ::= JAVABLOCK -{ - implements="org.jastadd.tooling.aspect.psi.JastAddAspectJavaBlockExtension" - extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectJavaBlockImplExtension" -} +aspect_declaration ::= ASPECT aspect_body + +aspect_body ::= LBRACE aspect_body_declaration* RBRACE + +aspect_body_declaration ::= ( aspect_refine_inh_equation + | aspect_refine_syn_equation + | aspect_refine_method_declaration + | aspect_refine_constructor_declaration + | aspect_class_declaration + | aspect_interface_declaration + | aspect_enum_declaration + | aspect_syn_attribute_declaration + | aspect_inh_attribute_declaration + | aspect_rewrite + | aspect_inh_equation + | aspect_syn_equation + | aspect_add_interface + | aspect_extend_interface + | collection_attribute + | collection_contribution + | aspect_method_declaration + | aspect_constructor_declaration + | aspect_field_declaration + | aspect_cache_declaration ) + +aspect_body_declarations_eof ::= aspect_body_declaration* EOF + +aspect_class_declaration ::= modifiers CLASS id type_parameters (EXTENDS class_or_interface_type)? (IMPLEMENTS type_name_list)? aspect_class_body + +aspect_class_body ::= JAVA_CLASS_BODY_DECLARATION // including curly braces + +aspect_interface_declaration ::= modifiers INTERFACE id type_parameters? (EXTENDS type_name_list)? LBRACE aspect_interface_member_declaration* RBRACE + +aspect_interface_member_declaration ::= ( aspect_nested_class_declaration + | aspect_nested_interface_declaration + | aspect_interface_syn_attribute_declaration + | aspect_interface_inh_attribute_declaration + | aspect_interface_method_declaration + | aspect_interface_field_declaration ) + +aspect_interface_syn_attribute_declaration ::= annotation* SYN LAZY? FINAL? aspect_type attribute_name LPAREN (type ID (COMMA type ID)* )? RPAREN (CIRCULAR LBRACKET JAVA_EXPRESSION RBRACKET)? SCOL + +aspect_interface_inh_attribute_declaration ::= annotation* INH LAZY? FINAL? aspect_type attribute_name LPAREN (type ID (COMMA type ID)* )? RPAREN (CIRCULAR LBRACKET JAVA_EXPRESSION RBRACKET)? SCOL + +aspect_interface_method_declaration ::= (PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL | NATIVE | SYNCHRONIZED )* aspect_result_type method_declarator (THROWS name_list ) SCOL + +aspect_interface_field_declaration ::= modifiers aspect_type variable_declarator (COMMA variable_declarator)* SCOL + +aspect_nested_interface_declaration ::= modifiers INTERFACE ID type_parameters? EXTENDS? LBRACE JAVA_INTERFACE_MEMBER_DECLARATIONS RBRACE + +aspect_nested_class_declaration ::= modifiers CLASS ID type_parameters? (EXTENDS class_or_interface_type)? (IMPLEMENTS type_name_list)? JAVA_CLASS_BODY_DECLARATION + +aspect_method_declaration ::= modifiers type_parameters? aspect_result_type ID DOT method_declarator (THROWS name_list)? (block | SCOL) + +aspect_refine_method_declaration ::= REFINE [ID] modifers type_parameters? aspect_result_type ID DOT method_declarator (THROWS name_list)? (block | SCOL) + +aspect_constructor_declaration ::= modifiers ID DOT ID formal_parameters (THROWS name_list)? LBRACE JAVA_EXPLICIT_CONSTRUCTUR_BLOCK RBRACE + +aspect_refine_constructor_declaration ::= REFINE ID (PUBLIC | PROTECTED | PRIVATE) ID DOT ID formal_parameters (THROWS name_list)? LBRACE block_statement* RBRACE + +aspect_field_declaration ::= modifiers aspect_type ID DOT variable_declarator (COMMA variable_declarator)* SCOL + +aspect_syn_attribute_declaration ::= annotation* SYN NTA? LAZY? FINAL? aspect_type ID DOT attribute_name LPAREN type ID (COMMA type ID)* RPAREN (CIRCULAR LBRACKET JAVA_EXPRESSION RBRACKET)? ( EQ JAVA_EXPRESSION SCOL | block | SCOL ) + +aspect_inh_attribute_declaration ::= annotation* INH NTA? LAZY? FINAL? aspect_type ID DOT attribute_name LPAREN (type ID (COMMA type ID)* )? (CIRCULAR LBRACKET JAVA_EXPRESSION RBRACKET)? SCOL + +aspect_rewrite ::= REWRITE ID (ID DOT ID LPAREN RPAREN)? LBRACE ((WHEN LPAREN JAVA_EXPRESSION RPAREN)? TO aspect_type ( JAVA_EXPRESSION SCOL | block ))+ RBRACE + +aspect_syn_equation ::= annotation* ID DOT attribute_name LPAREN (type ID (COMMA type ID)*)? RPAREN ( EQ JAVA_EXPRESSION SCOL | block ) + +aspect_refine_syn_equation ::= REFINE ID EQ ID attribute_name LPAREN (type ID (COMMA type ID)*)? RPAREN (EQ JAVA_EXPRESSION SCOL | block) + +aspect_inh_equation ::= annotation* EQ ID DOT ID LPAREN (INT ID)? DOT attribute_name LPAREN (type ID (COMMA type ID)*)? RPAREN (EQ JAVA_EXPRESSION | block) + +aspect_refine_inh_equation ::= REFINE ID EQ ID DOT ID LPAREN (INT ID)? RPAREN DOT attribute_name LPAREN (type ID (COMMA type ID)*)? RPAREN (EQ JAVA_EXPRESSION | block) + +collection_attribute ::= annotation* COLL aspect_type ID DOT attribute_name LPAREN RPAREN CIRCULAR? (LBRACKET JAVA_EXPRESSION RBRACKET)? (WITH ID)? (ROOT ID)? SCOL + +collection_contribution ::= annotation* CONTRIBUTES ( NTA JAVA_EXPRESSION TO ID DOT attribute_name LPAREN RPAREN | EACH? JAVA_EXPRESSION (WHEN JAVA_EXPRESSION)? TO ID DOT attribute_name LPAREN RPAREN (FOR EACH? JAVA_EXPRESSION)? | block TO ID DOT attribute_name LPAREN RPAREN ) SCOL + +aspect_add_interface ::= IO IMPLEMENTS type_name_list SCOL + +aspect_extend_interface ::= ID EXTENDS type_name_list SCOL + +// added + +type_name_list ::= class_or_interface_type (COMMA class_or_interface_type)* + +attribute_name ::= ID + +// TODO | UnmodifiedClassDeclaration("") +block_statement ::= (FINAL? type java_identifier local_variable_declaration SCOL) | statement + +aspect_cache_declaration ::= (CACHE | UNCACHE) ID DOT attribute_name LPAREN (type ID? (type ID?)* )? RPAREN SCOL + +modifiers ::= (PUBLIC | STATIC | PROTECTED | PRIVATE | FINAL | ABSTRACT | SYNCHRONIZED | NATIVE | TRANSIENT | VOLATILE | STRICTFP)* + +// Attribute type names can not start with JastAdd reserved words such as 'syn', 'eq', etc. +aspect_type ::= aspect_reference_type | ( primitive_type (LBRACKET RBRACKET)? ) + +formal_parameters ::= LPAREN ( formal_parameter ( COMMA formal_parameter )* )? RPAREN + +name_list ::= name (COMMA name)* + +formal_parameter ::= FINAL? type DOTS? variable_declarator_id + +variable_declarator_id ::= java_identifier ( LBRACKET RBRACKET )* + +java_identifier ::= ID | INH | SYN | LAZY | REWRITE | TO | WHEN | ASPECT | EQUATION | CIRCULAR | REFINE | COLL | CONTRIBUTES | EACH | NTA | CACHE | UNCACHE + +aspect_enum_declaration ::= modifiers ENUM ID (IMPLEMENTS type_name_list)? JAVA_ENUM_BODY + +variable_declarator ::= variable_declarator_id ( EQ variable_initializer )? + +variable_initializer ::= array_initializer | expression + +array_initializer ::= LBRACE ( variable_initializer (COMMA variable_initializer)* )? RBRACE + +primitive_type ::= boolean | char | byte | short | int | long | float | double + +class_or_interface_type ::= java_identifier type_arguments? (DOT java_identifier type_arguments? )* + +type_arguments ::= LESSTHAN (type_argument (COMMA type_argument)* )? MORETHAN + +type_argument ::= reference_type | (QUESTIONMARK wildcard_bounds?) + +wildcard_bounds ::= (EXTENDS reference_type) | SUPER reference_type + +reference_type ::= ( primitive_type (LBRACKET RBRACKET)+ ) | ( class_or_interface_type (LBRACKET RBRACKET)* ) + +aspect_reference_type ::= aspect_class_or_interface_type (LBRACKET RBRACKET)* + +aspect_class_or_interface_type ::= ID type_arguments? (DOT java_identifier type_arguments? )* + +local_variable_declaration ::= FINAL? type variable_declarator (COMMA variable_declarator)* + +type_parameters ::= LESSTHAN type_parameter (COMMA type_parameter)* GREATERTHAN + +type_parameter ::= java_identifier type_bound? + +type_bound ::= EXTENDS class_or_interface_type (AMPERSAND class_or_interface_type)* + +aspect_result_type ::= VOID | aspect_type + +method_declarator ::= java_identifier formal_parameters (LBRACKET RBRACKET)* diff --git a/src/main/grammar/JastAddAspect.flex b/src/main/grammar/JastAddAspect.flex index fafc09948777b0855329ca2b4776b0a1a393317f..9f12d97ca8125b60ff2c5fd0b24f54af459c064a 100644 --- a/src/main/grammar/JastAddAspect.flex +++ b/src/main/grammar/JastAddAspect.flex @@ -37,8 +37,82 @@ NotParenthesis = [^{}]* "{" { yybegin(JAVA); counter = 1; } } -<JAVA> { +<JAVA_PARENTHESIS_BLOCK> { {NotParenthesis} {} "{" { counter++; yybegin(JAVA); } "}" { counter--; if (counter==0) { yybegin(YYINITIAL); return JastAddAspectTypes.JAVABLOCK; } } } + +<JAVATOKENS> { + "abstract" { return JastAddAspectTypes.ABSTRACT; } + "assert" { return JastAddAspectTypes.ASSERT; } + "boolean" { return JastAddAspectTypes.BOOLEAN; } + "break" { return JastAddAspectTypes.BREAK; } + "byte" { return JastAddAspectTypes.BYTE; } + "case" { return JastAddAspectTypes.CASE; } + "catch" { return JastAddAspectTypes.CATCH; } + "char" { return JastAddAspectTypes.CHAR; } + "class" { return JastAddAspectTypes.CLASS; } + "const" { return JastAddAspectTypes.CONST; } + "continue" { return JastAddAspectTypes.CONTINUE; } + "default" { return JastAddAspectTypes._DEFAULT; } + "do" { return JastAddAspectTypes.DO; } + "double" { return JastAddAspectTypes.DOUBLE; } + "else" { return JastAddAspectTypes.ELSE; } + "enum" { return JastAddAspectTypes.ENUM; } + "extends" { return JastAddAspectTypes.EXTENDS; } + "false" { return JastAddAspectTypes.FALSE; } + "final" { return JastAddAspectTypes.FINAL; } + "finally" { return JastAddAspectTypes.FINALLY; } + "float" { return JastAddAspectTypes.FLOAT; } + "for" { return JastAddAspectTypes.FOR; } + "goto" { return JastAddAspectTypes.GOTO; } + "if" { return JastAddAspectTypes.IF; } + "implements" { return JastAddAspectTypes.IMPLEMENTS; } + "import" { return JastAddAspectTypes.IMPORT; } + "instanceof" { return JastAddAspectTypes.INSTANCEOF; } + "int" { return JastAddAspectTypes.INT; } + "interface" { return JastAddAspectTypes.INTERFACE; } + "long" { return JastAddAspectTypes.LONG; } + "native" { return JastAddAspectTypes.NATIVE; } + "new" { return JastAddAspectTypes.NEW; } + "null" { return JastAddAspectTypes.NULL; } + "package" { return JastAddAspectTypes.PACKAGE; } + "private" { return JastAddAspectTypes.PRIVATE; } + "protected" { return JastAddAspectTypes.PROTECTED; } + "public" { return JastAddAspectTypes.PUBLIC; } + "return" { return JastAddAspectTypes.RETURN; } + "short" { return JastAddAspectTypes.SHORT; } + "static" { return JastAddAspectTypes.STATIC; } + "strictfp" { return JastAddAspectTypes.STRICTFP; } + "super" { return JastAddAspectTypes.SUPER; } + "switch" { return JastAddAspectTypes.SWITCH; } + "synchronized" { return JastAddAspectTypes.SYNCHRONIZED; } + "this" { return JastAddAspectTypes.THIS; } + "throw" { return JastAddAspectTypes.THROW; } + "throws" { return JastAddAspectTypes.THROWS; } + "transient" { return JastAddAspectTypes.TRANSIENT; } + "true" { return JastAddAspectTypes.TRUE; } + "try" { return JastAddAspectTypes.TRY; } + "void" { return JastAddAspectTypes.VOID; } + "volatile" { return JastAddAspectTypes.VOLATILE; } + "while" { return JastAddAspectTypes.WHILE; } + + // JastAdd + + "inh" { return JastAddAspectTypes.INH; } + "syn" { return JastAddAspectTypes.SYN; } + "lazy" { return JastAddAspectTypes.LAZY; } + "rewrite" { return JastAddAspectTypes.REWRITE; } + "to" { return JastAddAspectTypes.TO; } + "when" { return JastAddAspectTypes.WHEN; } + "aspect" { return JastAddAspectTypes.ASPECT; } + "eq" { return JastAddAspectTypes.EQUATION; } + "circular" { return JastAddAspectTypes.CIRCULAR; } + "refine" { return JastAddAspectTypes.REFINE; } + "contributes" { return JastAddAspectTypes.CONTRIBUTES; } + "each" { return JastAddAspectTypes.EACH; } + "nta" { return JastAddAspectTypes.NTA; } + "cache" { return JastAddAspectTypes.CACHE; } + "uncache" { return JastAddAspectTypes.UNCACHE; } +} diff --git a/src/main/grammar/Jrag.jjt b/src/main/grammar/Jrag.jjt new file mode 100644 index 0000000000000000000000000000000000000000..0fad94504848b91080e3d8e0fe3c94ce0468bb79 --- /dev/null +++ b/src/main/grammar/Jrag.jjt @@ -0,0 +1,2733 @@ +/* Copyright (c) 2006, Sun Microsystems, Inc. + * 2006-2018, The JastAdd Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Sun Microsystems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file is based on the Java1.1.jjt file from the VTransformer example + * from JavaCC by Sun Microsystems, Inc. Modifications have been made by the + * JastAdd team to add support for JastAdd features. The original author of + * this file, according to older releases of JavaCC, was Sriram Sankar. A date + * tag in the older releases shows the file was created on 3/5/97. + */ +options { + JAVA_UNICODE_ESCAPE = true; + + STATIC=false; + MULTI=true; + VISITOR=true; + NODE_USES_PARSER=true; + NODE_SCOPE_HOOK= true; + NODE_PACKAGE="org.jastadd.jrag.AST"; +} + +PARSER_BEGIN(JragParser) +package org.jastadd.jrag.AST; +import java.util.*; +import org.jastadd.jrag.*; + +import org.jastadd.ast.AST.Grammar; + +public class JragParser { + + /* Added attributes to the parser: */ + public String className = ""; // Name of class currently parsed. + public String enclosingAspect = ""; // The name of the aspect currently being parsed. + public String fileName; // Name of parsed file. + + private java.util.List<String> contextStack = new java.util.ArrayList<String>(); + + public boolean inTopLevelOrAspect() { + int size = contextStack.size(); + return size == 0 || (size == 1 && contextStack.get(0).equals("aspect")); + } + + public boolean shouldAddClassBodyDecl() { + int size = contextStack.size(); + return size == 1 && + (contextStack.get(0).equals("aspect") || + contextStack.get(0).equals("class") || + contextStack.get(0).equals("interface")); + } + + public void pushTopLevelOrAspect(String context) { + contextStack.add(context); + } + + public void popTopLevelOrAspect() { + contextStack.remove(contextStack.size()-1); + } + + public Grammar root; + public java.io.InputStream inputStream; + + /** Set name of parsed file. */ + public void setFileName(String name) { + fileName = name; + className = ""; + contextStack = new java.util.ArrayList<String>(); + } + + /* ------ Added methods for NODE_SCOPE_HOOKS ---------*/ + public void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + public void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + /* ------End of methods for NODE_SCOPE_HOOK------------*/ + + /** Returns string consisting of all chars before a dot. */ + public String beforeDot(String s) { + int i = s.indexOf('.'); + if (i < 0) { + return s; + } else { + return s.substring(0, i); + } + } + + /** + * Returns string consisting of all chars between "get" and before a '('. + * Returns null if "get" is not a prefix; s if no "(" found. + */ + public String stripGet(String s) { + if (!s.startsWith("get")) { + return null; + } + s = s.substring(3, s.length()); + return s; + } + + /** Returns string consisting of all chars after a dot. */ + public String afterDot(String s) { + int i = s.indexOf('.'); + if (i < 0) { + return null; + } else { + return s.substring(i+1,s.length()); + } + } +} + +PARSER_END(JragParser) + +/* WHITE SPACE */ + +<DEFAULT,COLLECTION_DECL> +SPECIAL_TOKEN : +{ + " " +| "\t" +| "\n" +| "\r" +| "\f" +} + +/* COMMENTS */ + +<DEFAULT,COLLECTION_DECL> +MORE : +{ + "//" : IN_SINGLE_LINE_COMMENT +| + <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT +| + "/*" : IN_MULTI_LINE_COMMENT +} + + +<IN_SINGLE_LINE_COMMENT> +SPECIAL_TOKEN : +{ + <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT +} + +<IN_FORMAL_COMMENT> +SPECIAL_TOKEN : +{ + <FORMAL_COMMENT: "*/" > : DEFAULT +} + +<IN_MULTI_LINE_COMMENT> +SPECIAL_TOKEN : +{ + <MULTI_LINE_COMMENT: "*/" > : DEFAULT +} + +<IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT> +MORE : +{ + < ~[] > +} + +/* RESERVED WORDS AND LITERALS */ + +<DEFAULT,COLLECTION_DECL> +TOKEN : +{ + < ABSTRACT: "abstract" > +| < ASSERT: "assert" > +| < BOOLEAN: "boolean" > +| < BREAK: "break" > +| < BYTE: "byte" > +| < CASE: "case" > +| < CATCH: "catch" > +| < CHAR: "char" > +| < CLASS: "class" > +| < CONST: "const" > +| < CONTINUE: "continue" > +| < _DEFAULT: "default" > +| < DO: "do" > +| < DOUBLE: "double" > +| < ELSE: "else" > +| < ENUM: "enum" > +| < EXTENDS: "extends" > +| < FALSE: "false" > +| < FINAL: "final" > +| < FINALLY: "finally" > +| < FLOAT: "float" > +| < FOR: "for" > +| < GOTO: "goto" > +| < IF: "if" > +| < IMPLEMENTS: "implements" > +| < IMPORT: "import" > +| < INSTANCEOF: "instanceof" > +| < INT: "int" > +| < INTERFACE: "interface" > +| < LONG: "long" > +| < NATIVE: "native" > +| < NEW: "new" > +| < NULL: "null" > +| < PACKAGE: "package"> +| < PRIVATE: "private" > +| < PROTECTED: "protected" > +| < PUBLIC: "public" > +| < RETURN: "return" > +| < SHORT: "short" > +| < STATIC: "static" > +| < STRICTFP: "strictfp" > +| < SUPER: "super" > +| < SWITCH: "switch" > +| < SYNCHRONIZED: "synchronized" > +| < THIS: "this" > +| < THROW: "throw" > +| < THROWS: "throws" > +| < TRANSIENT: "transient" > +| < TRUE: "true" > +| < TRY: "try" > +| < VOID: "void" > +| < VOLATILE: "volatile" > +| < WHILE: "while" > + +// JastAdd keywords: +| < INH: "inh"> +| < SYN: "syn"> +| < LAZY: "lazy"> +| < REWRITE: "rewrite"> +| < TO: "to"> +| < WHEN: "when"> +| < ASPECT: "aspect"> +| < EQUATION: "eq"> +| < CIRCULAR: "circular"> +| < REFINE: "refine"> +| < CONTRIBUTES: "contributes"> +| < EACH: "each"> +| < NTA: "nta"> +| < CACHE: "cache"> +| < UNCACHE: "uncache"> +} + +TOKEN : +{ + < COLL: "coll"> : COLLECTION_DECL +} + +<COLLECTION_DECL> +TOKEN : +{ + < WITH: "with"> +| < ROOT: "root"> +} + +/* LITERALS */ + +<DEFAULT,COLLECTION_DECL> +TOKEN : +{ + < INTEGER_LITERAL: + <DECIMAL_LITERAL> (["l","L"])? + | <HEX_LITERAL> (["l","L"])? + | <OCTAL_LITERAL> (["l","L"])? + > +| + < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* > +| + < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ > +| + < #OCTAL_LITERAL: "0" (["0"-"7"])* > +| + < FLOATING_POINT_LITERAL: + (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])? + | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])? + | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])? + | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"] + > +| + < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > +| + < CHARACTER_LITERAL: + "'" + ( (~["'","\\","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + ) + "'" + > +| + < STRING_LITERAL: + "\"" + ( (~["\"","\\","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + )* + "\"" + > +} + +/* IDENTIFIERS */ + +<DEFAULT,COLLECTION_DECL> +TOKEN : +{ + < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* > +| + < #LETTER: + [ + "\u0024", + "\u0041"-"\u005a", + "\u005f", + "\u0061"-"\u007a", + "\u00c0"-"\u00d6", + "\u00d8"-"\u00f6", + "\u00f8"-"\u00ff", + "\u0100"-"\u1fff", + "\u3040"-"\u318f", + "\u3300"-"\u337f", + "\u3400"-"\u3d2d", + "\u4e00"-"\u9fff", + "\uf900"-"\ufaff" + ] + > +| + < #DIGIT: + [ + "\u0030"-"\u0039", + "\u0660"-"\u0669", + "\u06f0"-"\u06f9", + "\u0966"-"\u096f", + "\u09e6"-"\u09ef", + "\u0a66"-"\u0a6f", + "\u0ae6"-"\u0aef", + "\u0b66"-"\u0b6f", + "\u0be7"-"\u0bef", + "\u0c66"-"\u0c6f", + "\u0ce6"-"\u0cef", + "\u0d66"-"\u0d6f", + "\u0e50"-"\u0e59", + "\u0ed0"-"\u0ed9", + "\u1040"-"\u1049" + ] + > +} + +/* SEPARATORS */ + +<DEFAULT,COLLECTION_DECL> +TOKEN : +{ + < LPAREN: "(" > +| < RPAREN: ")" > +| < LBRACE: "{" > +| < RBRACE: "}" > +| < LBRACKET: "[" > +| < RBRACKET: "]" > +| < SEMICOLON: ";" > +| < COMMA: "," > +| < DOT: "." > +| < AT: "@" > +} + +/* OPERATORS */ + +<DEFAULT,COLLECTION_DECL> +TOKEN : +{ + < ASSIGN: "=" > +| < LT: "<" > +| < BANG: "!" > +| < TILDE: "~" > +| < HOOK: "?" > +| < COLON: ":" > +| < EQ: "==" > +| < LE: "<=" > +| < GE: ">=" > +| < NE: "!=" > +| < SC_OR: "||" > +| < SC_AND: "&&" > +| < INCR: "++" > +| < DECR: "--" > +| < PLUS: "+" > +| < MINUS: "-" > +| < STAR: "*" > +| < SLASH: "/" > +| < BIT_AND: "&" > +| < BIT_OR: "|" > +| < XOR: "^" > +| < REM: "%" > +| < LSHIFT: "<<" > +| < PLUSASSIGN: "+=" > +| < MINUSASSIGN: "-=" > +| < STARASSIGN: "*=" > +| < SLASHASSIGN: "/=" > +| < ANDASSIGN: "&=" > +| < ORASSIGN: "|=" > +| < XORASSIGN: "^=" > +| < REMASSIGN: "%=" > +| < LSHIFTASSIGN: "<<=" > +| < RSIGNEDSHIFTASSIGN: ">>=" > +| < RUNSIGNEDSHIFTASSIGN: ">>>=" > +| < ELLIPSIS: "..." > +| < ARROW: "->" > +| < DOUBLECOLON: "::" > +} + +/* >'s need special attention due to generics syntax. */ +<DEFAULT,COLLECTION_DECL> +TOKEN : +{ + < RUNSIGNEDSHIFT: ">>>" > + { + matchedToken.kind = GT; + ((Token.GTToken)matchedToken).realKind = RUNSIGNEDSHIFT; + input_stream.backup(2); + } +| < RSIGNEDSHIFT: ">>" > + { + matchedToken.kind = GT; + ((Token.GTToken)matchedToken).realKind = RSIGNEDSHIFT; + input_stream.backup(1); + } +| < GT: ">" > +} + +/***************************************** + * THE JAVA LANGUAGE GRAMMAR STARTS HERE * + *****************************************/ + +/* + * Program structuring syntax follows. + */ + +ASTCompilationUnit CompilationUnit() : +{} +{ + ( ImportDeclaration() )* + ( TypeDeclaration() )* + <EOF> + { + return jjtThis; + } +} + +void ImportDeclaration() : +{} +{ + "import" [ "static" ] Name() [ "." "*" ] ";" +} + +String Modifiers() : +{ + StringBuilder buf = new StringBuilder(); + SimpleNode annotation; +} +{ + (LOOKAHEAD(2) + ( + "public" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "static" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "protected" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "private" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "final" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "abstract" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "synchronized" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "native" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "transient" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "volatile" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + "strictfp" + { + if (buf.length() > 0) buf.append(" "); + buf.append(token.image); + } + | + annotation = Annotation() + { + if (buf.length() > 0) buf.append(" "); + buf.append(Unparser.unparse(annotation)); + } + ) + )* + { jjtree.popNode(); return buf.toString(); } +} + +void TypeDeclaration() : +{ + String modifiers; +} +{ + ";" +| + modifiers = Modifiers() + ( + ClassDeclaration(modifiers) + | + InterfaceDeclaration(modifiers) + | + UnmodifiedEnumDeclaration(modifiers) + | + AnnotationTypeDeclaration(modifiers) + | + AspectDeclaration(modifiers) + ) +} + +void AspectDeclaration(String modifiers) : +{ Token t; } +{ + "aspect" { pushTopLevelOrAspect("aspect"); } + t = <IDENTIFIER> { + enclosingAspect = t.image; + root.registerAspect(enclosingAspect, Unparser.unparseComment(jjtThis)); + } + AspectBody() + { popTopLevelOrAspect(); enclosingAspect = ""; } +} + +void AspectBody() : +{} +{ + "{" ( AspectBodyDeclaration() )* "}" +} + +void AspectBodyDeclaration() : +{} +{ + LOOKAHEAD(<REFINE> <IDENTIFIER> "eq" <IDENTIFIER> "." <IDENTIFIER> "(" [<INT> <IDENTIFIER>] ")" "." <IDENTIFIER>) + AspectRefineInhEquation() +| + LOOKAHEAD(<REFINE> <IDENTIFIER> "eq") + AspectRefineSynEquation() +| + LOOKAHEAD(AspectRefineMethodDeclarationLookahead()) + AspectRefineMethodDeclaration() +| + LOOKAHEAD(<REFINE>) + AspectRefineConstructorDeclaration() +| + LOOKAHEAD( Modifiers() "class" ) + AspectClassDeclaration() +| + LOOKAHEAD( Modifiers() "interface" ) + AspectInterfaceDeclaration() +| + LOOKAHEAD( Modifiers() "enum" ) + AspectEnumDeclaration() +| + LOOKAHEAD( ( Annotation() )* "syn" ) + AspectSynAttributeDeclaration() +| + LOOKAHEAD( ( Annotation() )* "inh" ) + AspectInhAttributeDeclaration() +| + LOOKAHEAD( "rewrite" ) + AspectRewrite() +| + LOOKAHEAD( ( Annotation() )* "eq" <IDENTIFIER> "." <IDENTIFIER> "(" [<INT> <IDENTIFIER>] ")" "." ) + AspectInhEquation() +| + LOOKAHEAD( ( Annotation() )* "eq" ) + AspectSynEquation() +| + LOOKAHEAD( <IDENTIFIER> "implements" ) + AspectAddInterface() +| + LOOKAHEAD( <IDENTIFIER> "extends" ) + AspectExtendInterface() +| + LOOKAHEAD( ( Annotation() )* "coll" ) + CollectionAttribute() +| + LOOKAHEAD( <IDENTIFIER> "contributes" ) + CollectionContribution() +| + LOOKAHEAD( AspectMethodDeclarationLookahead() ) + AspectMethodDeclaration() +| + LOOKAHEAD( Modifiers() <IDENTIFIER> "." <IDENTIFIER> "(" ) + AspectConstructorDeclaration() +| + LOOKAHEAD( AspectFieldDeclarationLookahead() ) + AspectFieldDeclaration() +| + LOOKAHEAD( ( "cache" | "uncache" ) ) + AspectCacheDeclaration() +} + +/** + * This production is used for aspects generated by JastAdd and includes an EOF + */ +void AspectBodyDeclarationsEOF() : +{} +{ + ( AspectBodyDeclaration() )* <EOF> +} + +void AspectClassDeclaration() : +{ + Token t; + Token first; + String outerClassName; + String name = ""; + SimpleNode nameList = null; + String modifiers; + SimpleNode node; + org.jastadd.ast.AST.TypeDecl typeDecl = null; + String typeParameters; +} +{ + modifiers = Modifiers() + first = "class" + t = <IDENTIFIER> { + pushTopLevelOrAspect("class"); + outerClassName = className; + className = t.image; + typeDecl = root.findClassDecl(className, Unparser.unparseComment(jjtThis), + fileName, first.beginLine, enclosingAspect); + typeDecl.modifiers = modifiers; + } + [ typeParameters = TypeParameters() { typeDecl.typeParameters = typeParameters; } ] + [ "extends" + node = ClassOrInterfaceType() { + name = Unparser.unparse(node); + if (!name.equals("") && typeDecl instanceof org.jastadd.ast.AST.ClassDecl) { + ((org.jastadd.ast.AST.ClassDecl)typeDecl).extendsName = name; + } + } + ] + [ "implements" nameList = TypeNameList() { root.addInterface(nameList, className, fileName); } ] + AspectClassBody() { className = outerClassName; popTopLevelOrAspect(); } +} + +void AspectClassBody() : +{ + SimpleNode n; +} +{ + "{" ( n = ClassBodyDeclaration() { root.addClassBodyDecl(n, className, fileName, enclosingAspect); } )* "}" +} + +void AspectInterfaceDeclaration() : +{ + Token t; + Token first; + String outerClassName; + SimpleNode nameList = null; + org.jastadd.ast.AST.TypeDecl typeDecl = null; + String typeParameters; + String modifiers; +} +{ + modifiers = Modifiers() + first = "interface" + t = <IDENTIFIER> { + pushTopLevelOrAspect("interface"); + outerClassName = className; + className = t.image; + typeDecl = root.findInterfaceDecl(className, Unparser.unparseComment(jjtThis), + fileName, first.beginLine, enclosingAspect); + typeDecl.modifiers = modifiers; + } + [ typeParameters = TypeParameters() { typeDecl.typeParameters = typeParameters; } ] + [ "extends" nameList = TypeNameList() { root.addInterface(nameList, className, fileName); } ] + "{" ( AspectInterfaceMemberDeclaration() )* "}" { className = outerClassName; popTopLevelOrAspect(); } +} + +void AspectInterfaceMemberDeclaration() : +{} +{ + LOOKAHEAD( Modifiers() "class" ) + AspectNestedClassDeclaration() +| + LOOKAHEAD( Modifiers() "interface" ) + AspectNestedInterfaceDeclaration() +| + LOOKAHEAD("syn") + AspectInterfaceSynAttributeDeclaration() +| + LOOKAHEAD("inh") + AspectInterfaceInhAttributeDeclaration() +| + LOOKAHEAD( AspectInterfaceMethodDeclarationLookahead() ) + AspectInterfaceMethodDeclaration() +| + AspectInterfaceFieldDeclaration() +} + +void AspectInterfaceSynAttributeDeclaration() : +{ String attrType; + Token attrName; + Token t; + Token first, last; + + String type; + Token name; + String targetName; + + org.jastadd.ast.AST.List list = new org.jastadd.ast.AST.List(); + + SimpleNode eq = null; + + boolean init = false; + boolean isLazy = false; + boolean isFinal = false; + SimpleNode bottomValue = null; + + ArrayList<String> annotations = new ArrayList<String>(); + SimpleNode annotation; +} +{ + ( annotation = Annotation() { annotations.add(Unparser.unparseSkipComment(annotation)); } )* + + "syn" { first = token; } ["lazy" {isLazy = true;}] ["final" {isFinal = true;}] + attrType = AspectType() attrName = AttributeName() + + "(" + [ + type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); } + ( "," type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); })* + ] + ")" + + [ + <CIRCULAR> <LBRACKET> bottomValue = Expression() <RBRACKET> + ] + + ";" { last = token; } + { + root.addSynDecl(attrName.image, attrType, className, + isLazy, fileName, first.beginLine, last.endLine, list, + bottomValue == null ? "" : Unparser.unparse(bottomValue), + isFinal, false, jjtThis, enclosingAspect, annotations); + + } +} + +void AspectInterfaceInhAttributeDeclaration() : +{ String attrType; + Token attrName; + Token t; + Token first, last; + + String type; + Token name; + String targetName; + org.jastadd.ast.AST.List list = new org.jastadd.ast.AST.List(); + SimpleNode bottomValue = null; + boolean isLazy = false; + boolean isFinal = false; + + ArrayList<String> annotations = new ArrayList<String>(); + SimpleNode annotation; +} +{ + ( annotation = Annotation() { annotations.add(Unparser.unparse(annotation)); } )* + + "inh" { first = token; } ["lazy" {isLazy = true;}] ["final" {isFinal = true;}] attrType = AspectType() + attrName = AttributeName() + + "(" + [ + type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); } + ( "," type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); })* + ] + + ")" + + [ + <CIRCULAR> <LBRACKET> bottomValue = Expression() <RBRACKET> + ] + + ";" + { + last = token; + root.addInhDecl(attrName.image, attrType, className, + isLazy, fileName, first.beginLine, + last.endLine, list, bottomValue == null ? "" : Unparser.unparse(bottomValue), + isFinal, false, jjtThis, enclosingAspect, annotations); + } +} + +void AspectInterfaceMethodDeclarationLookahead() : +{} +{ + ( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" )* + AspectResultType() JavaIdentifier() "(" +} + +void AspectInterfaceMethodDeclaration() : +{ + Token t; +} +{ + ( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" )* + AspectResultType() MethodDeclarator() [ "throws" NameList() ] + ";" { + root.addClassBodyDecl(jjtThis, className, fileName, enclosingAspect); + } +} + +void AspectInterfaceFieldDeclaration() : +{ + Token t; + String modifiers; +} +{ + modifiers = Modifiers() + AspectType() VariableDeclarator() ( "," VariableDeclarator() )* ";" + { + root.addClassBodyDecl(jjtThis, className, fileName, enclosingAspect); + } +} + +void AspectNestedInterfaceDeclaration() : +{ + String outerClassName = className; + className = "D$u$m$m$y"; + String modifiers; +} +{ + modifiers = Modifiers() + "interface" { pushTopLevelOrAspect("interface"); } <IDENTIFIER> + [ TypeParameters() ] + [ "extends" TypeNameList() ] + "{" ( InterfaceMemberDeclaration() )* "}" + { + className = outerClassName; + root.addClassBodyDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + popTopLevelOrAspect(); + } +} + +void AspectNestedClassDeclaration() : +{ + String outerClassName = className; + className = "D$u$m$m$y"; + String modifiers; + String typeParameters; +} +{ + modifiers = Modifiers() + "class" { pushTopLevelOrAspect("class"); } <IDENTIFIER> + [ TypeParameters() ] + [ "extends" ClassOrInterfaceType() ] + [ "implements" TypeNameList() ] + ClassBody() + { + className = outerClassName; + root.addClassBodyDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + popTopLevelOrAspect(); + } +} + +void AspectMethodDeclarationLookahead() : +{} +{ + Modifiers() + [ TypeParameters() ] + AspectResultType() <IDENTIFIER> "." JavaIdentifier() "(" +} + +void AspectMethodDeclaration() : +{Token t;} +{ + Modifiers() + [ TypeParameters() ] + AspectResultType() t = <IDENTIFIER> "." { className = t.image; } MethodDeclarator() [ "throws" NameList() ] + ( Block() | ";" ) { + root.addClassBodyDecl(jjtThis, className, fileName, enclosingAspect); + } +} + +void AspectRefineMethodDeclarationLookahead() : +{} +{ + <REFINE> [LOOKAHEAD(<IDENTIFIER>)<IDENTIFIER>] + Modifiers() + [ TypeParameters() ] + AspectResultType() <IDENTIFIER> "." JavaIdentifier() "(" +} + +void AspectRefineMethodDeclaration() : +{Token t; String aspectName = ""; String secondAspectName; } +{ + t = <REFINE> { t.image = ""; } [LOOKAHEAD(<IDENTIFIER>) t = <IDENTIFIER> { aspectName = t.image; t.image = ""; }] + Modifiers() + [ TypeParameters() ] + AspectResultType() t = <IDENTIFIER> "." { className = t.image; } MethodDeclarator() [ "throws" NameList() ] + ( Block() | ";" ) { + root.addRefinedClassBodyDecl(jjtThis, className, fileName, aspectName, enclosingAspect); + } +} +void AspectConstructorDeclaration() : +{Token t;} +{ + Modifiers() + t = <IDENTIFIER> "." { className = t.image; } <IDENTIFIER> FormalParameters() [ "throws" NameList() ] + "{" + [ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ] + ( BlockStatement() )* + "}" + { + root.addClassBodyDecl(jjtThis, className, fileName, enclosingAspect); + } +} + +void AspectRefineConstructorDeclaration() : +{Token t; String aspectName; String secondAspectName; } +{ + t = <REFINE> { t.image = ""; } t = <IDENTIFIER> { aspectName = t.image; t.image = ""; } [ "public" | "protected" | "private" ] + t = <IDENTIFIER> "." { className = t.image; } <IDENTIFIER> FormalParameters() [ "throws" NameList() ] + "{" + [ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ] + ( BlockStatement() )* + "}" + { + root.addRefinedClassBodyDecl(jjtThis, className, fileName, aspectName, enclosingAspect); + } +} + +void AspectFieldDeclarationLookahead() : +{} +{ + Modifiers() + AspectType() <IDENTIFIER> "." VariableDeclarator() +} + +void AspectFieldDeclaration() : +{Token t;} +{ + Modifiers() + AspectType() t = <IDENTIFIER> "." { className = t.image; } VariableDeclarator() ( "," VariableDeclarator() )* ";" { + root.addClassBodyDecl(jjtThis, className, fileName, enclosingAspect); + } +} + +void AspectSynAttributeDeclaration() : +{ String attrType; + Token attrName; + Token t; + Token first, last; + + String type; + Token name; + String targetName; + + org.jastadd.ast.AST.List list = new org.jastadd.ast.AST.List(); + + SimpleNode eq = null; + + boolean init = false; + boolean isLazy = false; + SimpleNode bottomValue = null; + boolean isFinal = false; + boolean isNTA = false; + + ArrayList<String> annotations = new ArrayList<String>(); + SimpleNode annotation; +} +{ + ( annotation = Annotation() { annotations.add(Unparser.unparseSkipComment(annotation)); } )* + + "syn" { first = token; } + + [<NTA> {isNTA = true; }] + + ["lazy" {isLazy = true;}] + + ["final" {isFinal = true; }] + + attrType = AspectType() + + t = <IDENTIFIER> "." { targetName = t.image; } + + attrName = AttributeName() + + "(" + [ + type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); } + ( "," type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); })* + ] + ")" + + [ + <CIRCULAR> <LBRACKET> bottomValue = Expression() <RBRACKET> + ] + + ( ("=" eq = Expression() ";" { last = token; init = true;} ) + | (eq = Block() { last = token; init = true;}) + | ";" { last = token; } ) + + { + root.addSynDecl(attrName.image, attrType, targetName, + isLazy, fileName, first.beginLine, + last.endLine, list, bottomValue == null ? "" : Unparser.unparse(bottomValue), + isFinal, isNTA, jjtThis, enclosingAspect, annotations); + + if (init) { + root.addSynEq(attrName.image, targetName, eq, fileName, first.beginLine, + last.endLine, (org.jastadd.ast.AST.List)list.fullCopy(), jjtThis, + enclosingAspect, annotations); + } + } +} + +void AspectInhAttributeDeclaration() : +{ String attrType; + Token attrName; + Token t; + Token first, last; + + String type; + Token name; + String targetName; + org.jastadd.ast.AST.List list = new org.jastadd.ast.AST.List(); + SimpleNode bottomValue = null; + boolean isLazy = false; + boolean isFinal = false; + boolean isNTA = false; + + ArrayList<String> annotations = new ArrayList<String>(); + SimpleNode annotation; +} +{ + ( annotation = Annotation() { annotations.add(Unparser.unparseSkipComment(annotation)); } )* + + "inh" { first = token; } [<NTA> {isNTA = true;}] ["lazy" {isLazy = true;}] ["final" {isFinal = true; }] attrType = AspectType() + t = <IDENTIFIER> "." { targetName = t.image; } + attrName = AttributeName() + + "(" + [ + type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); } + ( "," type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); })* + ] + + ")" + + [ + <CIRCULAR> <LBRACKET> bottomValue = Expression() <RBRACKET> + ] + + ";" + { + last = token; + root.addInhDecl(attrName.image, attrType, targetName, + isLazy, fileName, first.beginLine, + last.endLine, list, bottomValue == null ? "" : Unparser.unparse(bottomValue), + isFinal, isNTA, jjtThis, enclosingAspect, annotations); + } +} + + +void AspectRewrite() : +{ + Token t; + SimpleNode cond; + SimpleNode eq; + Token first, last; + + Token parent = null; + Token child = null; + String type; +} +{ + "rewrite" {cond = null; first = token;} t = <IDENTIFIER> { className = t.image; } + [<IDENTIFIER> parent = <IDENTIFIER> "." child = <IDENTIFIER> <LPAREN> <RPAREN>] + <LBRACE> + ( ["when" { first = token; } <LPAREN> cond = Expression() <RPAREN>] + "to" type = AspectType() ( (eq = Expression() ";" { last = token; }) | eq = Block() { last = token; } ) + { + if (parent != null && child != null) { + root.addRewriteList(className, cond, eq, type, fileName, first.beginLine, last.endLine, parent.image, child.image, enclosingAspect); + } else { + root.addRewrite(className, cond, eq, type, fileName, first.beginLine, last.endLine, enclosingAspect); + } + cond = null; + } + )+ + <RBRACE> +} + +void AspectSynEquation() : +{ + String t; + Token first, last; + SimpleNode eq; + String type; + Token name; + Token attrName; + Token targetName; + org.jastadd.ast.AST.List list = new org.jastadd.ast.AST.List(); + + ArrayList<String> annotations = new ArrayList<String>(); + SimpleNode annotation; +} +{ + ( annotation = Annotation() { annotations.add(Unparser.unparseSkipComment(annotation)); } )* + + "eq" { first = token; } + + targetName = <IDENTIFIER> "." + attrName = AttributeName() + + "(" + [ + type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); } + ( "," type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); })* + ] + + ")" + + ( ("=" eq = Expression() ";" { last = token; }) + | eq = Block() { last = token; } ) + + { + root.addSynEq(attrName.image, targetName.image, eq, fileName, + first.beginLine, last.endLine, list, jjtThis, enclosingAspect, + annotations); + } + +} +void AspectRefineSynEquation() : +{ + String t; + Token first, last; + SimpleNode eq; + String type; + Token name; + Token attrName; + Token targetName; + Token aspectName; + Token secondAspectName; + org.jastadd.ast.AST.List list = new org.jastadd.ast.AST.List(); +} +{ + <REFINE> aspectName = <IDENTIFIER> + "eq" { first = token; } + + targetName = <IDENTIFIER> "." + attrName = AttributeName() + + "(" + [ + type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); } + ( "," type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); })* + ] + + ")" + + ( ( ("=" eq = Expression() ";" { last = token; }) + | eq = Block() { last = token; } ) + { root.addRefinedSynEq(attrName.image, targetName.image, eq, fileName, first.beginLine, last.endLine, list, aspectName.image, jjtThis, enclosingAspect); } + ) +} + +void AspectInhEquation() : +{ + String t; + Token first, last; + SimpleNode eq; + Token name; + String type; + Token attrName; + Token targetName; + Token childName; + org.jastadd.ast.AST.List list = new org.jastadd.ast.AST.List(); + org.jastadd.ast.AST.Parameter p = null; + + ArrayList<String> annotations = new ArrayList<String>(); + SimpleNode annotation; +} +{ + ( annotation = Annotation() { annotations.add(Unparser.unparseSkipComment(annotation)); } )* + + "eq" { first = token; } + + targetName = <IDENTIFIER> "." + childName = <IDENTIFIER> "(" [ <INT> name = <IDENTIFIER> { p = new org.jastadd.ast.AST.Parameter("int", name.image); } ] ")" "." + attrName = AttributeName() + + "(" + [ + type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); } + ( "," type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); })* + ] + + ")" + + ( ("=" eq = Expression() ";" { last = token; }) + | eq = Block() { last = token; } ) + + { + root.addInhEq(childName.image, attrName.image, targetName.image, eq, + fileName, first.beginLine, last.endLine, list, p, jjtThis, + enclosingAspect, annotations); + } +} +void AspectRefineInhEquation() : +{ + String t; + Token first, last; + SimpleNode eq; + Token name; + String type; + Token attrName; + Token targetName; + Token childName; + org.jastadd.ast.AST.List list = new org.jastadd.ast.AST.List(); + org.jastadd.ast.AST.Parameter p = null; + Token aspectName; +} +{ + <REFINE> aspectName = <IDENTIFIER> "eq" { first = token; } + + targetName = <IDENTIFIER> "." + childName = <IDENTIFIER> "(" [ <INT> name = <IDENTIFIER> { p = new org.jastadd.ast.AST.Parameter("int", name.image); } ] ")" "." + attrName = AttributeName() + + "(" + [ + type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); } + ( "," type = Type() name = <IDENTIFIER> { list.add(new org.jastadd.ast.AST.Parameter(type, name.image)); })* + ] + + ")" + + ( ("=" eq = Expression() ";" { last = token; }) + | eq = Block() { last = token; } ) + + { + root.addRefinedInhEq(childName.image, attrName.image, targetName.image, eq, fileName, first.beginLine, last.endLine, list, p, aspectName.image, jjtThis, enclosingAspect); + } +} + +void CollectionAttribute(): +{ + Token t; + Token first, last; + String attrType; + String targetName; + Token attrName; + String combOp = "add"; + String rootName = null; + SimpleNode startValue = null; + boolean isCircular = false; + + ArrayList<String> annotations = new ArrayList<String>(); + SimpleNode annotation; +} +{ + ( annotation = Annotation() { annotations.add(Unparser.unparseSkipComment(annotation)); } )* + "coll" { first = token; } + attrType = AspectType() t = <IDENTIFIER> "." { targetName = t.image; } attrName = AttributeName() "(" ")" + [ <CIRCULAR> { isCircular = true; } ] + [ <LBRACKET> startValue = Expression() <RBRACKET> ] + [ <WITH> t = <IDENTIFIER> { combOp = t.image; } ] + [ <ROOT> t = <IDENTIFIER> { rootName = t.image; } ] + ";" + { + last = token; + root.addCollDecl(attrName.image, attrType, targetName, fileName, + first.beginLine, last.endLine, + startValue == null ? "new " + attrType + "()" : Unparser.unparse(startValue), + combOp, + isCircular, annotations, jjtThis, rootName, enclosingAspect); + token_source.SwitchTo(DEFAULT); + } +} + +void CollectionContribution(): +{ + Token t; + Token first, last; + SimpleNode block; + SimpleNode value = null; + SimpleNode condition = null; + SimpleNode ntaExpression = null; + String targetName; + String targetAttributeName; + String attributeType; + String surveyBlock = null; + SimpleNode reference = null; + org.jastadd.ast.AST.List contributionList = new org.jastadd.ast.AST.List(); + boolean iterableValue = false; + boolean iterableTarget = false; + ArrayList<String> annotations = new ArrayList<String>(); + SimpleNode annotation; +} +{ + ( annotation = Annotation() { annotations.add(Unparser.unparseComment(annotation)); } )* + t = <IDENTIFIER> { first = token; attributeType = t.image; } + "contributes" + ( + LOOKAHEAD("nta") "nta" + ntaExpression = Expression() + "to" t = <IDENTIFIER> "." { targetName = t.image; } t = AttributeName() { targetAttributeName = t.image; } "(" ")" + | [ LOOKAHEAD("each") "each" { iterableValue = true; } ] + value = Expression() + [ "when" condition = Expression() ] + "to" t = <IDENTIFIER> "." { targetName = t.image; } t = AttributeName() { targetAttributeName = t.image; } "(" ")" + [ "for" [ LOOKAHEAD("each") "each" { iterableTarget = true; } ] reference = Expression() ] + | block = Block() { surveyBlock = Unparser.unparse(block); } + "to" t = <IDENTIFIER> "." { targetName = t.image; } t = AttributeName() { targetAttributeName = t.image; } "(" ")" + ) + ";" { last = token; } + { + if (surveyBlock != null) { + root.addCustomSurveyBlock(targetName, + targetAttributeName, + attributeType, + surveyBlock, + fileName, + first.beginLine, + last.endLine, + jjtThis, + enclosingAspect, + annotations); + } else if (ntaExpression != null) { + root.addCustomSurveyExpression(targetName, + targetAttributeName, + attributeType, + Unparser.unparse(ntaExpression), + fileName, + first.beginLine, + last.endLine, + jjtThis, + enclosingAspect, + annotations); + } else { + org.jastadd.ast.AST.CollEq equ = root.addCollEq(targetName, + targetAttributeName, + attributeType, + reference == null ? "" : Unparser.unparse(reference), + fileName, + first.beginLine, + last.endLine, + iterableValue, + iterableTarget, + jjtThis, + enclosingAspect, + annotations); + // TODO(joqvist): make the returned equ non-null. + if (equ != null) { + equ.setValue(Unparser.unparse(value)); + if (condition != null) { + equ.setCondition(Unparser.unparse(condition)); + } + } + } + } +} + +void AspectAddInterface() : +{ + Token first, last; + Token targetName; + SimpleNode nameList; +} +{ + targetName = <IDENTIFIER> { first = token; } + "implements" + nameList = TypeNameList() + ";" + { + last = token; + root.addInterface(nameList, targetName.image, fileName); + } + +} + +void AspectExtendInterface() : +{ + Token first, last; + Token targetName; + SimpleNode nameList; +} +{ + targetName = <IDENTIFIER> { first = token; } + "extends" + nameList = TypeNameList() + ";" + { + last = token; + root.extendInterface(nameList, targetName.image, fileName); + } + +} + + +/* + * Declaration syntax follows. + */ + +void ClassDeclaration(String modifiers) : +{ Token t; + Token first; + SimpleNode node; + String outerClassName; + StringBuffer name = new StringBuffer(); + org.jastadd.ast.AST.TypeDecl typeDecl = null; + SimpleNode nameList = null; + String typeParameters; +} +{ + first = "class" + t = <IDENTIFIER> { + pushTopLevelOrAspect("class"); + outerClassName = className; + className = t.image; + typeDecl = root.findClassDecl(className, Unparser.unparseComment(jjtThis), + fileName, first.beginLine, enclosingAspect); + typeDecl.modifiers = modifiers; + } + [ typeParameters = TypeParameters() { typeDecl.typeParameters = typeParameters; } ] + [ "extends" + node = ClassOrInterfaceType() { name.append(Unparser.unparse(node)); } + { if(!name.toString().equals("") && typeDecl instanceof org.jastadd.ast.AST.ClassDecl) + ((org.jastadd.ast.AST.ClassDecl)typeDecl).extendsName = name.toString(); + } + ] + [ "implements" nameList = TypeNameList() { root.addInterface(nameList, className, fileName);} ] + ClassBody() { className = outerClassName; popTopLevelOrAspect(); } +} + +SimpleNode TypeNameList(): +{} +{ + ( + ClassOrInterfaceType() + ( "," ClassOrInterfaceType() )* + ) + { return jjtThis; } +} + + +/* Added action to set classname and add class to allClasses */ +void UnmodifiedClassDeclaration(String modifiers) : +{ + Token t; + SimpleNode nameList; + String outerClassName; +} +{ + "class" t = <IDENTIFIER> { pushTopLevelOrAspect("class"); outerClassName = className; className = t.image; } + [ TypeParameters() ] + [ "extends" ClassOrInterfaceType() ] [ "implements" nameList = TypeNameList() ] + ClassBody() { className = outerClassName; popTopLevelOrAspect(); } + { if (shouldAddClassBodyDecl()) { + root.addClassBodyDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + } + } +} + + +void AspectEnumDeclaration(): +{ + Token t; + Token first; + String outerClassName; + String modifiers; + SimpleNode node; + org.jastadd.ast.AST.EnumDecl typeDecl = null; +} +{ + modifiers = Modifiers() + first = "enum" + t = <IDENTIFIER> { + pushTopLevelOrAspect("enum"); + outerClassName = className; + className = t.image; + typeDecl = (org.jastadd.ast.AST.EnumDecl) root.findEnumDecl(className, Unparser.unparseComment(jjtThis), + fileName, first.beginLine, enclosingAspect); + typeDecl.modifiers = modifiers; + typeDecl.simpleNode = jjtThis; + } + [ "implements" TypeNameList() ] + EnumBody() { className = outerClassName; popTopLevelOrAspect(); } +} + +void UnmodifiedEnumDeclaration(String modifiers): +{} +{ + "enum" { pushTopLevelOrAspect("enum"); } JavaIdentifier() + [ "implements" TypeNameList() ] + EnumBody() + { popTopLevelOrAspect(); + if (shouldAddClassBodyDecl()) { + root.addClassBodyDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + } + } +} + +void EnumBody(): +{ + SimpleNode n; +} +{ + "{" + EnumConstant() ( "," EnumConstant() )* + [ ";" ( ClassBodyDeclaration() )* ] + "}" +} + +void EnumConstant(): +{} +{ + JavaIdentifier() [ Arguments() ] [ ClassBody() ] +} + +String TypeParameters(): +{} +{ + ( + "<" TypeParameter() ( "," TypeParameter() )* ">" + ) + { return Unparser.unparse(jjtThis); } +} + +void TypeParameter(): +{} +{ + JavaIdentifier() [ TypeBound() ] +} + +void TypeBound(): +{} +{ + "extends" ClassOrInterfaceType() ( "&" ClassOrInterfaceType() )* +} + + + + +void ClassBody() : +{} +{ + "{" ( ClassBodyDeclaration() )* "}" +} + +/* Added one branch corresponding to attribute declarations + and two branches for syn and inh attribute equations */ +SimpleNode ClassBodyDeclaration() : +{ + String modifiers; +} +{ + ( + LOOKAHEAD(2) + Initializer() +| + modifiers = Modifiers() + ( + UnmodifiedClassDeclaration(modifiers) + | + UnmodifiedInterfaceDeclaration(modifiers) + | + AnnotationTypeDeclaration(modifiers) + | + UnmodifiedEnumDeclaration(modifiers) + | + LOOKAHEAD( [TypeParameters() ] JavaIdentifier() "(" ) + ConstructorDeclaration(modifiers) + | + LOOKAHEAD( AspectType() JavaIdentifier() ( "[" "]" )* ( "," | "=" | ";" ) ) + FieldDeclaration(modifiers) + | + MethodDeclaration(modifiers) + ) +| + ";" + ) + { + return jjtThis; + } +} + +void InterfaceDeclaration(String modifiers) : +{} +{ + UnmodifiedInterfaceDeclaration(modifiers) +} + +void UnmodifiedInterfaceDeclaration(String modifiers) : +{ + boolean isTopLevel; + Token t; + Token first; + String outerClassName; + SimpleNode nameList = null; + org.jastadd.ast.AST.TypeDecl typeDecl = null; + String typeParameters; +} +{ + first = "interface" + t = <IDENTIFIER> { + isTopLevel = inTopLevelOrAspect(); + pushTopLevelOrAspect("interface"); + outerClassName = className; + className = t.image; + if (isTopLevel) { + typeDecl = root.findInterfaceDecl(className, Unparser.unparseComment(jjtThis), + fileName, first.beginLine, enclosingAspect); + typeDecl.modifiers = modifiers; + } + } + [ typeParameters = TypeParameters() { if (isTopLevel) typeDecl.typeParameters = typeParameters; } ] + [ "extends" nameList = TypeNameList() { if (isTopLevel) root.addInterface(nameList, className, fileName); } ] + "{" ( InterfaceMemberDeclaration() )* "}" { className = outerClassName; popTopLevelOrAspect(); } + { if (shouldAddClassBodyDecl()) { + root.addClassBodyDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + } + } +} + +void InterfaceMemberDeclaration() : +{ + String modifiers; +} +{ + modifiers = Modifiers() + ( + UnmodifiedClassDeclaration(modifiers) + | + UnmodifiedInterfaceDeclaration(modifiers) + | + LOOKAHEAD( AspectType() JavaIdentifier() ( "[" "]" )* ( "," | "=" | ";" ) ) + FieldDeclaration(modifiers) + | + MethodDeclaration(modifiers) + ) +| + ";" +} + +void FieldDeclaration(String modifiers) : +{} +{ + AspectType() VariableDeclarator() ( "," VariableDeclarator() )* ";" + { if (shouldAddClassBodyDecl()) { + root.addClassBodyDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + } + } +} + +void VariableDeclarator() : +{} +{ + VariableDeclaratorId() [ "=" VariableInitializer() ] + +} + +void VariableDeclaratorId() : +{} +{ + JavaIdentifier() ( "[" "]" )* +} + +void VariableInitializer() : +{} +{ + ArrayInitializer() +| + Expression() +} + +void ArrayInitializer() : +{} +{ + "{" [ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}" +} + +void MethodDeclaration(String modifiers) : +{} +{ + [ TypeParameters() ] + AspectResultType() MethodDeclarator() [ "throws" NameList() ] + ( Block() | ";" ) + { if (shouldAddClassBodyDecl()) { + root.addMethodDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + } + } +} + +void MethodDeclarator() : +{} +{ + JavaIdentifier() FormalParameters() ( "[" "]" )* +} + +void FormalParameters() : +{} +{ + "(" [ FormalParameter() ( "," FormalParameter() )* ] ")" +} + +void FormalParameter() : +{} +{ + [ "final" ] Type() ["..."] VariableDeclaratorId() +} + +void ConstructorDeclaration(String modifiers) : +{} +{ + [ TypeParameters() ] + JavaIdentifier() FormalParameters() [ "throws" NameList() ] + "{" + [ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ] + ( BlockStatement() )* + "}" + { if (shouldAddClassBodyDecl()) { + root.addClassBodyDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + } + } +} + +void ExplicitConstructorInvocation() : +{} +{ + LOOKAHEAD("this" Arguments() ";") + "this" Arguments() ";" +| + [ LOOKAHEAD(2) PrimaryExpression() "." ] "super" Arguments() ";" +} + +void Initializer() : +{} +{ + [ "static" ] Block() +} + + +/* + * Type, name and expression syntax follows. + */ + +// Attribute type names can not start with JastAdd reserved words such as 'syn', 'eq', etc. +String AspectType(): +{} +{ + ( + LOOKAHEAD(2) AspectReferenceType() + | + LOOKAHEAD(2) PrimitiveType() ( LOOKAHEAD(2) "[" "]" )+ + | + PrimitiveType() + ) + { return Unparser.unparse(jjtThis); } +} + +void AspectResultType(): +{} +{ + "void" + | + AspectType() +} + +void AspectReferenceType(): +{} +{ + ( AspectClassOrInterfaceType() ) ( LOOKAHEAD(2) "[" "]" )* +} + +SimpleNode AspectClassOrInterfaceType(): +{} +{ + ( + <IDENTIFIER> [ LOOKAHEAD(2) TypeArguments() ] + ( LOOKAHEAD(2) "." JavaIdentifier() [ LOOKAHEAD(2) TypeArguments() ] )* + ) + { return jjtThis; } +} + +/*Changed to return string */ +String Type(): +{} +{ + ( + LOOKAHEAD(2) ReferenceType() + | + PrimitiveType() + ) + { return Unparser.unparse(jjtThis); } +} + +void ReferenceType(): +{} +{ + PrimitiveType() ( LOOKAHEAD(2) "[" "]" )+ + | + ( ClassOrInterfaceType() ) ( LOOKAHEAD(2) "[" "]" )* +} + +SimpleNode ClassOrInterfaceType(): +{} +{ + ( + JavaIdentifier() [ LOOKAHEAD(2) TypeArguments() ] + ( LOOKAHEAD(2) "." JavaIdentifier() [ LOOKAHEAD(2) TypeArguments() ] )* + ) + { return jjtThis; } +} + +void TypeArguments(): +{} +{ + "<" [ TypeArgument() ( "," TypeArgument() )* ] ">" +} + +void TypeArgument(): +{} +{ + ReferenceType() + | + "?" [ WildcardBounds() ] +} + +void WildcardBounds(): +{} +{ + "extends" ReferenceType() + | + "super" ReferenceType() +} + +void PrimitiveType(): +{} +{ + "boolean" +| + "char" +| + "byte" +| + "short" +| + "int" +| + "long" +| + "float" +| + "double" +} + +void ResultType(): +{} +{ + "void" +| + Type() +} + +/* Changed to return token */ +String Name() : +/* + * A lookahead of 2 is required below since "Name" can be followed + * by a ".*" when used in the context of an "ImportDeclaration". + */ +{} +{ + (JavaIdentifier() + ( LOOKAHEAD(2) "." JavaIdentifier() + )* + ) + { return Unparser.unparse(jjtThis); } +} + +SimpleNode NameList() : +{} +{ + (Name() + ( "," Name() + )* + ) + { + return jjtThis; + } +} + + +/* + * Expression syntax follows. + */ + +SimpleNode Expression() : +/* + * This expansion has been written this way instead of: + * Assignment() | ConditionalExpression() + * for performance reasons. + * However, it is a weakening of the grammar for it allows the LHS of + * assignments to be any conditional expression whereas it can only be + * a primary expression. Consider adding a semantic predicate to work + * around this. + */ +{} +{ +( + LOOKAHEAD(LambdaExpression()) + LambdaExpression() +| + ConditionalExpression() + [ + LOOKAHEAD(2) + AssignmentOperator() Expression() + ] +) + { + return jjtThis; + } +} + +void AssignmentOperator() : +{} +{ + "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|=" +} + +void ConditionalExpression() : +{} +{ + ConditionalOrExpression() [ "?" Expression() ":" ConditionalExpression() ] +} + +void ConditionalOrExpression() : +{} +{ + ConditionalAndExpression() ( "||" ConditionalAndExpression() )* +} + +void ConditionalAndExpression() : +{} +{ + InclusiveOrExpression() ( "&&" InclusiveOrExpression() )* +} + +void InclusiveOrExpression() : +{} +{ + ExclusiveOrExpression() ( "|" ExclusiveOrExpression() )* +} + +void ExclusiveOrExpression() : +{} +{ + AndExpression() ( "^" AndExpression() )* +} + +void AndExpression() : +{} +{ + EqualityExpression() ( "&" EqualityExpression() )* +} + +void EqualityExpression() : +{} +{ + InstanceOfExpression() ( ( "==" | "!=" ) InstanceOfExpression() )* +} + +void InstanceOfExpression() : +{} +{ + RelationalExpression() [ "instanceof" Type() ] +} + +void RelationalExpression() : +{} +{ + ShiftExpression() ( ( "<" | ">" | "<=" | ">=" ) ShiftExpression() )* +} + +void ShiftExpression(): +{} +{ + AdditiveExpression() ( ( "<<" | RSIGNEDSHIFT() | RUNSIGNEDSHIFT() ) AdditiveExpression() )* +} + +void AdditiveExpression() : +{} +{ + MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )* +} + +void MultiplicativeExpression() : +{} +{ + UnaryExpression() ( ( "*" | "/" | "%" ) UnaryExpression() )* +} + +void UnaryExpression() : +{} +{ + ( "+" | "-" ) UnaryExpression() +| + PreIncrementExpression() +| + PreDecrementExpression() +| + UnaryExpressionNotPlusMinus() +} + +void PreIncrementExpression() : +{} +{ + "++" PrimaryExpression() +} + +void PreDecrementExpression() : +{} +{ + "--" PrimaryExpression() +} + +void UnaryExpressionNotPlusMinus() : +{} +{ + ( "~" | "!" ) UnaryExpression() +| + LOOKAHEAD( CastLookahead() ) + CastExpression() +| + PostfixExpression() +} + +// This production is to determine lookahead only. The LOOKAHEAD specifications +// below are not used, but they are there just to indicate that we know about +// this. +void CastLookahead() : +{} +{ + LOOKAHEAD(2) + "(" PrimitiveType() +| + LOOKAHEAD("(" Type() "[") + "(" Type() "[" "]" +| + "(" Type() ")" ( "~" | "!" | "(" | JavaIdentifier() | "this" | "super" | "new" | Literal() ) +} + +void PostfixExpression() : +{} +{ + PrimaryExpression() [ "++" | "--" ] +} + +void CastExpression() : +{} +{ + LOOKAHEAD("(" PrimitiveType()) + "(" Type() ")" UnaryExpression() +| + "(" Type() ")" UnaryExpressionNotPlusMinus() +} + +void PrimaryExpression() : +{} +{ + PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )* +} + +void MemberSelector(): +{} +{ + "." TypeArguments() JavaIdentifier() +} + +void PrimaryPrefix() : +{} +{ + Literal() +| + "this" +| + "super" "." JavaIdentifier() +| + "(" Expression() ")" +| + AllocationExpression() +| + LOOKAHEAD( ResultType() "." "class" ) + ResultType() "." "class" +| + Name() +} + +void PrimarySuffix() : +{} +{ + LOOKAHEAD(2) + "." "this" +| + LOOKAHEAD(2) + "." AllocationExpression() +| + LOOKAHEAD(3) + "." TypeArguments() JavaIdentifier() +| + "[" Expression() "]" +| + "." JavaIdentifier() +| + Arguments() +| + LOOKAHEAD(2) + "::" "new" +| + LOOKAHEAD(2) + "::" JavaIdentifier() +} + +void Literal() : +{} +{ + <INTEGER_LITERAL> +| + <FLOATING_POINT_LITERAL> +| + <CHARACTER_LITERAL> +| + <STRING_LITERAL> +| + BooleanLiteral() +| + NullLiteral() +} + +void BooleanLiteral() : +{} +{ + "true" +| + "false" +} + +void NullLiteral() : +{} +{ + "null" +} + +void Arguments() : +{} +{ + "(" [ ArgumentList() ] ")" +} + +void ArgumentList() : +{} +{ + Expression() ( "," Expression() )* +} + +void AllocationExpression() : +{ String outerClassName = className; + className = "D$u$m$m$y"; + pushTopLevelOrAspect("expr"); +} +{ + ( + LOOKAHEAD(2) + "new" PrimitiveType() ArrayDimsAndInits() +| + "new" ClassOrInterfaceType() [ TypeArguments() ] + + ( + ArrayDimsAndInits() + | + Arguments() + [ ClassBody() ] + ) + ) + { + className = outerClassName; + popTopLevelOrAspect(); + } +} + +/* + * The third LOOKAHEAD specification below is to parse to PrimarySuffix + * if there is an expression between the "[...]". + */ +void ArrayDimsAndInits() : +{} +{ + LOOKAHEAD(2) + ( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )* +| + ( "[" "]" )+ ArrayInitializer() +} + +/* + * Java 8 expression additions follow. + * + * New Java 8 expressions: lambdas, method/constructor reference, union types. + */ +void LambdaExpression() : +{} +{ + LambdaParameters() "->" ( Expression() | Block() ) +} + +void LambdaParameters() : +{} +{ + Name() +| + "(" [ LOOKAHEAD(2) TypedLambdaParameters() | UntypedLambdaParameters() ] ")" +} + +void TypedLambdaParameters() : +{} +{ + Type() Name() ( "," Type() Name() )* +} + +void UntypedLambdaParameters() : +{} +{ + Name() ( "," Name() )* +} + +/* + * Statement syntax follows. + */ + +void Statement() : +{} +{ + LOOKAHEAD(2) + LabeledStatement() +| + AssertStatement() +| + Block() +| + EmptyStatement() +| + StatementExpression() ";" +| + SwitchStatement() +| + IfStatement() +| + WhileStatement() +| + DoStatement() +| + ForStatement() +| + BreakStatement() +| + ContinueStatement() +| + ReturnStatement() +| + ThrowStatement() +| + SynchronizedStatement() +| + TryStatement() +} + +void AssertStatement(): +{} +{ + "assert" Expression() [ ":" Expression() ] ";" +} + +void LabeledStatement() : +{} +{ + JavaIdentifier() ":" Statement() +} + +SimpleNode Block() : +{} +{ + ( + "{" ( BlockStatement() )* "}" + ) + { + return jjtThis; + } +} + +void BlockStatement() : +{} +{ + LOOKAHEAD([ "final" ] Type() JavaIdentifier()) + LocalVariableDeclaration() ";" +| + Statement() +| + UnmodifiedClassDeclaration("") +} + +void LocalVariableDeclaration() : +{} +{ + [ "final" ] Type() VariableDeclarator() ( "," VariableDeclarator() )* +} + +void EmptyStatement() : +{} +{ + ";" +} + +void StatementExpression() : +/* + * The last expansion of this production accepts more than the legal + * Java expansions for StatementExpression. This expansion does not + * use PostfixExpression for performance reasons. + */ +{} +{ + PreIncrementExpression() +| + PreDecrementExpression() +| + PrimaryExpression() + [ + "++" + | + "--" + | + AssignmentOperator() Expression() + ] +} + +void SwitchStatement() : +{} +{ + "switch" "(" Expression() ")" "{" + ( SwitchLabel() ( BlockStatement() )* )* + "}" +} + +void SwitchLabel() : +{} +{ + "case" Expression() ":" +| + "default" ":" +} + +void IfStatement() : +/* + * The disambiguating algorithm of JavaCC automatically binds dangling + * else's to the innermost if statement. The LOOKAHEAD specification + * is to tell JavaCC that we know what we are doing. + */ +{} +{ + "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ] +} + +void WhileStatement() : +{} +{ + "while" "(" Expression() ")" Statement() +} + +void DoStatement() : +{} +{ + "do" Statement() "while" "(" Expression() ")" ";" +} + +void ForStatement() : +{} +{ + "for" "(" + + ( + LOOKAHEAD(Type() JavaIdentifier() ":") + Type() JavaIdentifier() ":" Expression() + | + [ ForInit() ] ";" [ Expression() ] ";" [ ForUpdate() ] + ) + + ")" Statement() +} + +void ForInit() : +{} +{ + LOOKAHEAD( [ "final" ] Type() JavaIdentifier() ) + LocalVariableDeclaration() +| + StatementExpressionList() +} + +void StatementExpressionList() : +{} +{ + StatementExpression() ( "," StatementExpression() )* +} + +void ForUpdate() : +{} +{ + StatementExpressionList() +} + +void BreakStatement() : +{} +{ + "break" [ JavaIdentifier() ] ";" +} + +void ContinueStatement() : +{} +{ + "continue" [ JavaIdentifier() ] ";" +} + +void ReturnStatement() : +{} +{ + "return" [ Expression() ] ";" +} + +void ThrowStatement() : +{} +{ + "throw" Expression() ";" +} + +void SynchronizedStatement() : +{} +{ + "synchronized" "(" Expression() ")" Block() +} + +void TryStatement() : +/* + * Semantic check required here to make sure that at least one + * finally/catch is present. + */ +{} +{ + "try" + // Java 7 extension (resource declarations): + [ "(" LocalVariableDeclaration() ( LOOKAHEAD(2) ";" LocalVariableDeclaration() )* [ ";" ] ")" ] + Block() + ( "catch" "(" ["final"] Type() ( "|" ["final"] Type() )* VariableDeclaratorId() ")" Block() )* + [ "finally" Block() ] +} + +/* We use productions to match >>>, >> and > so that we can keep the + * type declaration syntax with generics clean + */ + +void RUNSIGNEDSHIFT(): +{} +{ + ( LOOKAHEAD({ getToken(1).kind == GT && + ((Token.GTToken)getToken(1)).realKind == RUNSIGNEDSHIFT} ) + ">" ">" ">" + ) +} + +void RSIGNEDSHIFT(): +{} +{ + ( LOOKAHEAD({ getToken(1).kind == GT && + ((Token.GTToken)getToken(1)).realKind == RSIGNEDSHIFT} ) + ">" ">" + ) +} + +/* Annotation syntax follows. */ + +SimpleNode Annotation(): +{} +{ + ( + LOOKAHEAD( NormalAnnotation() ) + NormalAnnotation() + | + LOOKAHEAD( SingleMemberAnnotation() ) + SingleMemberAnnotation() + | + LOOKAHEAD( MarkerAnnotation() ) + MarkerAnnotation() + ) + { return jjtThis; } +} + +void NormalAnnotation(): +{} +{ + "@" Name() "(" [ MemberValuePairs() ] ")" +} + +void MarkerAnnotation(): +{} +{ + "@" Name() +} + +void SingleMemberAnnotation(): +{} +{ + "@" Name() "(" MemberValue() ")" +} + +void MemberValuePairs(): +{} +{ + MemberValuePair() ( "," MemberValuePair() )* +} + +void MemberValuePair(): +{} +{ + JavaIdentifier() "=" MemberValue() +} + +void MemberValue(): +{} +{ + Annotation() + | + MemberValueArrayInitializer() + | + ConditionalExpression() +} + +void MemberValueArrayInitializer(): +{} +{ + "{" MemberValue() ( LOOKAHEAD(2) "," MemberValue() )* [ "," ] "}" +} + + +/* Annotation Types. */ + +void AnnotationTypeDeclaration(String modifiers): +{} +{ + "@" "interface" { pushTopLevelOrAspect("annotation"); } JavaIdentifier() AnnotationTypeBody() { popTopLevelOrAspect(); } + { if (shouldAddClassBodyDecl()) { + root.addClassBodyDecl(jjtThis, className, fileName, modifiers, enclosingAspect); + } + } +} + +void AnnotationTypeBody(): +{} +{ + "{" ( AnnotationTypeMemberDeclaration() )* "}" +} + +void AnnotationTypeMemberDeclaration(): +{ + String modifiers; +} +{ + modifiers = Modifiers() + ( + LOOKAHEAD(AspectType() JavaIdentifier() "(") + AspectType() JavaIdentifier() "(" ")" [ DefaultValue() ] ";" + | + UnmodifiedClassDeclaration(modifiers) + | + UnmodifiedInterfaceDeclaration(modifiers) + | + UnmodifiedEnumDeclaration(modifiers) + | + AnnotationTypeDeclaration(modifiers) + | + FieldDeclaration(modifiers) + ) + | + ( ";" ) +} + +void DefaultValue(): +{} +{ + "default" MemberValue() +} + +// Adding (cache|uncached) keywords in front of each line in the cache configuration. +// This information is propagated to the grammar via setAttributeCacheMode(..) +void AspectCacheDeclaration(): +{ + Token t; + Token cacheConfig; + Token hostType; + Token attrName; + + int paramIndex = 1; + String paramType; + Token paramName; + org.jastadd.ast.AST.List paramList = new org.jastadd.ast.AST.List(); +} +{ + ( cacheConfig = "cache" | cacheConfig = "uncache" ) + hostType = <IDENTIFIER> "." + attrName = AttributeName() + "(" { paramList = new org.jastadd.ast.AST.List(); } + [ + paramType = Type() (<IDENTIFIER>)? + { paramList.add(new org.jastadd.ast.AST.Parameter(paramType, "p0")); } + ( + "," paramType = Type() (<IDENTIFIER>)? + { paramList.add(new org.jastadd.ast.AST.Parameter(paramType, "p" + (paramIndex++))); } + )* + ] + ")" + ";" + { + root.setAttributeCacheMode(cacheConfig.image, hostType.image, attrName.image, + paramList, fileName, cacheConfig.beginLine); + } +} + +// Valid Java identifiers include 'syn', 'eq', etc. (reserved JastAdd words are legal in pure Java) +void JavaIdentifier() : +{} +{ + <IDENTIFIER> +| <INH> +| <SYN> +| <LAZY> +| <REWRITE> +| <TO> +| <WHEN> +| <ASPECT> +| <EQUATION> +| <CIRCULAR> +| <REFINE> +| <COLL> +| <CONTRIBUTES> +| <EACH> +| <NTA> +| <CACHE> +| <UNCACHE> +} + +Token AttributeName() : +{Token t;} +{ + t = <IDENTIFIER> { return t; } +} +