diff options
Diffstat (limited to 'javaparser-core/src/main/javacc/java.jj')
-rw-r--r-- | javaparser-core/src/main/javacc/java.jj | 2795 |
1 files changed, 2795 insertions, 0 deletions
diff --git a/javaparser-core/src/main/javacc/java.jj b/javaparser-core/src/main/javacc/java.jj new file mode 100644 index 000000000..c68822878 --- /dev/null +++ b/javaparser-core/src/main/javacc/java.jj @@ -0,0 +1,2795 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +options { + STATIC=false; + COMMON_TOKEN_ACTION=true; + JDK_VERSION = "1.8"; + TOKEN_EXTENDS ="TokenBase"; + JAVA_TEMPLATE_TYPE = "modern"; +} + +PARSER_BEGIN(GeneratedJavaParser) +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ +package com.github.javaparser; +import java.io.*; +import java.util.*; +import com.github.javaparser.ast.*; +import com.github.javaparser.ast.body.*; +import com.github.javaparser.ast.comments.*; +import com.github.javaparser.ast.modules.*; +import com.github.javaparser.ast.expr.*; +import com.github.javaparser.ast.stmt.*; +import com.github.javaparser.ast.type.*; +import com.github.javaparser.utils.*; +import javax.annotation.Generated; +import static com.github.javaparser.JavaToken.INVALID; +import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE; +import static com.github.javaparser.utils.Utils.*; +import static com.github.javaparser.ast.NodeList.*; +import static com.github.javaparser.GeneratedJavaParser.*; +import static com.github.javaparser.Range.*; +import static com.github.javaparser.Position.*; +import static com.github.javaparser.ast.type.ArrayType.*; +import static com.github.javaparser.GeneratedJavaParserTokenManagerBase.*; + +@Generated("JavaCC") +final class GeneratedJavaParser extends GeneratedJavaParserBase { + /* Returns the JavaParser specific token type of the last matched token */ + JavaToken token() { + return token.javaToken; + } + + /* Changes the amount by which the horizontal position is increased when a tab character is encountered. + One by default.*/ + void setTabSize(int size) { + jj_input_stream.setTabSize(size); + } + + @Override + GeneratedJavaParserTokenManager getTokenSource() { + return token_source; + } +} + +PARSER_END(GeneratedJavaParser) + +/* WHITE SPACE */ + +SPECIAL_TOKEN : +{ + <SPACE: [" ", "\t", "\f", "\u0085", "\u00A0", "\u1680", "\u180e", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", + "\u2006", "\u2007", "\u2008", "\u2009", "\u200a", "\u200b", "\u200c", "\u200d", "\u2028", "\u2029", "\u202f", "\u205f", "\u2060", "\u3000", "\ufeff"]> +| <WINDOWS_EOL : "\r\n"> +| <UNIX_EOL: "\n"> +| <OLD_MAC_EOL: "\r"> +} + +TOKEN_MGR_DECLS : +{ + private List<JavaToken> tokens = new ArrayList<JavaToken>(); + private CommentsCollection commentsCollection = new CommentsCollection(); + private JavaToken homeToken; + private Stack<Token> tokenWorkStack = new Stack<Token>(); + private boolean storeTokens; + + void reset() { + tokens = new ArrayList<JavaToken>(); + commentsCollection = new CommentsCollection(); + homeToken = null; + } + + List<JavaToken> getTokens() { + if(storeTokens) { + return tokens; + } + return null; + } + + CommentsCollection getCommentsCollection() { + return commentsCollection; + } + + /* Get the very first token in the file */ + JavaToken getHomeToken() { + return homeToken; + } + + /* Makes the parser keep a list of tokens */ + public void setStoreTokens(boolean storeTokens) { + this.storeTokens = storeTokens; + } + + private void CommonTokenAction(Token token) { + // Use an intermediary stack to avoid recursion, see issue 1003 + do { + tokenWorkStack.push(token); + token = token.specialToken; + } while (token != null); + + // The stack is now filled with tokens in left-to-right order. Process them. + while(!tokenWorkStack.empty()) { + token = tokenWorkStack.pop(); + token.javaToken = new JavaToken(token, tokens); + + if(storeTokens) { + tokens.add(token.javaToken); + } + + if (homeToken == null) { + homeToken = token.javaToken; + } + + if(TokenTypes.isComment(token.kind)) { + Comment comment = createCommentFromToken(token); + commentsCollection.addComment(comment); + } + } + } +} + +/* COMMENTS */ + +SPECIAL_TOKEN : +{ + <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")? > +} + +MORE : +{ + <ENTER_JAVADOC_COMMENT: "/**" ~["/"]> { input_stream.backup(1); } : IN_JAVADOC_COMMENT +| + <ENTER_MULTILINE_COMMENT: "/*"> : IN_MULTI_LINE_COMMENT +} + +<IN_JAVADOC_COMMENT> +SPECIAL_TOKEN : +{ + <JAVADOC_COMMENT: "*/" > : DEFAULT +} + +<IN_MULTI_LINE_COMMENT> +SPECIAL_TOKEN : +{ + <MULTI_LINE_COMMENT: "*/" > : DEFAULT +} + +<IN_JAVADOC_COMMENT, IN_MULTI_LINE_COMMENT> +MORE : +{ + <COMMENT_CONTENT: ~[] > +} + +/* RESERVED WORDS AND LITERALS */ + +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" > +| < REQUIRES: "requires" > +| < TO: "to" > +| < WITH: "with" > +| < OPEN: "open" > +| < OPENS: "opens" > +| < USES: "uses" > +| < MODULE: "module" > +| < EXPORTS: "exports" > +| < PROVIDES: "provides" > +| < TRANSITIVE: "transitive" > +} + +/* LITERALS */ + +TOKEN : +{ + < LONG_LITERAL: + <DECIMAL_LITERAL> (["l","L"]) + | <HEX_LITERAL> (["l","L"]) + | <OCTAL_LITERAL> (["l","L"]) + | <BINARY_LITERAL> (["l","L"]) + > +| + < INTEGER_LITERAL: + <DECIMAL_LITERAL> + | <HEX_LITERAL> + | <OCTAL_LITERAL> + | <BINARY_LITERAL> + > +| + < #DECIMAL_LITERAL: ["0"-"9"]((["0"-"9","_"])*["0"-"9"])? > +| + < #HEX_LITERAL: "0" ["x","X"] <HEX_DIGITS> > +| + < #OCTAL_LITERAL: "0" ["0"-"7"]((["0"-"7","_"])*["0"-"7"])? > +| + < #BINARY_LITERAL: "0" ["b","B"] ["0","1"]((["0","1","_"])*["0","1"])? > +| + < FLOATING_POINT_LITERAL: + <DECIMAL_FLOATING_POINT_LITERAL> + | <HEXADECIMAL_FLOATING_POINT_LITERAL> + > +| + < #DECIMAL_FLOATING_POINT_LITERAL: + <DECIMAL_LITERAL> "." (<DECIMAL_LITERAL>)? (<DECIMAL_EXPONENT>)? (["f","F","d","D"])? + | "." <DECIMAL_LITERAL> (<DECIMAL_EXPONENT>)? (["f","F","d","D"])? + | <DECIMAL_LITERAL> <DECIMAL_EXPONENT> (["f","F","d","D"])? + | <DECIMAL_LITERAL> (<DECIMAL_EXPONENT>)? ["f","F","d","D"] + > +| + < #DECIMAL_EXPONENT: ["e","E"] (["+","-"])? (<DECIMAL_LITERAL>)+ > +| + < #HEXADECIMAL_FLOATING_POINT_LITERAL: + <HEX_LITERAL> (".")? <HEXADECIMAL_EXPONENT> (["f","F","d","D"])? + | "0" ["x","X"] (<HEX_DIGITS>)? "." <HEX_DIGITS> <HEXADECIMAL_EXPONENT> (["f","F","d","D"])? + > +| + < #HEXADECIMAL_EXPONENT: ["p","P"] (["+","-"])? <DECIMAL_LITERAL> > +| + < #HEX_DIGITS: ["0"-"9","a"-"f","A"-"F"]((["0"-"9","a"-"f","A"-"F","_"])*["0"-"9","a"-"f","A"-"F"])? > +| + < #UNICODE_ESCAPE: + "\\u" + ["0"-"9","A"-"F","a"-"f"] + ["0"-"9","A"-"F","a"-"f"] + ["0"-"9","A"-"F","a"-"f"] + ["0"-"9","A"-"F","a"-"f"] > +| + < CHARACTER_LITERAL: + "'" + ( (~["'","\\","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + | <UNICODE_ESCAPE> + ) + "'" + > +| + < STRING_LITERAL: + "\"" + ( (~["\"","\\","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + | ("\\u" + ["0"-"9","A"-"F","a"-"f"] + ["0"-"9","A"-"F","a"-"f"] + ["0"-"9","A"-"F","a"-"f"] + ["0"-"9","A"-"F","a"-"f"] + ) + )* + "\"" + > +} + +/* IDENTIFIERS */ + +TOKEN : +{ + < IDENTIFIER: <LETTER> (<PART_LETTER>)* > +| + < #LETTER: [ + "\u0024", "\u0041"-"\u005a", "\u005f", "\u0061"-"\u007a", "\u00a2"-"\u00a5", "\u00aa", "\u00b5", + "\u00ba", "\u00c0"-"\u00d6", "\u00d8"-"\u00f6", "\u00f8"-"\u02c1", "\u02c6"-"\u02d1", "\u02e0"-"\u02e4", + "\u02ec", "\u02ee", "\u0370"-"\u0374", "\u0376"-"\u0377", "\u037a"-"\u037d", "\u0386", "\u0388"-"\u038a", + "\u038c", "\u038e"-"\u03a1", "\u03a3"-"\u03f5", "\u03f7"-"\u0481", "\u048a"-"\u0527", "\u0531"-"\u0556", + "\u0559", "\u0561"-"\u0587", "\u058f", "\u05d0"-"\u05ea", "\u05f0"-"\u05f2", "\u060b", "\u0620"-"\u064a", + "\u066e"-"\u066f", "\u0671"-"\u06d3", "\u06d5", "\u06e5"-"\u06e6", "\u06ee"-"\u06ef", "\u06fa"-"\u06fc", + "\u06ff", "\u0710", "\u0712"-"\u072f", "\u074d"-"\u07a5", "\u07b1", "\u07ca"-"\u07ea", "\u07f4"-"\u07f5", + "\u07fa", "\u0800"-"\u0815", "\u081a", "\u0824", "\u0828", "\u0840"-"\u0858", "\u08a0", "\u08a2"-"\u08ac", + "\u0904"-"\u0939", "\u093d", "\u0950", "\u0958"-"\u0961", "\u0971"-"\u0977", "\u0979"-"\u097f", + "\u0985"-"\u098c", "\u098f"-"\u0990", "\u0993"-"\u09a8", "\u09aa"-"\u09b0", "\u09b2", "\u09b6"-"\u09b9", + "\u09bd", "\u09ce", "\u09dc"-"\u09dd", "\u09df"-"\u09e1", "\u09f0"-"\u09f3", "\u09fb", "\u0a05"-"\u0a0a", + "\u0a0f"-"\u0a10", "\u0a13"-"\u0a28", "\u0a2a"-"\u0a30", "\u0a32"-"\u0a33", "\u0a35"-"\u0a36", + "\u0a38"-"\u0a39", "\u0a59"-"\u0a5c", "\u0a5e", "\u0a72"-"\u0a74", "\u0a85"-"\u0a8d", "\u0a8f"-"\u0a91", + "\u0a93"-"\u0aa8", "\u0aaa"-"\u0ab0", "\u0ab2"-"\u0ab3", "\u0ab5"-"\u0ab9", "\u0abd", "\u0ad0", + "\u0ae0"-"\u0ae1", "\u0af1", "\u0b05"-"\u0b0c", "\u0b0f"-"\u0b10", "\u0b13"-"\u0b28", "\u0b2a"-"\u0b30", + "\u0b32"-"\u0b33", "\u0b35"-"\u0b39", "\u0b3d", "\u0b5c"-"\u0b5d", "\u0b5f"-"\u0b61", "\u0b71", + "\u0b83", "\u0b85"-"\u0b8a", "\u0b8e"-"\u0b90", "\u0b92"-"\u0b95", "\u0b99"-"\u0b9a", "\u0b9c", + "\u0b9e"-"\u0b9f", "\u0ba3"-"\u0ba4", "\u0ba8"-"\u0baa", "\u0bae"-"\u0bb9", "\u0bd0", "\u0bf9", + "\u0c05"-"\u0c0c", "\u0c0e"-"\u0c10", "\u0c12"-"\u0c28", "\u0c2a"-"\u0c33", "\u0c35"-"\u0c39", + "\u0c3d", "\u0c58"-"\u0c59", "\u0c60"-"\u0c61", "\u0c85"-"\u0c8c", "\u0c8e"-"\u0c90", "\u0c92"-"\u0ca8", + "\u0caa"-"\u0cb3", "\u0cb5"-"\u0cb9", "\u0cbd", "\u0cde", "\u0ce0"-"\u0ce1", "\u0cf1"-"\u0cf2", + "\u0d05"-"\u0d0c", "\u0d0e"-"\u0d10", "\u0d12"-"\u0d3a", "\u0d3d", "\u0d4e", "\u0d60"-"\u0d61", + "\u0d7a"-"\u0d7f", "\u0d85"-"\u0d96", "\u0d9a"-"\u0db1", "\u0db3"-"\u0dbb", "\u0dbd", "\u0dc0"-"\u0dc6", + "\u0e01"-"\u0e30", "\u0e32"-"\u0e33", "\u0e3f"-"\u0e46", "\u0e81"-"\u0e82", "\u0e84", "\u0e87"-"\u0e88", + "\u0e8a", "\u0e8d", "\u0e94"-"\u0e97", "\u0e99"-"\u0e9f", "\u0ea1"-"\u0ea3", "\u0ea5", "\u0ea7", + "\u0eaa"-"\u0eab", "\u0ead"-"\u0eb0", "\u0eb2"-"\u0eb3", "\u0ebd", "\u0ec0"-"\u0ec4", "\u0ec6", + "\u0edc"-"\u0edf", "\u0f00", "\u0f40"-"\u0f47", "\u0f49"-"\u0f6c", "\u0f88"-"\u0f8c", "\u1000"-"\u102a", + "\u103f", "\u1050"-"\u1055", "\u105a"-"\u105d", "\u1061", "\u1065"-"\u1066", "\u106e"-"\u1070", + "\u1075"-"\u1081", "\u108e", "\u10a0"-"\u10c5", "\u10c7", "\u10cd", "\u10d0"-"\u10fa", "\u10fc"-"\u1248", + "\u124a"-"\u124d", "\u1250"-"\u1256", "\u1258", "\u125a"-"\u125d", "\u1260"-"\u1288", "\u128a"-"\u128d", + "\u1290"-"\u12b0", "\u12b2"-"\u12b5", "\u12b8"-"\u12be", "\u12c0", "\u12c2"-"\u12c5", "\u12c8"-"\u12d6", + "\u12d8"-"\u1310", "\u1312"-"\u1315", "\u1318"-"\u135a", "\u1380"-"\u138f", "\u13a0"-"\u13f4", + "\u1401"-"\u166c", "\u166f"-"\u167f", "\u1681"-"\u169a", "\u16a0"-"\u16ea", "\u16ee"-"\u16f0", + "\u1700"-"\u170c", "\u170e"-"\u1711", "\u1720"-"\u1731", "\u1740"-"\u1751", "\u1760"-"\u176c", + "\u176e"-"\u1770", "\u1780"-"\u17b3", "\u17d7", "\u17db"-"\u17dc", "\u1820"-"\u1877", "\u1880"-"\u18a8", + "\u18aa", "\u18b0"-"\u18f5", "\u1900"-"\u191c", "\u1950"-"\u196d", "\u1970"-"\u1974", "\u1980"-"\u19ab", + "\u19c1"-"\u19c7", "\u1a00"-"\u1a16", "\u1a20"-"\u1a54", "\u1aa7", "\u1b05"-"\u1b33", "\u1b45"-"\u1b4b", + "\u1b83"-"\u1ba0", "\u1bae"-"\u1baf", "\u1bba"-"\u1be5", "\u1c00"-"\u1c23", "\u1c4d"-"\u1c4f", + "\u1c5a"-"\u1c7d", "\u1ce9"-"\u1cec", "\u1cee"-"\u1cf1", "\u1cf5"-"\u1cf6", "\u1d00"-"\u1dbf", + "\u1e00"-"\u1f15", "\u1f18"-"\u1f1d", "\u1f20"-"\u1f45", "\u1f48"-"\u1f4d", "\u1f50"-"\u1f57", + "\u1f59", "\u1f5b", "\u1f5d", "\u1f5f"-"\u1f7d", "\u1f80"-"\u1fb4", "\u1fb6"-"\u1fbc", "\u1fbe", + "\u1fc2"-"\u1fc4", "\u1fc6"-"\u1fcc", "\u1fd0"-"\u1fd3", "\u1fd6"-"\u1fdb", "\u1fe0"-"\u1fec", + "\u1ff2"-"\u1ff4", "\u1ff6"-"\u1ffc", "\u203f"-"\u2040", "\u2054", "\u2071", "\u207f", "\u2090"-"\u209c", + "\u20a0"-"\u20ba", "\u2102", "\u2107", "\u210a"-"\u2113", "\u2115", "\u2119"-"\u211d", "\u2124", + "\u2126", "\u2128", "\u212a"-"\u212d", "\u212f"-"\u2139", "\u213c"-"\u213f", "\u2145"-"\u2149", + "\u214e", "\u2160"-"\u2188", "\u2c00"-"\u2c2e", "\u2c30"-"\u2c5e", "\u2c60"-"\u2ce4", "\u2ceb"-"\u2cee", + "\u2cf2"-"\u2cf3", "\u2d00"-"\u2d25", "\u2d27", "\u2d2d", "\u2d30"-"\u2d67", "\u2d6f", "\u2d80"-"\u2d96", + "\u2da0"-"\u2da6", "\u2da8"-"\u2dae", "\u2db0"-"\u2db6", "\u2db8"-"\u2dbe", "\u2dc0"-"\u2dc6", + "\u2dc8"-"\u2dce", "\u2dd0"-"\u2dd6", "\u2dd8"-"\u2dde", "\u2e2f", "\u3005"-"\u3007", "\u3021"-"\u3029", + "\u3031"-"\u3035", "\u3038"-"\u303c", "\u3041"-"\u3096", "\u309d"-"\u309f", "\u30a1"-"\u30fa", + "\u30fc"-"\u30ff", "\u3105"-"\u312d", "\u3131"-"\u318e", "\u31a0"-"\u31ba", "\u31f0"-"\u31ff", + "\u3400"-"\u4db5", "\u4e00"-"\u9fcc", "\ua000"-"\ua48c", "\ua4d0"-"\ua4fd", "\ua500"-"\ua60c", + "\ua610"-"\ua61f", "\ua62a"-"\ua62b", "\ua640"-"\ua66e", "\ua67f"-"\ua697", "\ua6a0"-"\ua6ef", + "\ua717"-"\ua71f", "\ua722"-"\ua788", "\ua78b"-"\ua78e", "\ua790"-"\ua793", "\ua7a0"-"\ua7aa", + "\ua7f8"-"\ua801", "\ua803"-"\ua805", "\ua807"-"\ua80a", "\ua80c"-"\ua822", "\ua838", "\ua840"-"\ua873", + "\ua882"-"\ua8b3", "\ua8f2"-"\ua8f7", "\ua8fb", "\ua90a"-"\ua925", "\ua930"-"\ua946", "\ua960"-"\ua97c", + "\ua984"-"\ua9b2", "\ua9cf", "\uaa00"-"\uaa28", "\uaa40"-"\uaa42", "\uaa44"-"\uaa4b", "\uaa60"-"\uaa76", + "\uaa7a", "\uaa80"-"\uaaaf", "\uaab1", "\uaab5"-"\uaab6", "\uaab9"-"\uaabd", "\uaac0", "\uaac2", + "\uaadb"-"\uaadd", "\uaae0"-"\uaaea", "\uaaf2"-"\uaaf4", "\uab01"-"\uab06", "\uab09"-"\uab0e", + "\uab11"-"\uab16", "\uab20"-"\uab26", "\uab28"-"\uab2e", "\uabc0"-"\uabe2", "\uac00"-"\ud7a3", + "\ud7b0"-"\ud7c6", "\ud7cb"-"\ud7fb", "\ud800"-"\udfff", "\uf900"-"\ufa6d", "\ufa70"-"\ufad9", + "\ufb00"-"\ufb06", "\ufb13"-"\ufb17", "\ufb1d", "\ufb1f"-"\ufb28", "\ufb2a"-"\ufb36", "\ufb38"-"\ufb3c", + "\ufb3e", "\ufb40"-"\ufb41", "\ufb43"-"\ufb44", "\ufb46"-"\ufbb1", "\ufbd3"-"\ufd3d", "\ufd50"-"\ufd8f", + "\ufd92"-"\ufdc7", "\ufdf0"-"\ufdfc", "\ufe33"-"\ufe34", "\ufe4d"-"\ufe4f", "\ufe69", "\ufe70"-"\ufe74", + "\ufe76"-"\ufefc", "\uff04", "\uff21"-"\uff3a", "\uff3f", "\uff41"-"\uff5a", "\uff66"-"\uffbe", + "\uffc2"-"\uffc7", "\uffca"-"\uffcf", "\uffd2"-"\uffd7", "\uffda"-"\uffdc", "\uffe0"-"\uffe1", + "\uffe5"-"\uffe6" ] + | <UNICODE_ESCAPE> + > +| + < #PART_LETTER: [ + "\u0000"-"\u0008", "\u000e"-"\u001b", "\u0024", "\u0030"-"\u0039", "\u0041"-"\u005a", "\u005f", + "\u0061"-"\u007a", "\u007f"-"\u009f", "\u00a2"-"\u00a5", "\u00aa", "\u00ad", "\u00b5", "\u00ba", + "\u00c0"-"\u00d6", "\u00d8"-"\u00f6", "\u00f8"-"\u02c1", "\u02c6"-"\u02d1", "\u02e0"-"\u02e4", + "\u02ec", "\u02ee", "\u0300"-"\u0374", "\u0376"-"\u0377", "\u037a"-"\u037d", "\u0386", "\u0388"-"\u038a", + "\u038c", "\u038e"-"\u03a1", "\u03a3"-"\u03f5", "\u03f7"-"\u0481", "\u0483"-"\u0487", "\u048a"-"\u0527", + "\u0531"-"\u0556", "\u0559", "\u0561"-"\u0587", "\u058f", "\u0591"-"\u05bd", "\u05bf", "\u05c1"-"\u05c2", + "\u05c4"-"\u05c5", "\u05c7", "\u05d0"-"\u05ea", "\u05f0"-"\u05f2", "\u0600"-"\u0604", "\u060b", + "\u0610"-"\u061a", "\u0620"-"\u0669", "\u066e"-"\u06d3", "\u06d5"-"\u06dd", "\u06df"-"\u06e8", + "\u06ea"-"\u06fc", "\u06ff", "\u070f"-"\u074a", "\u074d"-"\u07b1", "\u07c0"-"\u07f5", "\u07fa", + "\u0800"-"\u082d", "\u0840"-"\u085b", "\u08a0", "\u08a2"-"\u08ac", "\u08e4"-"\u08fe", "\u0900"-"\u0963", + "\u0966"-"\u096f", "\u0971"-"\u0977", "\u0979"-"\u097f", "\u0981"-"\u0983", "\u0985"-"\u098c", + "\u098f"-"\u0990", "\u0993"-"\u09a8", "\u09aa"-"\u09b0", "\u09b2", "\u09b6"-"\u09b9", "\u09bc"-"\u09c4", + "\u09c7"-"\u09c8", "\u09cb"-"\u09ce", "\u09d7", "\u09dc"-"\u09dd", "\u09df"-"\u09e3", "\u09e6"-"\u09f3", + "\u09fb", "\u0a01"-"\u0a03", "\u0a05"-"\u0a0a", "\u0a0f"-"\u0a10", "\u0a13"-"\u0a28", "\u0a2a"-"\u0a30", + "\u0a32"-"\u0a33", "\u0a35"-"\u0a36", "\u0a38"-"\u0a39", "\u0a3c", "\u0a3e"-"\u0a42", "\u0a47"-"\u0a48", + "\u0a4b"-"\u0a4d", "\u0a51", "\u0a59"-"\u0a5c", "\u0a5e", "\u0a66"-"\u0a75", "\u0a81"-"\u0a83", + "\u0a85"-"\u0a8d", "\u0a8f"-"\u0a91", "\u0a93"-"\u0aa8", "\u0aaa"-"\u0ab0", "\u0ab2"-"\u0ab3", + "\u0ab5"-"\u0ab9", "\u0abc"-"\u0ac5", "\u0ac7"-"\u0ac9", "\u0acb"-"\u0acd", "\u0ad0", "\u0ae0"-"\u0ae3", + "\u0ae6"-"\u0aef", "\u0af1", "\u0b01"-"\u0b03", "\u0b05"-"\u0b0c", "\u0b0f"-"\u0b10", "\u0b13"-"\u0b28", + "\u0b2a"-"\u0b30", "\u0b32"-"\u0b33", "\u0b35"-"\u0b39", "\u0b3c"-"\u0b44", "\u0b47"-"\u0b48", + "\u0b4b"-"\u0b4d", "\u0b56"-"\u0b57", "\u0b5c"-"\u0b5d", "\u0b5f"-"\u0b63", "\u0b66"-"\u0b6f", + "\u0b71", "\u0b82"-"\u0b83", "\u0b85"-"\u0b8a", "\u0b8e"-"\u0b90", "\u0b92"-"\u0b95", "\u0b99"-"\u0b9a", + "\u0b9c", "\u0b9e"-"\u0b9f", "\u0ba3"-"\u0ba4", "\u0ba8"-"\u0baa", "\u0bae"-"\u0bb9", "\u0bbe"-"\u0bc2", + "\u0bc6"-"\u0bc8", "\u0bca"-"\u0bcd", "\u0bd0", "\u0bd7", "\u0be6"-"\u0bef", "\u0bf9", "\u0c01"-"\u0c03", + "\u0c05"-"\u0c0c", "\u0c0e"-"\u0c10", "\u0c12"-"\u0c28", "\u0c2a"-"\u0c33", "\u0c35"-"\u0c39", + "\u0c3d"-"\u0c44", "\u0c46"-"\u0c48", "\u0c4a"-"\u0c4d", "\u0c55"-"\u0c56", "\u0c58"-"\u0c59", + "\u0c60"-"\u0c63", "\u0c66"-"\u0c6f", "\u0c82"-"\u0c83", "\u0c85"-"\u0c8c", "\u0c8e"-"\u0c90", + "\u0c92"-"\u0ca8", "\u0caa"-"\u0cb3", "\u0cb5"-"\u0cb9", "\u0cbc"-"\u0cc4", "\u0cc6"-"\u0cc8", + "\u0cca"-"\u0ccd", "\u0cd5"-"\u0cd6", "\u0cde", "\u0ce0"-"\u0ce3", "\u0ce6"-"\u0cef", "\u0cf1"-"\u0cf2", + "\u0d02"-"\u0d03", "\u0d05"-"\u0d0c", "\u0d0e"-"\u0d10", "\u0d12"-"\u0d3a", "\u0d3d"-"\u0d44", + "\u0d46"-"\u0d48", "\u0d4a"-"\u0d4e", "\u0d57", "\u0d60"-"\u0d63", "\u0d66"-"\u0d6f", "\u0d7a"-"\u0d7f", + "\u0d82"-"\u0d83", "\u0d85"-"\u0d96", "\u0d9a"-"\u0db1", "\u0db3"-"\u0dbb", "\u0dbd", "\u0dc0"-"\u0dc6", + "\u0dca", "\u0dcf"-"\u0dd4", "\u0dd6", "\u0dd8"-"\u0ddf", "\u0df2"-"\u0df3", "\u0e01"-"\u0e3a", + "\u0e3f"-"\u0e4e", "\u0e50"-"\u0e59", "\u0e81"-"\u0e82", "\u0e84", "\u0e87"-"\u0e88", "\u0e8a", + "\u0e8d", "\u0e94"-"\u0e97", "\u0e99"-"\u0e9f", "\u0ea1"-"\u0ea3", "\u0ea5", "\u0ea7", "\u0eaa"-"\u0eab", + "\u0ead"-"\u0eb9", "\u0ebb"-"\u0ebd", "\u0ec0"-"\u0ec4", "\u0ec6", "\u0ec8"-"\u0ecd", "\u0ed0"-"\u0ed9", + "\u0edc"-"\u0edf", "\u0f00", "\u0f18"-"\u0f19", "\u0f20"-"\u0f29", "\u0f35", "\u0f37", "\u0f39", + "\u0f3e"-"\u0f47", "\u0f49"-"\u0f6c", "\u0f71"-"\u0f84", "\u0f86"-"\u0f97", "\u0f99"-"\u0fbc", + "\u0fc6", "\u1000"-"\u1049", "\u1050"-"\u109d", "\u10a0"-"\u10c5", "\u10c7", "\u10cd", "\u10d0"-"\u10fa", + "\u10fc"-"\u1248", "\u124a"-"\u124d", "\u1250"-"\u1256", "\u1258", "\u125a"-"\u125d", "\u1260"-"\u1288", + "\u128a"-"\u128d", "\u1290"-"\u12b0", "\u12b2"-"\u12b5", "\u12b8"-"\u12be", "\u12c0", "\u12c2"-"\u12c5", + "\u12c8"-"\u12d6", "\u12d8"-"\u1310", "\u1312"-"\u1315", "\u1318"-"\u135a", "\u135d"-"\u135f", + "\u1380"-"\u138f", "\u13a0"-"\u13f4", "\u1401"-"\u166c", "\u166f"-"\u167f", "\u1681"-"\u169a", + "\u16a0"-"\u16ea", "\u16ee"-"\u16f0", "\u1700"-"\u170c", "\u170e"-"\u1714", "\u1720"-"\u1734", + "\u1740"-"\u1753", "\u1760"-"\u176c", "\u176e"-"\u1770", "\u1772"-"\u1773", "\u1780"-"\u17d3", + "\u17d7", "\u17db"-"\u17dd", "\u17e0"-"\u17e9", "\u180b"-"\u180d", "\u1810"-"\u1819", "\u1820"-"\u1877", + "\u1880"-"\u18aa", "\u18b0"-"\u18f5", "\u1900"-"\u191c", "\u1920"-"\u192b", "\u1930"-"\u193b", + "\u1946"-"\u196d", "\u1970"-"\u1974", "\u1980"-"\u19ab", "\u19b0"-"\u19c9", "\u19d0"-"\u19d9", + "\u1a00"-"\u1a1b", "\u1a20"-"\u1a5e", "\u1a60"-"\u1a7c", "\u1a7f"-"\u1a89", "\u1a90"-"\u1a99", + "\u1aa7", "\u1b00"-"\u1b4b", "\u1b50"-"\u1b59", "\u1b6b"-"\u1b73", "\u1b80"-"\u1bf3", "\u1c00"-"\u1c37", + "\u1c40"-"\u1c49", "\u1c4d"-"\u1c7d", "\u1cd0"-"\u1cd2", "\u1cd4"-"\u1cf6", "\u1d00"-"\u1de6", + "\u1dfc"-"\u1f15", "\u1f18"-"\u1f1d", "\u1f20"-"\u1f45", "\u1f48"-"\u1f4d", "\u1f50"-"\u1f57", + "\u1f59", "\u1f5b", "\u1f5d", "\u1f5f"-"\u1f7d", "\u1f80"-"\u1fb4", "\u1fb6"-"\u1fbc", "\u1fbe", + "\u1fc2"-"\u1fc4", "\u1fc6"-"\u1fcc", "\u1fd0"-"\u1fd3", "\u1fd6"-"\u1fdb", "\u1fe0"-"\u1fec", + "\u1ff2"-"\u1ff4", "\u1ff6"-"\u1ffc", "\u200b"-"\u200f", "\u202a"-"\u202e", "\u203f"-"\u2040", + "\u2054", "\u2060"-"\u2064", "\u206a"-"\u206f", "\u2071", "\u207f", "\u2090"-"\u209c", "\u20a0"-"\u20ba", + "\u20d0"-"\u20dc", "\u20e1", "\u20e5"-"\u20f0", "\u2102", "\u2107", "\u210a"-"\u2113", "\u2115", + "\u2119"-"\u211d", "\u2124", "\u2126", "\u2128", "\u212a"-"\u212d", "\u212f"-"\u2139", "\u213c"-"\u213f", + "\u2145"-"\u2149", "\u214e", "\u2160"-"\u2188", "\u2c00"-"\u2c2e", "\u2c30"-"\u2c5e", "\u2c60"-"\u2ce4", + "\u2ceb"-"\u2cf3", "\u2d00"-"\u2d25", "\u2d27", "\u2d2d", "\u2d30"-"\u2d67", "\u2d6f", "\u2d7f"-"\u2d96", + "\u2da0"-"\u2da6", "\u2da8"-"\u2dae", "\u2db0"-"\u2db6", "\u2db8"-"\u2dbe", "\u2dc0"-"\u2dc6", + "\u2dc8"-"\u2dce", "\u2dd0"-"\u2dd6", "\u2dd8"-"\u2dde", "\u2de0"-"\u2dff", "\u2e2f", "\u3005"-"\u3007", + "\u3021"-"\u302f", "\u3031"-"\u3035", "\u3038"-"\u303c", "\u3041"-"\u3096", "\u3099"-"\u309a", + "\u309d"-"\u309f", "\u30a1"-"\u30fa", "\u30fc"-"\u30ff", "\u3105"-"\u312d", "\u3131"-"\u318e", + "\u31a0"-"\u31ba", "\u31f0"-"\u31ff", "\u3400"-"\u4db5", "\u4e00"-"\u9fcc", "\ua000"-"\ua48c", + "\ua4d0"-"\ua4fd", "\ua500"-"\ua60c", "\ua610"-"\ua62b", "\ua640"-"\ua66f", "\ua674"-"\ua67d", + "\ua67f"-"\ua697", "\ua69f"-"\ua6f1", "\ua717"-"\ua71f", "\ua722"-"\ua788", "\ua78b"-"\ua78e", + "\ua790"-"\ua793", "\ua7a0"-"\ua7aa", "\ua7f8"-"\ua827", "\ua838", "\ua840"-"\ua873", "\ua880"-"\ua8c4", + "\ua8d0"-"\ua8d9", "\ua8e0"-"\ua8f7", "\ua8fb", "\ua900"-"\ua92d", "\ua930"-"\ua953", "\ua960"-"\ua97c", + "\ua980"-"\ua9c0", "\ua9cf"-"\ua9d9", "\uaa00"-"\uaa36", "\uaa40"-"\uaa4d", "\uaa50"-"\uaa59", + "\uaa60"-"\uaa76", "\uaa7a"-"\uaa7b", "\uaa80"-"\uaac2", "\uaadb"-"\uaadd", "\uaae0"-"\uaaef", + "\uaaf2"-"\uaaf6", "\uab01"-"\uab06", "\uab09"-"\uab0e", "\uab11"-"\uab16", "\uab20"-"\uab26", + "\uab28"-"\uab2e", "\uabc0"-"\uabea", "\uabec"-"\uabed", "\uabf0"-"\uabf9", "\uac00"-"\ud7a3", + "\ud7b0"-"\ud7c6", "\ud7cb"-"\ud7fb", "\ud800"-"\udfff", "\uf900"-"\ufa6d", "\ufa70"-"\ufad9", + "\ufb00"-"\ufb06", "\ufb13"-"\ufb17", "\ufb1d"-"\ufb28", "\ufb2a"-"\ufb36", "\ufb38"-"\ufb3c", + "\ufb3e", "\ufb40"-"\ufb41", "\ufb43"-"\ufb44", "\ufb46"-"\ufbb1", "\ufbd3"-"\ufd3d", "\ufd50"-"\ufd8f", + "\ufd92"-"\ufdc7", "\ufdf0"-"\ufdfc", "\ufe00"-"\ufe0f", "\ufe20"-"\ufe26", "\ufe33"-"\ufe34", + "\ufe4d"-"\ufe4f", "\ufe69", "\ufe70"-"\ufe74", "\ufe76"-"\ufefc", "\ufeff", "\uff04", "\uff10"-"\uff19", + "\uff21"-"\uff3a", "\uff3f", "\uff41"-"\uff5a", "\uff66"-"\uffbe", "\uffc2"-"\uffc7", "\uffca"-"\uffcf", + "\uffd2"-"\uffd7", "\uffda"-"\uffdc", "\uffe0"-"\uffe1", "\uffe5"-"\uffe6", "\ufff9"-"\ufffb" ] + | <UNICODE_ESCAPE> + > +} + +/* SEPARATORS */ + +TOKEN : +{ + < LPAREN: "(" > +| < RPAREN: ")" > +| < LBRACE: "{" > +| < RBRACE: "}" > +| < LBRACKET: "[" > +| < RBRACKET: "]" > +| < SEMICOLON: ";" > +| < COMMA: "," > +| < DOT: "." > +| < AT: "@" > +} + +/* OPERATORS */ + +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. */ +TOKEN : +{ + < RUNSIGNEDSHIFT: ">>>" > + { + matchedToken.kind = GT; + matchedToken.realKind = RUNSIGNEDSHIFT; + input_stream.backup(2); + } +| < RSIGNEDSHIFT: ">>" > + { + matchedToken.kind = GT; + matchedToken.realKind = RSIGNEDSHIFT; + input_stream.backup(1); + } +| < GT: ">" > +} + +TOKEN: { <CTRL_Z: "\u001A" /** ctrl+z char **/> } + +/***************************************** + * THE JAVA LANGUAGE GRAMMAR STARTS HERE * + *****************************************/ + +/* + * Program structuring syntax follows. + */ + +CompilationUnit CompilationUnit(): +{ + PackageDeclaration pakage = null; + NodeList<ImportDeclaration> imports = emptyList(); + ImportDeclaration in = null; + NodeList<TypeDeclaration<?>> types = emptyList(); + ModifierHolder modifier; + TypeDeclaration tn = null; + ModuleDeclaration module = null; +} +{ + try { + ( LOOKAHEAD(2)";" )* + [ LOOKAHEAD(PackageDeclaration()) pakage = PackageDeclaration() ] + ( + in = ImportDeclaration() { imports = add(imports, in); } + | + ( + modifier = Modifiers() + ( + tn = ClassOrInterfaceDeclaration(modifier) { types = add(types, tn); } + | + tn = EnumDeclaration(modifier) { types = add(types, tn); } + | + tn = AnnotationTypeDeclaration(modifier) { types = add(types, tn); } + | + module = ModuleDeclaration(modifier) + | + ";" + ) + ) + )* + (<EOF> | <CTRL_Z>) + { return new CompilationUnit(range(token_source.getHomeToken(), token()), pakage, imports, types, module); } + } catch (ParseException e) { + recover(EOF, e); + final CompilationUnit compilationUnit = new CompilationUnit(range(token_source.getHomeToken(), token()), null, new NodeList<ImportDeclaration>(), new NodeList<TypeDeclaration<?>>(), null); + compilationUnit.setParsed(UNPARSABLE); + return compilationUnit; + } +} + +PackageDeclaration PackageDeclaration(): +{ + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); + Name name; + JavaToken begin; +} +{ + annotations = Annotations() + "package" {begin = token();} name = Name() ";" + { return new PackageDeclaration(range(begin, token()), annotations, name); } +} + + +ImportDeclaration ImportDeclaration(): +{ + Name name; + boolean isStatic = false; + boolean isAsterisk = false; + JavaToken begin; +} +{ + "import" {begin = token();} + [ "static" { isStatic = true; } ] + name = Name() + [ "." "*" { isAsterisk = true; } ] ";" + { return new ImportDeclaration(range(begin, token()), name, isStatic, isAsterisk); } +} + +/* + * Modifiers. We match all modifiers in a single rule to reduce the chances of + * syntax errors for simple modifier mistakes. It will also enable us to give + * better error messages. + */ + +ModifierHolder Modifiers(): +{ + JavaToken begin = INVALID; + EnumSet<Modifier> modifiers = EnumSet.noneOf(Modifier.class); + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); + AnnotationExpr ann; +} +{ + ( + LOOKAHEAD(2) + ( + "public" { addModifier(modifiers, Modifier.PUBLIC); begin = orIfInvalid(begin, token()); } + | + "static" { addModifier(modifiers, Modifier.STATIC); begin = orIfInvalid(begin, token()); } + | + "protected" { addModifier(modifiers, Modifier.PROTECTED); begin = orIfInvalid(begin, token()); } + | + "private" { addModifier(modifiers, Modifier.PRIVATE); begin = orIfInvalid(begin, token()); } + | + "final" { addModifier(modifiers, Modifier.FINAL); begin = orIfInvalid(begin, token()); } + | + "abstract" { addModifier(modifiers, Modifier.ABSTRACT); begin = orIfInvalid(begin, token()); } + | + "synchronized" { addModifier(modifiers, Modifier.SYNCHRONIZED); begin = orIfInvalid(begin, token()); } + | + "native" { addModifier(modifiers, Modifier.NATIVE); begin = orIfInvalid(begin, token()); } + | + "transient" { addModifier(modifiers, Modifier.TRANSIENT); begin = orIfInvalid(begin, token()); } + | + "volatile" { addModifier(modifiers, Modifier.VOLATILE); begin = orIfInvalid(begin, token()); } + | + "strictfp" { addModifier(modifiers, Modifier.STRICTFP); begin = orIfInvalid(begin, token()); } + | + "transitive" { addModifier(modifiers, Modifier.TRANSITIVE); begin = orIfInvalid(begin, token()); } + | + "default" { addModifier(modifiers, Modifier.DEFAULT); begin = orIfInvalid(begin, token()); } + | + ann = Annotation() { annotations = add(annotations, ann); begin = orIfInvalid(begin, ann); } + ) + )* + + { + return new ModifierHolder(begin, modifiers, annotations); + } +} + +/* + * Declaration syntax follows. + */ + +ClassOrInterfaceDeclaration ClassOrInterfaceDeclaration(ModifierHolder modifier): +{ + boolean isInterface = false; + SimpleName name; + RangedList<TypeParameter> typePar = new RangedList<TypeParameter>(emptyList()); + NodeList<ClassOrInterfaceType> extList = emptyList(); + NodeList<ClassOrInterfaceType> impList = emptyList(); + NodeList<BodyDeclaration<?>> members = emptyList(); + JavaToken begin = modifier.begin; +} +{ + ( "class" | "interface" { isInterface = true; } ) { begin = orIfInvalid(begin, token()); } + name = SimpleName() + [ typePar = TypeParameters() ] + [ extList = ExtendsList() ] + [ impList = ImplementsList() ] + members = ClassOrInterfaceBody() + + { return new ClassOrInterfaceDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, isInterface, name, typePar.list, extList, impList, members); } +} + +NodeList<ClassOrInterfaceType> ExtendsList(): +{ + boolean extendsMoreThanOne = false; + NodeList<ClassOrInterfaceType> ret = new NodeList<ClassOrInterfaceType>(); + ClassOrInterfaceType cit; +} +{ + "extends" cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } + ( "," cit = AnnotatedClassOrInterfaceType() { ret.add(cit); extendsMoreThanOne = true; } )* + { return ret; } +} + +NodeList<ClassOrInterfaceType> ImplementsList(): +{ + NodeList<ClassOrInterfaceType> ret = new NodeList<ClassOrInterfaceType>(); + ClassOrInterfaceType cit; +} +{ + "implements" cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } + ( "," cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } )* + { return ret; } +} + +EnumDeclaration EnumDeclaration(ModifierHolder modifier): +{ + SimpleName name; + NodeList<ClassOrInterfaceType> impList = emptyList(); + EnumConstantDeclaration entry; + NodeList<EnumConstantDeclaration> entries = emptyList(); + BodyDeclaration<?> member; + NodeList<BodyDeclaration<?>> members = emptyList(); + JavaToken begin = modifier.begin; +} +{ + "enum" { begin = orIfInvalid(begin, token()); } + name = SimpleName() + [ impList = ImplementsList() ] + "{" + [ + entry = EnumConstantDeclaration() { entries.add(entry); } ( LOOKAHEAD(2) "," entry = EnumConstantDeclaration() { entries.add(entry); } )* + ] + [ "," ] + [ + ";" ( + member = ClassOrInterfaceBodyDeclaration() { members = add(members, member); } + | + ";" + )* + ] + "}" + + { return new EnumDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, name, impList, entries, members); } +} + + +EnumConstantDeclaration EnumConstantDeclaration(): +{ + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); + AnnotationExpr ann; + SimpleName name; + NodeList<Expression> args = emptyList(); + NodeList<BodyDeclaration<?>> classBody = emptyList(); + JavaToken begin = INVALID; +} +{ + { } + ( ann = Annotation() { annotations = add(annotations, ann); begin = orIfInvalid(begin, ann); } )* + name = SimpleName() { begin = orIfInvalid(begin, token()); } + [ args = Arguments() ] [ classBody = ClassOrInterfaceBody() ] + { + return new EnumConstantDeclaration(range(begin, token()), annotations, name, args, classBody); + } +} + +/** + * If the list inside the returned RangedList is null, there are no brackets. + * If it is empty, there are brackets, but nothing is in them <>. + * The normal case is that it contains TypeParameters, like <A, B, C>. + */ +RangedList<TypeParameter> TypeParameters(): +{ + RangedList<TypeParameter> ret = new RangedList<TypeParameter>(new NodeList<TypeParameter>()); + TypeParameter tp; + NodeList<AnnotationExpr> annotations; +} +{ + "<" { ret.beginAt(token()); } + annotations = Annotations() + tp = TypeParameter(annotations) { ret.add(tp); annotations = null; } + ( "," + annotations = Annotations() tp = TypeParameter(annotations) { ret.add(tp); annotations = null; } )* + ">" { ret.endAt(token()); } + { return ret; } +} + +TypeParameter TypeParameter(NodeList<AnnotationExpr> annotations): +{ + SimpleName name; + NodeList<ClassOrInterfaceType> typeBound = emptyList(); + JavaToken begin; +} +{ + name = SimpleName() { begin=token(); } [ typeBound = TypeBound() ] + { return new TypeParameter(range(begin, token()), name, typeBound, annotations); } +} + +NodeList<ClassOrInterfaceType> TypeBound(): +{ + NodeList<ClassOrInterfaceType> ret = emptyList(); + ClassOrInterfaceType cit; +} +{ + "extends" cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } + ( "&" cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } )* + { return ret; } +} + +NodeList<BodyDeclaration<?>> ClassOrInterfaceBody(): +{ + NodeList<BodyDeclaration<?>> ret = emptyList(); + BodyDeclaration member; +} +{ + "{" ( + member = ClassOrInterfaceBodyDeclaration() { ret.add(member); } + | + ";" + )* "}" + { return ret; } +} + +BodyDeclaration<?> ClassOrInterfaceBodyDeclaration(): +{ + ModifierHolder modifier; + BodyDeclaration<?> ret; +} +{ + ( + LOOKAHEAD(2) + ret = InitializerDeclaration() + | + // Just get all the modifiers out of the way. If you want to do + // more checks, pass the modifiers down to the member + modifier = Modifiers() + ( + ret = ClassOrInterfaceDeclaration(modifier) + | LOOKAHEAD("enum") + ret = EnumDeclaration(modifier) + | LOOKAHEAD("@" "interface") + ret = AnnotationTypeDeclaration(modifier) + | LOOKAHEAD( [ TypeParameters() ] Identifier() "(" ) + ret = ConstructorDeclaration(modifier) + | LOOKAHEAD( Type() Identifier() ( ArrayBracketPair() )* ( "," | "=" | ";" ) ) + ret = FieldDeclaration(modifier) + | + ret = MethodDeclaration(modifier) + ) + ) + { return ret; } +} + +FieldDeclaration FieldDeclaration(ModifierHolder modifier): +{ + Type partialType; + NodeList<VariableDeclarator> variables = new NodeList<VariableDeclarator>(); + VariableDeclarator val; +} +{ + // Modifiers are already matched in the caller + partialType = Type(emptyList()) val = VariableDeclarator(partialType) { variables.add(val); } + ( "," val = VariableDeclarator(partialType) { variables.add(val); } )* ";" + { + JavaToken begin = orIfInvalid(modifier.begin, partialType); + return new FieldDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, variables); + } +} + +VariableDeclarator VariableDeclarator(Type partialType): +{ + Pair<SimpleName, List<ArrayBracketPair>> id; + Expression init = null; +} +{ + id = VariableDeclaratorId() [ "=" init = VariableInitializer() ] + { return new VariableDeclarator(range(id.a, token()), juggleArrayType(partialType, id.b), id.a, init); } +} + +Pair<SimpleName, List<ArrayBracketPair>> VariableDeclaratorId(): +{ + SimpleName name; + JavaToken begin; + ArrayBracketPair arrayBracketPair; + List<ArrayBracketPair> arrayBracketPairs = new ArrayList(0); +} +{ + name = SimpleName() { begin=token();} ( arrayBracketPair = ArrayBracketPair(Origin.NAME) { arrayBracketPairs=add(arrayBracketPairs, arrayBracketPair); } )* + { + if(storeTokens) { + name.setTokenRange(name.getTokenRange().get().withEnd(token())); + } + return new Pair(name, arrayBracketPairs); + } +} + +Expression VariableInitializer(): +{ + Expression ret; +} +{ + ( + ret = ArrayInitializer() + | + ret = Expression() + ) + { return ret;} +} + +ArrayInitializerExpr ArrayInitializer(): +{ + NodeList<Expression> values = emptyList(); + Expression val; + JavaToken begin; +} +{ + "{" {begin=token();} [ val = VariableInitializer() { values = add(values, val); } ( LOOKAHEAD(2) "," val = VariableInitializer() { values = add(values, val); } )* ] [ "," ] "}" + { return new ArrayInitializerExpr(range(begin, token()), values); } +} + +MethodDeclaration MethodDeclaration(ModifierHolder modifier): +{ + RangedList<TypeParameter> typeParameters = new RangedList<TypeParameter>(emptyList()); + Type type; + SimpleName name; + Pair<NodeList<Parameter>, ReceiverParameter> parameters = new Pair<NodeList<Parameter>, ReceiverParameter>(emptyList(), null); + ArrayBracketPair arrayBracketPair; + List<ArrayBracketPair> arrayBracketPairs = new ArrayList(0); + NodeList<ReferenceType> throws_ = emptyList(); + BlockStmt body = null; + NodeList<AnnotationExpr> annotations; + JavaToken begin = modifier.begin; + ReferenceType throwType; +} +{ + // Modifiers already matched in the caller! + [ typeParameters = TypeParameters() { begin = orIfInvalid(begin, typeParameters.range.getBegin()); } ] + annotations = Annotations() { modifier.annotations.addAll(annotations); begin = orIfInvalid(begin, nodeListBegin(annotations)); } + type = ResultType(emptyList()) { begin = orIfInvalid(begin, type); } + name = SimpleName() parameters = Parameters() ( arrayBracketPair = ArrayBracketPair(Origin.NAME) { arrayBracketPairs=add(arrayBracketPairs, arrayBracketPair); } )* + [ "throws" throwType = AnnotatedReferenceType() { throws_ = add(throws_, throwType); } + ("," throwType = AnnotatedReferenceType() { throws_ = add(throws_, throwType); } )* ] + ( body = Block() | ";" ) + { + type = juggleArrayType(type, arrayBracketPairs); + return new MethodDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, typeParameters.list, type, name, parameters.a, throws_, body, parameters.b); + } +} + +ReferenceType AnnotatedReferenceType(): +{ + NodeList<AnnotationExpr> annotations; + ReferenceType type; +} +{ + annotations = Annotations() + type = ReferenceType(annotations) + { return type; } +} + +Type AnnotatedType(): +{ + NodeList<AnnotationExpr> annotations; + Type type; +} +{ + annotations = Annotations() + type = Type(annotations) + { return type; } +} + +Pair<NodeList<Parameter>, ReceiverParameter> Parameters(): +{ + NodeList<Parameter> ret = emptyList(); + Parameter par; + ReceiverParameter rp = null; +} +{ + "(" + [ + ( LOOKAHEAD(ReceiverParameter()) + rp = ReceiverParameter() + | + par = Parameter() { ret = add(ret, par); } + ) + ( "," par = Parameter() { ret = add(ret, par); } )* + ] + ")" + { return new Pair(ret, rp); } +} + +NodeList<Parameter> LambdaParameters(): +{ + NodeList<Parameter> ret = null; + Parameter par; +} +{ + par = Parameter() { ret = add(ret, par); } ( "," par = Parameter() { ret = add(ret, par); } )* + { return ret; } +} + +NodeList<Parameter> InferredLambdaParameters(): +{ + NodeList<Parameter> ret = null; + Pair<SimpleName, List<ArrayBracketPair>> id; +} +{ + id = VariableDeclaratorId() { ret = add(ret, new Parameter(range(id.a, id.a), EnumSet.noneOf(Modifier.class), emptyList(), new UnknownType(), false, emptyList(), id.a));} + ( + "," id = VariableDeclaratorId() { ret = add(ret, new Parameter(range(id.a, id.a), EnumSet.noneOf(Modifier.class), emptyList(), new UnknownType(), false, emptyList(), id.a)); } + )* + { return ret; } +} + +Parameter Parameter(): +{ + ModifierHolder modifier; + Type partialType; + boolean isVarArg = false; + Pair<SimpleName, List<ArrayBracketPair>> id; + NodeList<AnnotationExpr> varArgAnnotations = emptyList(); +} +{ + modifier = Modifiers() partialType = Type(emptyList()) [ varArgAnnotations = Annotations() "..." { isVarArg = true;} ] + id = VariableDeclaratorId() + { + JavaToken begin = orIfInvalid(modifier.begin, partialType); + return new Parameter(range(begin, token()), modifier.modifiers, modifier.annotations, juggleArrayType(partialType, id.b), isVarArg, varArgAnnotations, id.a); + } +} + +ReceiverParameter ReceiverParameter(): +{ + Type partialType; + Name id; + NodeList<AnnotationExpr> annotations = emptyList(); +} +{ + annotations = Annotations() + partialType = Type(emptyList()) + id = ReceiverParameterId() + { + return new ReceiverParameter(range(partialType, token()), annotations, partialType, id); + } +} + +Name ReceiverParameterId(): +{ + Name ret = null; + NodeList<AnnotationExpr> annotations; +} +{ + [ LOOKAHEAD(Name()) ret = Name() "."] annotations=Annotations() "this" + { return new Name(tokenRange(), ret, token.image, annotations); } +} + +ConstructorDeclaration ConstructorDeclaration(ModifierHolder modifier): +{ + RangedList<TypeParameter> typeParameters = new RangedList<TypeParameter>(emptyList()); + SimpleName name; + Pair<NodeList<Parameter>, ReceiverParameter> parameters = new Pair<NodeList<Parameter>, ReceiverParameter>(emptyList(), null); + NodeList<ReferenceType> throws_ = emptyList(); + ExplicitConstructorInvocationStmt exConsInv = null; + NodeList<Statement> stmts = emptyList(); + JavaToken begin = modifier.begin; + JavaToken blockBegin = INVALID; + ReferenceType throwType; +} +{ + [ typeParameters = TypeParameters() { begin = orIfInvalid(begin, typeParameters.range.getBegin()); } ] + // Modifiers matched in the caller + name = SimpleName() { begin = orIfInvalid(begin, typeParameters.range.getBegin()); begin = orIfInvalid(begin, token()); } parameters = Parameters() [ "throws" throwType = AnnotatedReferenceType() { throws_ = add(throws_, throwType); } + ("," throwType = AnnotatedReferenceType() { throws_ = add(throws_, throwType); })* ] + "{" { blockBegin=token(); } + [ LOOKAHEAD(ExplicitConstructorInvocation()) exConsInv = ExplicitConstructorInvocation() ] + stmts = Statements() + "}" + + { + if (exConsInv != null) { + stmts = prepend(stmts, exConsInv); + } + return new ConstructorDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, typeParameters.list, name, parameters.a, throws_, new BlockStmt(range(blockBegin, token()), stmts), parameters.b); + } +} + +ExplicitConstructorInvocationStmt ExplicitConstructorInvocation(): +{ + boolean isThis = false; + NodeList<Expression> args; + Expression expr = null; + RangedList<Type> typeArgs = new RangedList<Type>(null); + JavaToken begin = INVALID; +} +{ + ( + LOOKAHEAD([ TypeArguments() ] <THIS> "(") + [ typeArgs = TypeArguments() { begin=typeArgs.range.getBegin(); } ] + <THIS> { begin = orIfInvalid(begin, token()); isThis = true; } + args = Arguments() ";" + | + [ + LOOKAHEAD( PrimaryExpressionWithoutSuperSuffix() "." ) + expr = PrimaryExpressionWithoutSuperSuffix() "." + { begin = orIfInvalid(begin, expr); } + ] + [ typeArgs = TypeArguments() { begin = orIfInvalid(begin, typeArgs.range.getBegin()); } ] + <SUPER> {begin = orIfInvalid(begin, token());} + args = Arguments() ";" + ) + { return new ExplicitConstructorInvocationStmt(range(begin, token()),typeArgs.list, isThis, expr, args); } +} + +NodeList<Statement> Statements(): +{ + NodeList<Statement> ret = emptyList(); + Statement stmt; +} +{ + ( LOOKAHEAD(2) stmt = BlockStatement() { ret = add(ret, stmt); } )* + { return ret; } +} + +InitializerDeclaration InitializerDeclaration(): +{ + BlockStmt body; + JavaToken begin = INVALID; + boolean isStatic = false; +} +{ + [ "static" { isStatic = true; begin=token();} ] + body = Block() {begin = orIfInvalid(begin, body);} + { return new InitializerDeclaration(range(begin, token()), isStatic, body); } +} + + +/* + * Type, name and expression syntax follows. + */ + +Type Type(NodeList<AnnotationExpr> annotations): +{ + Type ret; +} +{ + ( + LOOKAHEAD(2) ret = ReferenceType(annotations) + | + ret = PrimitiveType(annotations ) + ) + { return ret; } +} + +ReferenceType ReferenceType(NodeList<AnnotationExpr> annotations): +{ + Type type; + ArrayBracketPair arrayBracketPair; + List<ArrayBracketPair> arrayBracketPairs = new ArrayList(0); +} +{ + ( + type = PrimitiveType(annotations) ( LOOKAHEAD(Annotations() "[") arrayBracketPair = ArrayBracketPair(Origin.TYPE) { arrayBracketPairs=add(arrayBracketPairs, arrayBracketPair); } )+ + | + type = ClassOrInterfaceType(annotations) ( LOOKAHEAD(Annotations() "[") arrayBracketPair = ArrayBracketPair(Origin.TYPE) { arrayBracketPairs=add(arrayBracketPairs, arrayBracketPair); } )* + ) + { return (ReferenceType)wrapInArrayTypes(type, arrayBracketPairs); } +} + +ArrayBracketPair ArrayBracketPair(Origin origin): +{ + NodeList<AnnotationExpr> annotations; + JavaToken begin = INVALID; +} +{ + annotations = Annotations() + "[" { begin = orIfInvalid(begin, token()); } "]" + { return new ArrayBracketPair(range(begin, token()), origin, annotations); } +} + +IntersectionType IntersectionType(NodeList<AnnotationExpr> annotations): +{ + JavaToken begin = INVALID; + ReferenceType elementType; + NodeList<ReferenceType> elements = emptyList(); +} +{ + elementType = ReferenceType(annotations) { begin = orIfInvalid(begin, elementType); elements = add(elements, elementType); } + "&" (elementType = AnnotatedReferenceType() { elements = add(elements, elementType); } )+ + { return new IntersectionType(range(begin, token()), elements); } +} + +ClassOrInterfaceType AnnotatedClassOrInterfaceType(): +{ + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); + ClassOrInterfaceType cit; +} +{ + annotations = Annotations() + cit = ClassOrInterfaceType(annotations) + { return cit; } +} + +ClassOrInterfaceType ClassOrInterfaceType(NodeList<AnnotationExpr> firstAnnotations): +{ + ClassOrInterfaceType ret; + SimpleName name; + RangedList<Type> typeArgs = new RangedList<Type>(null); + JavaToken begin; + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); +} +{ + name = SimpleName() {begin=token();} + [ LOOKAHEAD(2) typeArgs = TypeArguments() ] + { + ret = new ClassOrInterfaceType(range(begin, token()), null, name, typeArgs.list, firstAnnotations); + typeArgs = new RangedList<Type>(null); + } + ( + LOOKAHEAD(2) "." annotations = Annotations() name = SimpleName() + [ LOOKAHEAD(2) typeArgs = TypeArguments() ] + { + ret = new ClassOrInterfaceType(range(begin, token()), ret, name, typeArgs.list, annotations); + typeArgs = new RangedList<Type>(null); + } + )* + { return ret; } +} + +RangedList<Type> TypeArguments(): +{ + RangedList<Type> ret = new RangedList<Type>(new NodeList<Type>()); + Type type; +} +{ + ( + "<" { ret.beginAt(token()); } + (type = TypeArgument() { ret.add(type); } ( "," type = TypeArgument() { ret.add(type); } )*)? + ">" { ret.endAt(token()); } + ) + { return ret; } +} + +Type TypeArgument(): +{ + Type ret; + NodeList<AnnotationExpr> annotations; +} +{ + annotations = Annotations() + ( + ret = Type(annotations) + | + ret = Wildcard(annotations) + ) + { return ret; } +} + +WildcardType Wildcard(NodeList<AnnotationExpr> firstAnnotations): +{ + ReferenceType ext = null; + ReferenceType sup = null; + JavaToken begin; + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); +} +{ + "?" {begin=token();} + [ + "extends" annotations = Annotations() ext = ReferenceType(annotations) + | + "super" annotations = Annotations() sup = ReferenceType(annotations) + ] + { + return new WildcardType(range(begin, token()), ext, sup, firstAnnotations); + } +} + +PrimitiveType PrimitiveType(NodeList<AnnotationExpr> annotations): +{ + PrimitiveType ret; +} +{ +( + "boolean" { ret = new PrimitiveType(tokenRange(), PrimitiveType.Primitive.BOOLEAN, annotations); } +| + "char" { ret = new PrimitiveType(tokenRange(), PrimitiveType.Primitive.CHAR, annotations); } +| + "byte" { ret = new PrimitiveType(tokenRange(), PrimitiveType.Primitive.BYTE, annotations); } +| + "short" { ret = new PrimitiveType(tokenRange(), PrimitiveType.Primitive.SHORT, annotations); } +| + "int" { ret = new PrimitiveType(tokenRange(), PrimitiveType.Primitive.INT, annotations); } +| + "long" { ret = new PrimitiveType(tokenRange(), PrimitiveType.Primitive.LONG, annotations); } +| + "float" { ret = new PrimitiveType(tokenRange(), PrimitiveType.Primitive.FLOAT, annotations); } +| + "double" { ret = new PrimitiveType(tokenRange(), PrimitiveType.Primitive.DOUBLE, annotations); } +) +{ return ret; } +} + +Type ResultType(NodeList<AnnotationExpr> annotations): +{ + Type ret; +} +{ + ( + "void" { ret = new VoidType(tokenRange()); } + | + ret = Type(annotations) + ) + { return ret; } +} + +Name Name(): +/* + * A lookahead is required below since "Name" can be followed + * by a ".*" when used in the context of an "ImportDeclaration". + */ +{ + Name ret; + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); +} +{ + annotations=Annotations() Identifier() { ret = new Name(tokenRange(), null, token.image, annotations); } + ( LOOKAHEAD("." Annotations() Identifier()) + "." annotations=Annotations() Identifier() { ret = new Name(range(ret, token()), ret, token.image, annotations); } )* + { return ret; } +} + +SimpleName SimpleName(): +{ + SimpleName ret; +} +{ + Identifier() { ret = new SimpleName(tokenRange(), token.image); } + { return ret; } +} + + +String Identifier(): +{ + String ret; +} +{ + // Make sure the module info keywords don't interfere with normal Java parsing by matching them as normal identifiers. + (<MODULE> | <REQUIRES> | <TO> | <WITH> | <OPEN> | <OPENS> | <USES> | <EXPORTS> | <PROVIDES> | <TRANSITIVE> | + // Make sure older Java versions parse + <ENUM> | <STRICTFP> | + // An actual plain old identifier + <IDENTIFIER>) { ret = token.image; setTokenKind(IDENTIFIER);} + { return ret; } +} + +/* + * Expression syntax follows. + */ + +Expression 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. This is caught by a validation after parsing. + */ +{ + Expression ret; + AssignExpr.Operator op; + Expression value; + Statement lambdaBody = null; + RangedList<Type> typeArgs = new RangedList<Type>(null); +} +{ + ret = ConditionalExpression() + [ + ( LOOKAHEAD(2) + op = AssignmentOperator() value = Expression() { ret = new AssignExpr(range(ret, token()), ret, value, op); } + | + "->" lambdaBody = LambdaBody() + { + if (ret instanceof CastExpr) { + ret = generateLambda(ret, lambdaBody); + } else if (ret instanceof ConditionalExpr) { + ConditionalExpr ce = (ConditionalExpr) ret; + if(ce.getElseExpr() != null) { + ce.setElseExpr(generateLambda(ce.getElseExpr(), lambdaBody)); + } + } else { + ret = generateLambda(ret, lambdaBody); + } + } + | + "::" [typeArgs = TypeArguments() ] (Identifier() | "new") { ret = new MethodReferenceExpr(range(ret, token()), ret, typeArgs.list, token.image); } + ) + ] + + { return ret; } +} + +AssignExpr.Operator AssignmentOperator(): +{ + AssignExpr.Operator ret; +} +{ + ( + "=" { ret = AssignExpr.Operator.ASSIGN; } + | "*=" { ret = AssignExpr.Operator.MULTIPLY; } + | "/=" { ret = AssignExpr.Operator.DIVIDE; } + | "%=" { ret = AssignExpr.Operator.REMAINDER; } + | "+=" { ret = AssignExpr.Operator.PLUS; } + | "-=" { ret = AssignExpr.Operator.MINUS; } + | "<<=" { ret = AssignExpr.Operator.LEFT_SHIFT; } + | ">>=" { ret = AssignExpr.Operator.SIGNED_RIGHT_SHIFT; } + | ">>>=" { ret = AssignExpr.Operator.UNSIGNED_RIGHT_SHIFT; } + | "&=" { ret = AssignExpr.Operator.BINARY_AND; } + | "^=" { ret = AssignExpr.Operator.XOR; } + | "|=" { ret = AssignExpr.Operator.BINARY_OR; } + ) + { return ret; } +} + +Expression ConditionalExpression(): +{ + Expression ret; + Expression left; + Expression right; +} +{ + ret = ConditionalOrExpression() + [ "?" left = Expression() ":" right = ConditionalExpression() { ret = new ConditionalExpr(range(ret, token()), ret, left, right); } ] + { return ret; } +} + +Expression ConditionalOrExpression(): +{ + Expression ret; + Expression right; +} +{ + ret = ConditionalAndExpression() ( "||" right = ConditionalAndExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.OR); } )* + { return ret; } +} + +Expression ConditionalAndExpression(): +{ + Expression ret; + Expression right; +} +{ + ret = InclusiveOrExpression() ( "&&" right = InclusiveOrExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.AND); } )* + { return ret; } +} + +Expression InclusiveOrExpression(): +{ + Expression ret; + Expression right; +} +{ + ret = ExclusiveOrExpression() ( "|" right = ExclusiveOrExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.BINARY_OR); } )* + { return ret; } +} + +Expression ExclusiveOrExpression(): +{ + Expression ret; + Expression right; +} +{ + ret = AndExpression() ( "^" right = AndExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.XOR); } )* + { return ret; } +} + +Expression AndExpression(): +{ + Expression ret; + Expression right; +} +{ + ret = EqualityExpression() ( "&" right = EqualityExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.BINARY_AND); } )* + { return ret; } +} + +Expression EqualityExpression(): +{ + Expression ret; + Expression right; + BinaryExpr.Operator op; +} +{ + ret = InstanceOfExpression() + ( + ( "==" { op = BinaryExpr.Operator.EQUALS; } | + "!=" { op = BinaryExpr.Operator.NOT_EQUALS; } + ) right = InstanceOfExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, op); } + )* + { return ret; } +} + +Expression InstanceOfExpression(): +{ + Expression ret; + ReferenceType type; + NodeList<AnnotationExpr> annotations; +} +{ + ret = RelationalExpression() [ "instanceof" type = AnnotatedReferenceType() { + ret = new InstanceOfExpr(range(ret, token()), ret, type); + } ] + { return ret; } +} + +Expression RelationalExpression(): +{ + Expression ret; + Expression right; + BinaryExpr.Operator op; +} +{ + ret = ShiftExpression() + ( + ( "<" { op = BinaryExpr.Operator.LESS; } | + ">" { op = BinaryExpr.Operator.GREATER; } | + "<=" { op = BinaryExpr.Operator.LESS_EQUALS; } | + ">=" { op = BinaryExpr.Operator.GREATER_EQUALS; } + ) right = ShiftExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, op); } + )* + { return ret; } +} + +Expression ShiftExpression(): +{ + Expression ret; + Expression right; + BinaryExpr.Operator op; +} +{ + ret = AdditiveExpression() + ( + ( "<<" { op = BinaryExpr.Operator.LEFT_SHIFT; } | + RSIGNEDSHIFT() { op = BinaryExpr.Operator.SIGNED_RIGHT_SHIFT; } | + RUNSIGNEDSHIFT() { op = BinaryExpr.Operator.UNSIGNED_RIGHT_SHIFT; } + ) right = AdditiveExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, op); } + )* + { return ret; } +} + +Expression AdditiveExpression(): +{ + Expression ret; + Expression right; + BinaryExpr.Operator op; +} +{ + ret = MultiplicativeExpression() + ( + ( "+" { op = BinaryExpr.Operator.PLUS; } | + "-" { op = BinaryExpr.Operator.MINUS; } + ) right = MultiplicativeExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, op); } + )* + { return ret; } +} + +Expression MultiplicativeExpression(): +{ + Expression ret; + Expression right; + BinaryExpr.Operator op; +} +{ + ret = UnaryExpression() + ( + ( "*" { op = BinaryExpr.Operator.MULTIPLY; } | + "/" { op = BinaryExpr.Operator.DIVIDE; } | + "%" { op = BinaryExpr.Operator.REMAINDER; } + ) right = UnaryExpression() { ret = new BinaryExpr(range(ret, token()), ret, right, op); } + )* + { return ret; } +} + +Expression UnaryExpression(): +{ + Expression ret; + UnaryExpr.Operator op; + JavaToken begin = INVALID; +} +{ + ( + ret = PreIncrementExpression() + | + ret = PreDecrementExpression() + | + ( "+" { op = UnaryExpr.Operator.PLUS; begin=token();} | + "-" { op = UnaryExpr.Operator.MINUS; begin=token();} + ) ret = UnaryExpression() + { + ret = new UnaryExpr(range(begin, token()), ret, op); + } + | + ret = UnaryExpressionNotPlusMinus() + ) + { return ret; } +} + +Expression PreIncrementExpression(): +{ + Expression ret; + JavaToken begin = INVALID; +} +{ + "++" {begin=token();} ret = UnaryExpression() { ret = new UnaryExpr(range(begin, token()), ret, UnaryExpr.Operator.PREFIX_INCREMENT); } + { return ret; } +} + +Expression PreDecrementExpression(): +{ + Expression ret; + JavaToken begin; +} +{ + "--" {begin=token();} ret = UnaryExpression() { ret = new UnaryExpr(range(begin, token()), ret, UnaryExpr.Operator.PREFIX_DECREMENT); } + { return ret; } +} + +Expression UnaryExpressionNotPlusMinus(): +{ + Expression ret; + UnaryExpr.Operator op; + JavaToken begin = INVALID; +} +{ + ( + ( "~" { op = UnaryExpr.Operator.BITWISE_COMPLEMENT; begin=token(); } | + "!" { op = UnaryExpr.Operator.LOGICAL_COMPLEMENT; begin=token(); } + ) ret = UnaryExpression() { ret = new UnaryExpr(range(begin, token()), ret, op); } + | + LOOKAHEAD( CastExpression() ) + ret = CastExpression() + | + ret = PostfixExpression() + ) + { return ret; } +} + +Expression PostfixExpression(): +{ + Expression ret; + UnaryExpr.Operator op; +} +{ + ret = PrimaryExpression() + [ + LOOKAHEAD(2) + ( "++" { op = UnaryExpr.Operator.POSTFIX_INCREMENT; } | + "--" { op = UnaryExpr.Operator.POSTFIX_DECREMENT; } + ) { ret = new UnaryExpr(range(ret, token()), ret, op); } + ] + { return ret; } +} + +Expression CastExpression(): +{ + Expression ret; + ReferenceType referenceType; + PrimitiveType primitiveType; + JavaToken begin = INVALID; + NodeList<AnnotationExpr> annotations; + NodeList<ReferenceType> typesOfMultiCast = emptyList(); +} +{ + "(" {begin=token();} + annotations = Annotations() + ( + LOOKAHEAD(2) + primitiveType = PrimitiveType(annotations) ")" ret = UnaryExpression() { ret = new CastExpr(range(begin, token()), primitiveType, ret); } + | + referenceType = ReferenceType(annotations) { typesOfMultiCast = add(typesOfMultiCast, referenceType); } + ( "&" referenceType = AnnotatedReferenceType() { + typesOfMultiCast = add(typesOfMultiCast, referenceType); + } + )* + ")" ret = UnaryExpressionNotPlusMinus() { + if (typesOfMultiCast.size() > 1) { + ret = new CastExpr(range(begin, token()), new IntersectionType(range(typesOfMultiCast.get(0), typesOfMultiCast.get(typesOfMultiCast.size() -1)), typesOfMultiCast), ret); + } else { + ret = new CastExpr(range(begin, token()), referenceType, ret); + } + } + ) + { return ret; } +} + + + +Expression PrimaryExpression(): +{ + Expression ret; +} +{ + ret = PrimaryPrefix() ( LOOKAHEAD(2) ret = PrimarySuffix(ret) )* + { return ret; } +} + +Expression PrimaryExpressionWithoutSuperSuffix(): +{ + Expression ret; +} +{ + ret = PrimaryPrefix() ( LOOKAHEAD( PrimarySuffixWithoutSuper(null) ) ret = PrimarySuffixWithoutSuper(ret) )* + { return ret; } +} + +Expression PrimaryPrefix(): +{ + Expression ret = null; + SimpleName name; + RangedList<Type> typeArgs = new RangedList<Type>(null); + NodeList<Expression> args = emptyList(); + NodeList<Parameter> params = emptyList(); + boolean hasArgs = false; + boolean isLambda = false; + Type type; + JavaToken begin; + Parameter p = null; + SimpleName id = null; +} +{ + ( + ret = Literal() + | + <THIS> { ret = new ThisExpr(tokenRange(), null); } + | + <SUPER> { ret = new SuperExpr(tokenRange(), null); } + ( + "." + [ typeArgs = TypeArguments() ] + name = SimpleName() + [ args = Arguments() {hasArgs=true;} ] + { + if (hasArgs) { + ret = new MethodCallExpr(range(ret, token()), ret, typeArgs.list, name, args); + } else { + ret = new FieldAccessExpr(range(ret, token()), ret, emptyList(), name); + } + } + | + "::" [typeArgs = TypeArguments() ] (Identifier() | "new") + { + ret = new MethodReferenceExpr(range(ret, token()), ret, typeArgs.list, token.image); + } + ) + | + "(" {begin=token();} + ( + ")" { ret = new LambdaExpr(range(begin, token()), params, new BlockStmt(), true); } + | LOOKAHEAD(Parameter()) + params = LambdaParameters() ")" { ret = new LambdaExpr(range(begin, token()), params, new BlockStmt(), true); } + | LOOKAHEAD(VariableDeclaratorId() ",") + params = InferredLambdaParameters() ")" { ret = new LambdaExpr(range(begin, token()), params, new BlockStmt(), true); } + | + // This could still be a lambda expression, but this is handled after matching -> elsewhere + ret = Expression() ")" { ret = new EnclosedExpr(range(begin, token()), ret); } + ) + | + ret = AllocationExpression(null) + | + LOOKAHEAD( ResultType() "." "class" ) + type = ResultType(emptyList()) "." "class" { ret = new ClassExpr(range(type, token()), type); } + + | LOOKAHEAD (AnnotatedType() "::" ) + type = AnnotatedType() "::" [typeArgs = TypeArguments() ] (Identifier() | "new") + { + ret = new TypeExpr(range(type, type), type); + ret = new MethodReferenceExpr(range(ret, token()), ret, typeArgs.list, token.image); + } + + | + name = SimpleName() { begin=token(); } + [ args = Arguments() { hasArgs=true; } ] + { + if (hasArgs) { + ret = new MethodCallExpr(range(begin, token()), null, null, name, args); + } else { + ret = new NameExpr(name); + } + } + ) + { return ret; } +} + +Expression PrimarySuffix(Expression scope): +{ + Expression ret; +} +{ + ( + LOOKAHEAD(2) + ret = PrimarySuffixWithoutSuper(scope) + | + "." "super" { ret = new SuperExpr(range(scope, token()), scope); } + ) + { return ret; } +} + +Expression PrimarySuffixWithoutSuper(Expression scope): +{ + Expression ret; + RangedList<Type> typeArgs = new RangedList<Type>(null); + NodeList<Expression> args = emptyList(); + boolean hasArgs = false; + SimpleName name; +} +{ + ( + "." + ( + "this" { ret = new ThisExpr(range(scope, token()), scope); } + | + ret = AllocationExpression(scope) + | + LOOKAHEAD( [ TypeArguments() ] Identifier() ) + [ typeArgs = TypeArguments() ] + name = SimpleName() + [ args = Arguments() {hasArgs=true;} ] + { + if (hasArgs) { + ret = new MethodCallExpr(range(scope, token()), scope, typeArgs.list, name, args); + } else { + ret = new FieldAccessExpr(range(scope, token()), scope, typeArgs.list, name); + } + } + ) + | + "["ret = Expression() "]" { ret = new ArrayAccessExpr(range(scope, token()), scope, ret); } + ) + { return ret; } +} + +Expression Literal(): +{ + Expression ret; +} +{ + ( + <INTEGER_LITERAL> { + ret = new IntegerLiteralExpr(tokenRange(), token.image); + } + | + <LONG_LITERAL> { + ret = new LongLiteralExpr(tokenRange(), token.image); + } + | + <FLOATING_POINT_LITERAL> { + ret = new DoubleLiteralExpr(tokenRange(), token.image); + } + | + <CHARACTER_LITERAL> { + ret = new CharLiteralExpr(tokenRange(), token.image.substring(1, token.image.length()-1)); + } + | + <STRING_LITERAL> { + ret = new StringLiteralExpr(tokenRange(), token.image.substring(1, token.image.length()-1)); + } + | + ret = BooleanLiteral() + | + ret = NullLiteral() + ) + { return ret; } +} + +Expression BooleanLiteral(): +{ + Expression ret; +} +{ + ( + "true" { ret = new BooleanLiteralExpr(tokenRange(), true); } + | + "false" { ret = new BooleanLiteralExpr(tokenRange(), false); } + ) + { return ret; } +} + +Expression NullLiteral(): +{} +{ + "null" + { return new NullLiteralExpr(tokenRange()); } +} + +NodeList<Expression> Arguments(): +{ + NodeList<Expression> ret = emptyList(); +} +{ + "(" [ ret = ArgumentList() ] ")" + { return ret; } +} + +NodeList<Expression> ArgumentList(): +{ + NodeList<Expression> ret = emptyList(); + Expression expr; +} +{ + expr = Expression() { ret.add(expr); } ( "," expr = Expression() { ret.add(expr); } )* + { return ret; } +} + +Expression AllocationExpression(Expression scope): +{ + Expression ret; + Type type; + RangedList<Type> typeArgs = new RangedList<Type>(null); + NodeList<BodyDeclaration<?>> anonymousBody = null; + NodeList<Expression> args; + JavaToken begin = INVALID; + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); +} +{ + "new" { if(scope==null) {begin=token();} else {begin = orIfInvalid(begin, scope);} } + + annotations = Annotations() + ( + type = PrimitiveType(annotations) + ret = ArrayCreation(begin, type) + | + [ typeArgs = TypeArguments() ] + type = AnnotatedClassOrInterfaceType() + ( + ret = ArrayCreation(begin, type) + | + args = Arguments() [ LOOKAHEAD(2) anonymousBody = ClassOrInterfaceBody() ] + { ret = new ObjectCreationExpr(range(begin, token()), scope, (ClassOrInterfaceType) type, typeArgs.list, args, anonymousBody); } + ) + ) + { return ret; } +} + +ArrayCreationExpr ArrayCreation(JavaToken begin, Type type): +{ + Expression expr = null; + ArrayInitializerExpr arrayInitializerExpr = null; + NodeList<Expression> inits = emptyList(); + List<NodeList<AnnotationExpr>> accum = new ArrayList<NodeList<AnnotationExpr>>(); + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); + JavaToken arrayCreationLevelStart = INVALID; + List<TokenRange> levelRanges = new ArrayList<TokenRange>(); +} +{ + ( LOOKAHEAD(2) + annotations = Annotations() + "[" { arrayCreationLevelStart = annotations.isEmpty() ? token() : orIfInvalid(arrayCreationLevelStart, annotations.get(0)); } + (expr = Expression())? { accum = add(accum, annotations); inits = add(inits, expr); annotations=null; expr=null; } + "]" { levelRanges.add(range(arrayCreationLevelStart, token())); } + )+ + (arrayInitializerExpr = ArrayInitializer())? + { + return juggleArrayCreation(range(begin, token()), levelRanges, type, inits, accum, arrayInitializerExpr); + } +} + +/* + * Statement syntax follows. + */ + +Statement Statement(): +{ + Statement ret; +} +{ + try { + ( LOOKAHEAD(2) + ret = LabeledStatement() + | + ret = AssertStatement() + | + ret = Block() + | + ret = EmptyStatement() + | + ret = StatementExpression() + | + ret = SwitchStatement() + | + ret = IfStatement() + | + ret = WhileStatement() + | + ret = DoStatement() + | + ret = ForStatement() + | + ret = BreakStatement() + | + ret = ContinueStatement() + | + ret = ReturnStatement() + | + ret = ThrowStatement() + | + ret = SynchronizedStatement() + | + ret = TryStatement() + ) + { return ret; } + } catch (ParseException e) { + TokenRange errorRange = recover(SEMICOLON, e); + return new UnparsableStmt(errorRange); + } +} + +AssertStmt AssertStatement(): +{ + Expression check; + Expression msg = null; + JavaToken begin; +} +{ + "assert" {begin=token();} check = Expression() [ ":" msg = Expression() ] ";" + { return new AssertStmt(range(begin, token()), check, msg); } +} + +LabeledStmt LabeledStatement(): +{ + SimpleName label; + Statement stmt; + JavaToken begin; +} +{ + label = SimpleName() {begin=token();} ":" stmt = Statement() + { return new LabeledStmt(range(begin, token()), label, stmt); } +} + +BlockStmt Block(): +{ + NodeList<Statement> stmts = emptyList(); + JavaToken begin; +} +{ + "{" {begin=token();} + try { + stmts = Statements() + "}" + { return new BlockStmt(range(begin, token()), stmts); } + } catch (ParseException e) { + recover(RBRACE, e); + BlockStmt block = new BlockStmt(range(begin, token()), new NodeList<Statement>()); + block.setParsed(UNPARSABLE); + return block; + } +} + +/* + * Classes inside body statements can only be abstract or final. The semantic must check it. + */ +Statement BlockStatement(): +{ + Statement ret; + Expression expr; + ClassOrInterfaceDeclaration typeDecl; + ModifierHolder modifier; +} +{ + try { + ( LOOKAHEAD( Modifiers() ("class" | "interface") ) + modifier = Modifiers() + typeDecl = ClassOrInterfaceDeclaration(modifier) { ret = new LocalClassDeclarationStmt(range(typeDecl, token()), typeDecl); } + | LOOKAHEAD(VariableDeclarationExpression() ) + expr = VariableDeclarationExpression() ";" + { ret = new ExpressionStmt(range(expr, token()), expr); } + | + ret = Statement() + ) + { return ret; } + } catch (ParseException e) { + TokenRange errorRange = recover(SEMICOLON, e); + return new UnparsableStmt(errorRange); + } +} + +VariableDeclarationExpr VariableDeclarationExpression(): +{ + ModifierHolder modifier; + Type partialType; + NodeList<VariableDeclarator> variables = new NodeList<VariableDeclarator>(); + VariableDeclarator var; +} +{ + modifier = Modifiers() partialType = Type(emptyList()) var = VariableDeclarator(partialType) { variables.add(var); } ( "," var = VariableDeclarator(partialType) { variables.add(var); } )* + { + JavaToken begin=orIfInvalid(modifier.begin, partialType); + return new VariableDeclarationExpr(range(begin, token()), modifier.modifiers, modifier.annotations, variables); + } +} + +EmptyStmt EmptyStatement(): +{} +{ + ";" + { return new EmptyStmt(tokenRange()); } +} + +Statement LambdaBody(): +{ + Expression expr; + Statement n = null; +} +{ + ( + expr = Expression() { n = new ExpressionStmt(range(expr, token()), expr); } + | + n = Block() + ) + { return n; } +} + +ExpressionStmt 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. + */ +{ + Expression expr; + AssignExpr.Operator op; + Expression value; + RangedList<Type> typeArgs = new RangedList<Type>(null); + Statement lambdaBody; +} +{ + ( LOOKAHEAD(2) + expr = PreIncrementExpression() + | + expr = PreDecrementExpression() + | + expr = PrimaryExpression() + [ + "++" { expr = new UnaryExpr(range(expr, token()), expr, UnaryExpr.Operator.POSTFIX_INCREMENT); } + | + "--" { expr = new UnaryExpr(range(expr, token()), expr, UnaryExpr.Operator.POSTFIX_DECREMENT); } + | + op = AssignmentOperator() value = Expression() { expr = new AssignExpr(range(expr, token()), expr, value, op); } + ] + ) + ";" + { return new ExpressionStmt(range(expr, token()), expr); } +} + +SwitchStmt SwitchStatement(): +{ + Expression selector; + SwitchEntryStmt entry; + NodeList<SwitchEntryStmt> entries = emptyList(); + JavaToken begin; +} +{ + "switch" {begin=token();} "(" selector = Expression() ")" "{" + ( entry = SwitchEntry() { entries = add(entries, entry); } )* + "}" + + { return new SwitchStmt(range(begin, token()), selector, entries); } +} + +SwitchEntryStmt SwitchEntry(): +{ + Expression label = null; + NodeList<Statement> stmts; + JavaToken begin; +} +{ + ( + "case" {begin=token();} label = Expression() + | + "default" {begin=token();} + ) + ":" stmts = Statements() + + { return new SwitchEntryStmt(range(begin, token()),label, stmts); } +} + +IfStmt 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. + */ +{ + Expression condition; + Statement thenStmt; + Statement elseStmt = null; + JavaToken begin; +} +{ + "if" {begin=token();} "(" condition = Expression() ")" {} thenStmt = Statement() [ LOOKAHEAD(1) "else" {} elseStmt = Statement() ] + { + return new IfStmt(range(begin, token()), condition, thenStmt, elseStmt); + } +} + +WhileStmt WhileStatement(): +{ + Expression condition; + Statement body; + JavaToken begin; +} +{ + "while" {begin=token();} "(" condition = Expression() ")" body = Statement() + { return new WhileStmt(range(begin, token()),condition, body); } +} + +DoStmt DoStatement(): +{ + Expression condition; + Statement body; + JavaToken begin; +} +{ + "do" {begin=token();} body = Statement() "while" "(" condition = Expression() ")" ";" + { return new DoStmt(range(begin, token()),body, condition); } +} + +Statement ForStatement(): +{ + VariableDeclarationExpr varExpr = null; + Expression expr = null; + NodeList<Expression> init = emptyList(); + NodeList<Expression> update = emptyList(); + Statement body; + JavaToken begin; +} +{ + "for" {begin=token();} "(" + + ( + LOOKAHEAD(VariableDeclarationExpression() ":") + varExpr = VariableDeclarationExpression() ":" expr = Expression() + | + [ init = ForInit() ] ";" [ expr = Expression() ] ";" [ update = ForUpdate() ] + ) + + ")" body = Statement() + + { + if (varExpr != null) { + return new ForeachStmt(range(begin, token()),varExpr, expr, body); + } + return new ForStmt(range(begin, token()),init, expr, update, body); + } +} + +NodeList<Expression> ForInit(): +{ + NodeList<Expression> ret; + Expression expr; +} +{ + ( + LOOKAHEAD( Modifiers() Type() Identifier() ) + expr = VariableDeclarationExpression() { ret = new NodeList<Expression>(); ret.add(expr); } + | + ret = ExpressionList() + ) + { return ret; } +} + +NodeList<Expression> ExpressionList(): +{ + NodeList<Expression> ret = new NodeList<Expression>(); + Expression expr; +} +{ + expr = Expression() { ret.add(expr); } ( "," expr = Expression() { ret.add(expr); } )* + + { return ret; } +} + +NodeList<Expression> ForUpdate(): +{ + NodeList<Expression> ret; +} +{ + ret = ExpressionList() + + { return ret; } +} + +BreakStmt BreakStatement(): +{ + SimpleName label = null; + JavaToken begin; +} +{ + "break" {begin=token();} [ label = SimpleName() ] ";" + { return new BreakStmt(range(begin, token()), label); } +} + +ContinueStmt ContinueStatement(): +{ + SimpleName label = null; + JavaToken begin; +} +{ + "continue" {begin=token();} [ label = SimpleName() ] ";" + { return new ContinueStmt(range(begin, token()), label); } +} + +ReturnStmt ReturnStatement(): +{ + Expression expr = null; + JavaToken begin; +} +{ + "return" {begin=token();} [ expr = Expression() ] ";" + { return new ReturnStmt(range(begin, token()),expr); } +} + +ThrowStmt ThrowStatement(): +{ + Expression expr; + JavaToken begin; +} +{ + "throw" {begin=token();} expr = Expression() ";" + { return new ThrowStmt(range(begin, token()),expr); } +} + +SynchronizedStmt SynchronizedStatement(): +{ + Expression expr; + BlockStmt body; + JavaToken begin; +} +{ + "synchronized" {begin=token();} "(" expr = Expression() ")" body = Block() + { return new SynchronizedStmt(range(begin, token()),expr, body); } +} + +TryStmt TryStatement(): +{ + NodeList<Expression> resources = emptyList(); + BlockStmt tryBlock; + BlockStmt finallyBlock = null; + NodeList<CatchClause> catchs = emptyList(); + BlockStmt catchBlock; + ModifierHolder exceptModifier; + ReferenceType exceptionType; + NodeList<ReferenceType> exceptionTypes = emptyList(); + Pair<SimpleName, List<ArrayBracketPair>> exceptId; + JavaToken begin; + JavaToken catchBegin; + JavaToken typesBegin; + JavaToken paramEnd; + Type type; +} +{ + "try" {begin=token();} + (resources = ResourceSpecification())? + tryBlock = Block() + ( + LOOKAHEAD(2) + ( + "catch" {catchBegin=token();} + "(" { typesBegin=token(); } + exceptModifier = Modifiers() exceptionType = ReferenceType(emptyList()) { exceptionTypes.add(exceptionType); } + ( "|" exceptionType = AnnotatedReferenceType() { exceptionTypes.add(exceptionType); } )* + exceptId = VariableDeclaratorId() { paramEnd = token(); } + ")" + + catchBlock = Block() + { + if (exceptionTypes.size() > 1) { + type = new UnionType(range(exceptionTypes.get(0), exceptionTypes.get(exceptionTypes.size() - 1)), exceptionTypes); + } else { + type = (Type)exceptionTypes.get(0); + } + Parameter catchType = new Parameter(range(type, paramEnd), exceptModifier.modifiers, exceptModifier.annotations, type, false, emptyList(), exceptId.a); + catchs = add(catchs, new CatchClause(range(catchBegin, token()), catchType, catchBlock)); + exceptionTypes = emptyList(); } + )* + [ "finally" finallyBlock = Block() ] + | + "finally" finallyBlock = Block() + ) + { return new TryStmt(range(begin, token()), resources, tryBlock, catchs, finallyBlock); } +} + + +NodeList<Expression> ResourceSpecification() : +{ + NodeList<Expression> variables; +} +{ + "(" + variables = Resources() + (LOOKAHEAD(2) ";")? + ")" + { return variables; } +} + + +NodeList<Expression> Resources() : +{ + NodeList<Expression> expressions = new NodeList<Expression>(); + Expression expr; +} +{ + expr = Resource() {expressions.add(expr);} (LOOKAHEAD(2) ";" expr = Resource() {expressions.add(expr);})* + { return expressions; } +} + +Expression Resource() : +{ + Expression expr; +} +{ + ( LOOKAHEAD( Modifiers() partialType = Type() VariableDeclarator(partialType)) + /*this is a bit more lenient than we need to be, eg allowing access modifiers like private*/ + expr = VariableDeclarationExpression() + | + expr = PrimaryExpression() + ) + { return expr; } +} + + +/* 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 && + getToken(1).realKind == RUNSIGNEDSHIFT} ) + ">" ">" ">" + ) +} + +void RSIGNEDSHIFT(): +{} +{ + ( LOOKAHEAD({ getToken(1).kind == GT && + getToken(1).realKind == RSIGNEDSHIFT} ) + ">" ">" + ) +} + +/* Annotation syntax follows. */ + +NodeList<AnnotationExpr> Annotations(): +{ + NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); + AnnotationExpr annotation; +} +{ + (LOOKAHEAD("@") annotation = Annotation() {annotations = add(annotations, annotation);} )* + { return annotations; } +} + +AnnotationExpr Annotation(): +{ + AnnotationExpr ret; + Name name; + NodeList<MemberValuePair> pairs = emptyList(); + JavaToken begin; + Expression memberVal; +} +{ + "@" { begin=token(); } name = Name() + ( + LOOKAHEAD( "(" ( Identifier() "=" | ")" )) + "(" [ pairs = MemberValuePairs() ] ")" + { ret = new NormalAnnotationExpr(range(begin, token()), name, pairs); } + | + LOOKAHEAD( "(" ) + "(" memberVal = MemberValue() ")" + { ret = new SingleMemberAnnotationExpr(range(begin, token()), name, memberVal); } + | + { ret = new MarkerAnnotationExpr(range(begin, token()), name); } + ) + { return ret; } +} + +NodeList<MemberValuePair> MemberValuePairs(): +{ + NodeList<MemberValuePair> ret = new NodeList<MemberValuePair>(); + MemberValuePair pair; +} +{ + pair = MemberValuePair() { ret.add(pair); } ( "," pair = MemberValuePair() { ret.add(pair); } )* + { return ret; } +} + +MemberValuePair MemberValuePair(): +{ + SimpleName name; + Expression value; + JavaToken begin; +} +{ + name = SimpleName() { begin=token();} "=" value = MemberValue() + { return new MemberValuePair(range(begin, token()),name, value); } +} + +Expression MemberValue(): +{ + Expression ret; +} +{ + ( LOOKAHEAD("@") + ret = Annotation() + | + ret = MemberValueArrayInitializer() + | + ret = ConditionalExpression() + ) + { return ret; } +} + +Expression MemberValueArrayInitializer(): +{ + NodeList<Expression> ret = emptyList(); + Expression member; + JavaToken begin; +} +{ + "{" {begin=token();} + ( member = MemberValue() { ret.add(member); } ( LOOKAHEAD(2) "," member = MemberValue() { ret.add(member); } )* )? [ "," ] + "}" + { return new ArrayInitializerExpr(range(begin, token()),ret); } +} + + +/* Annotation Types. */ + +AnnotationDeclaration AnnotationTypeDeclaration(ModifierHolder modifier): +{ + SimpleName name; + NodeList<BodyDeclaration<?>> members = emptyList(); + JavaToken begin = modifier.begin; +} +{ + "@" { begin=orIfInvalid(begin, token()); } + "interface" name = SimpleName() members = AnnotationTypeBody() + { + return new AnnotationDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, name, members); + } +} + +NodeList<BodyDeclaration<?>> AnnotationTypeBody(): +{ + NodeList<BodyDeclaration<?>> ret = emptyList(); + BodyDeclaration member; +} +{ + "{" ( + member = AnnotationBodyDeclaration() { ret = addWhenNotNull(ret, member); } + | + ";" + )* "}" + { return ret; } +} + +BodyDeclaration<?> AnnotationBodyDeclaration(): +{ + ModifierHolder modifier; + BodyDeclaration ret; +} +{ + ( + modifier = Modifiers() + ( + LOOKAHEAD(Type() Identifier() "(") + ret = AnnotationTypeMemberDeclaration(modifier) + | + ret = ClassOrInterfaceDeclaration(modifier) + | LOOKAHEAD("enum") + ret = EnumDeclaration(modifier) + | + ret = AnnotationTypeDeclaration(modifier) + | + ret = FieldDeclaration(modifier) + ) + ) + { return ret; } +} + +AnnotationMemberDeclaration AnnotationTypeMemberDeclaration(ModifierHolder modifier): +{ + Type type; + SimpleName name; + Expression defaultVal = null; +} +{ + type = Type(emptyList()) name = SimpleName() "(" ")" [ defaultVal = DefaultValue() ] ";" + + { + JavaToken begin = orIfInvalid(modifier.begin, type); + return new AnnotationMemberDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, type, name, defaultVal); + } +} + +Expression DefaultValue(): +{ + Expression ret; +} +{ + "default" ret = MemberValue() + { return ret; } +} + +/* Module syntax follows */ + + +ModuleStmt ModuleStmt(): +{ + ModifierHolder modifiers; + Name name; + Name tmpName; + NodeList<Name> names=emptyList(); + Type type; + Type tmpType; + NodeList<Type> types=emptyList(); + JavaToken begin; + ModuleStmt stmt=new ModuleRequiresStmt(); + JavaToken transitiveExceptionalToken; +} +{ + ( + // This is a hack for the edge case "requires transitive;" which is supposed to mean "require the module named 'transitive'" + LOOKAHEAD(<REQUIRES> <TRANSITIVE> ";") + <REQUIRES> {begin=token();} <TRANSITIVE> {transitiveExceptionalToken=token(); setTokenKind(IDENTIFIER);} ";" {stmt=new ModuleRequiresStmt(range(begin, token()), EnumSet.noneOf(Modifier.class), new Name(range(transitiveExceptionalToken, transitiveExceptionalToken), null, transitiveExceptionalToken.getText(), new NodeList<AnnotationExpr>()));} + | + <REQUIRES> {begin=token();} modifiers=Modifiers() name=Name() ";" {stmt=new ModuleRequiresStmt(range(begin, token()), modifiers.modifiers, name);} + | + <EXPORTS> {begin=token();} name=Name() [<TO> tmpName=Name() {names.add(tmpName);} ("," tmpName=Name(){names.add(tmpName);} )* ] ";" {stmt=new ModuleExportsStmt(range(begin, token()), name, names);} + | + <OPENS> {begin=token();} name=Name() [<TO> tmpName=Name() {names.add(tmpName);} ("," tmpName=Name(){names.add(tmpName);} )* ] ";" {stmt=new ModuleOpensStmt(range(begin, token()), name, names);} + | + <USES> { begin=token();} type=Type(emptyList()) ";" {stmt=new ModuleUsesStmt(range(begin, token()), type);} + | + <PROVIDES> { begin=token();} type=Type(emptyList()) <WITH> tmpType=Type(emptyList()) {types.add(tmpType);} ("," tmpType=Type(emptyList()) {types.add(tmpType);} )* ";" {stmt=new ModuleProvidesStmt(range(begin, token()), type, types);} + ) + { return stmt; } +} + +ModuleDeclaration ModuleDeclaration(ModifierHolder modifier): +{ + NodeList<ModuleStmt> statements = new NodeList<ModuleStmt>(); + boolean open=false; + ModuleStmt st; + Name name; + JavaToken begin = modifier.begin; +} +{ + [ <OPEN> {open=true; begin = orIfInvalid(begin, token());} ] + <MODULE> { begin = orIfInvalid(begin, token()); } + name = Name() "{" + ( st = ModuleStmt() { statements = add(statements, st); } )* + "}" + { return new ModuleDeclaration(range(begin, token()), modifier.annotations, name, open, statements); } +} + +/* Rules for matching partial inputs. +These rules are needed to properly terminate them - +if we simply use the usual rules, they will ignore everything in the provider +after they matched their desired input, which will lead to unexpected behaviour +*/ + + +BlockStmt BlockParseStart(): +{ BlockStmt ret; } +{ ret = Block() <EOF> { return ret; } } + +Statement BlockStatementParseStart(): +{ Statement ret; } +{ (LOOKAHEAD(3) ret = BlockStatement()|ret = ExplicitConstructorInvocation()) <EOF> { return ret; } } + +ImportDeclaration ImportDeclarationParseStart(): +{ ImportDeclaration ret; } +{ ret = ImportDeclaration() <EOF> { return ret; } } + +Expression ExpressionParseStart(): +{ Expression ret; } +{ ret = Expression() <EOF> { return ret; } } + +AnnotationExpr AnnotationParseStart(): +{ AnnotationExpr ret; } +{ ret = Annotation() <EOF> { return ret; } } + +BodyDeclaration<?> AnnotationBodyDeclarationParseStart(): +{ BodyDeclaration<?> ret; } +{ ret = AnnotationBodyDeclaration() <EOF> { return ret; } } + +BodyDeclaration<?> ClassOrInterfaceBodyDeclarationParseStart(): +{ BodyDeclaration<?> ret; } +{ ret = ClassOrInterfaceBodyDeclaration() <EOF> { return ret; } } + +ClassOrInterfaceType ClassOrInterfaceTypeParseStart(): +{ ClassOrInterfaceType ret; } +{ ret = AnnotatedClassOrInterfaceType() <EOF> { return ret; } } + +Type ResultTypeParseStart(): +{ NodeList<AnnotationExpr> annotations; Type ret; } +{ annotations = Annotations() ret = ResultType(annotations) <EOF> { return ret; } } + +VariableDeclarationExpr VariableDeclarationExpressionParseStart(): +{ VariableDeclarationExpr ret; } +{ ret = VariableDeclarationExpression() <EOF> { return ret; } } + +ExplicitConstructorInvocationStmt ExplicitConstructorInvocationParseStart(): +{ ExplicitConstructorInvocationStmt ret; } +{ ret = ExplicitConstructorInvocation() <EOF> { return ret; } } + +Name NameParseStart(): +{ Name ret; } +{ ret = Name() <EOF> { return ret; } } + +SimpleName SimpleNameParseStart(): +{ SimpleName ret; } +{ ret = SimpleName() <EOF> { return ret; } } + +Parameter ParameterParseStart(): +{ Parameter ret; } +{ ret = Parameter() <EOF> { return ret; } } + +PackageDeclaration PackageDeclarationParseStart(): +{ PackageDeclaration ret; } +{ ret = PackageDeclaration() <EOF> { return ret; } } |