Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
5787 lines (5523 sloc)
180 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2007-2010 Júlio Vilmar Gesser. | |
* Copyright (C) 2011, 2013-2020 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. | |
*/ | |
/* | |
* -- FILE STRUCTURE -- | |
* https://javacc.github.io/javacc/documentation/grammar.html#file-structure | |
* | |
* <pre>{@code | |
* javacc_input ::= javacc_options | |
* "PARSER_BEGIN" "(" <IDENTIFIER> ")" | |
* java_compilation_unit | |
* "PARSER_END" "(" <IDENTIFIER> ")" | |
* ( production )* | |
* <EOF> | |
* }</pre> | |
*/ | |
/* | |
* Available options are spread across: | |
* - https://javacc.github.io/javacc/documentation/cli.html | |
* - https://javacc.github.io/javacc/documentation/grammar.html#options | |
*/ | |
options { | |
COMMON_TOKEN_ACTION = true; | |
ERROR_REPORTING = true; | |
JAVA_TEMPLATE_TYPE = "modern"; // FIXME: Warning: Bad option name "JAVA_TEMPLATE_TYPE". Option setting will be ignored. | |
JDK_VERSION = "1.8"; | |
STATIC = false; | |
TOKEN_EXTENDS = "TokenBase"; | |
} | |
/******************************************************** | |
* This is the template for the generated file. * | |
* GeneratedJavaParser.java * | |
********************************************************/ | |
PARSER_BEGIN(GeneratedJavaParser) | |
/* | |
* Copyright (C) 2007-2010 Júlio Vilmar Gesser. | |
* Copyright (C) 2011, 2013-2020 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 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.*; | |
import static com.github.javaparser.ast.stmt.SwitchEntry.Type.*; | |
@Generated("JavaCC") | |
final class GeneratedJavaParser extends GeneratedJavaParserBase { | |
/* Returns the JavaParser specific token type of the last matched token */ | |
JavaToken token() { | |
return token.javaToken; | |
} | |
/* Returns the last matched token */ | |
Token getCurrentToken() { | |
return token; | |
} | |
/* 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) | |
/* | |
* https://javacc.github.io/javacc/documentation/grammar.html#production | |
* | |
* <pre>{@code | |
* production ::= javacode_production | |
* | regular_expr_production | |
* | bnf_production | |
* | token_manager_decls | |
* }</pre> | |
*/ | |
/*************************************************************************** | |
* TOKEN DEFINITIONS START HERE * | |
* https://javacc.github.io/javacc/documentation/grammar.html#regexpr_kind * | |
* * | |
* <pre>{@code * | |
* regexpr_kind ::= "TOKEN" * | |
* | "SPECIAL_TOKEN" * | |
* | "SKIP" * | |
* | "MORE" * | |
* }</pre> * | |
***************************************************************************/ | |
/* WHITE SPACE */ | |
SPECIAL_TOKEN : | |
{ | |
<SPACE: [ // TODO: Rename (or document) this as `WHITESPACE`? | |
" ", // regular space character | |
"\t", // tab character | |
"\f", // formfeed character | |
"\u0085", // 'NEXT LINE (NEL)' (U+0085) | |
"\u00A0", // 'NO-BREAK SPACE' (U+00A0) | |
"\u1680", // 'OGHAM SPACE MARK' (U+1680) | |
"\u180e", // 'MONGOLIAN VOWEL SEPARATOR' (U+180E) | |
"\u2000", // 'EN QUAD' (U+2000) | |
"\u2001", // 'EM QUAD' (U+2001) | |
"\u2002", // 'EN SPACE' (U+2002) | |
"\u2003", // 'EM SPACE' (U+2003) | |
"\u2004", // 'THREE-PER-EM SPACE' (U+2004) | |
"\u2005", // 'FOUR-PER-EM SPACE' (U+2005) | |
"\u2006", // 'SIX-PER-EM SPACE' (U+2006) | |
"\u2007", // 'FIGURE SPACE' (U+2007) | |
"\u2008", // 'PUNCTUATION SPACE' (U+2008) | |
"\u2009", // 'THIN SPACE' (U+2009) | |
"\u200a", // 'HAIR SPACE' (U+200A) | |
"\u200b", // 'ZERO WIDTH SPACE' (U+200B) | |
"\u200c", // 'ZERO WIDTH NON-JOINER' (U+200C) | |
"\u200d", // 'ZERO WIDTH JOINER' (U+200D) | |
"\u2028", // 'LINE SEPARATOR' (U+2028) // TODO: Investigate this being EOL? | |
"\u2029", // 'PARAGRAPH SEPARATOR' (U+2029) // TODO: Investigate this being EOL? | |
"\u202f", // 'NARROW NO-BREAK SPACE' (U+202F) | |
"\u205f", // 'MEDIUM MATHEMATICAL SPACE' (U+205F) | |
"\u2060", // 'WORD JOINER' (U+2060) | |
"\u3000", // 'IDEOGRAPHIC SPACE' (U+3000) | |
"\ufeff" // 'ZERO WIDTH NO-BREAK SPACE' (U+FEFF) | |
]> | |
| <WINDOWS_EOL : "\r\n"> | |
| <UNIX_EOL: "\n"> | |
| <OLD_MAC_EOL: "\r"> | |
} | |
/* | |
* GeneratedJavaParserTokenManager.java is generated, | |
* based on the template within this TOKEN_MGR_DECLS block. | |
*/ | |
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; | |
private boolean yieldSupported = false; | |
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; | |
} | |
public void setYieldSupported() { | |
yieldSupported = true; | |
} | |
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"])*> | |
} | |
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" > | |
| < RECORD: "record" > | |
| < 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" > | |
| < YIELD: "yield" > {if(!yieldSupported)matchedToken.kind=IDENTIFIER;} | |
| < REQUIRES: "requires" > | |
| < TO: "to" > | |
| < WITH: "with" > | |
| < OPEN: "open" > | |
| < OPENS: "opens" > | |
| < USES: "uses" > | |
| < MODULE: "module" > | |
| < EXPORTS: "exports" > | |
| < PROVIDES: "provides" > | |
| < TRANSITIVE: "transitive" > | |
} | |
/* LITERALS */ | |
TOKEN : | |
{ | |
/** | |
* Note that the JLS treats longs as an int followed by the letter {@code L} (upper or lowercase) | |
* Note that Javaparser differs, as it handles longs separately (as a {@code LONG_LITERAL}) | |
*/ | |
< LONG_LITERAL: | |
<DECIMAL_LITERAL> (["l","L"]) | |
| <HEX_LITERAL> (["l","L"]) | |
| <OCTAL_LITERAL> (["l","L"]) | |
| <BINARY_LITERAL> (["l","L"]) | |
> | |
| | |
/** | |
* Note that the JLS treats longs as an int followed by the letter {@code L} (upper or lowercase) | |
* Note that Javaparser differs, as it handles longs separately (as a {@code LONG_LITERAL}) | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10.1 | |
* <pre>{@code | |
* IntegerLiteral: | |
* DecimalIntegerLiteral | |
* HexIntegerLiteral | |
* OctalIntegerLiteral | |
* BinaryIntegerLiteral | |
* DecimalIntegerLiteral: | |
* DecimalNumeral [IntegerTypeSuffix] | |
* HexIntegerLiteral: | |
* HexNumeral [IntegerTypeSuffix] | |
* OctalIntegerLiteral: | |
* OctalNumeral [IntegerTypeSuffix] | |
* BinaryIntegerLiteral: | |
* BinaryNumeral [IntegerTypeSuffix] | |
* IntegerTypeSuffix: | |
* (one of) | |
* l L | |
* }</pre> | |
* For convenience: | |
* <pre>{@code | |
* DecimalNumeral: | |
* 0 | |
* NonZeroDigit [Digits] | |
* NonZeroDigit Underscores Digits | |
* NonZeroDigit: | |
* (one of) | |
* 1 2 3 4 5 6 7 8 9 | |
* Digits: | |
* Digit | |
* Digit [DigitsAndUnderscores] Digit | |
* Digit: | |
* 0 | |
* NonZeroDigit | |
* DigitsAndUnderscores: | |
* DigitOrUnderscore {DigitOrUnderscore} | |
* DigitOrUnderscore: | |
* Digit | |
* _ | |
* Underscores: | |
* _ {_} | |
* }</pre> | |
* For convenience: | |
* <pre>{@code | |
* HexNumeral: | |
* 0 x HexDigits | |
* 0 X HexDigits | |
* HexDigits: | |
* HexDigit | |
* HexDigit [HexDigitsAndUnderscores] HexDigit | |
* HexDigit: | |
* (one of) | |
* 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F | |
* HexDigitsAndUnderscores: | |
* HexDigitOrUnderscore {HexDigitOrUnderscore} | |
* HexDigitOrUnderscore: | |
* HexDigit | |
* _ | |
* }</pre> | |
* For convenience: | |
* <pre>{@code | |
* OctalNumeral: | |
* 0 OctalDigits | |
* 0 Underscores OctalDigits | |
* OctalDigits: | |
* OctalDigit | |
* OctalDigit [OctalDigitsAndUnderscores] OctalDigit | |
* OctalDigit: | |
* (one of) | |
* 0 1 2 3 4 5 6 7 | |
* OctalDigitsAndUnderscores: | |
* OctalDigitOrUnderscore {OctalDigitOrUnderscore} | |
* OctalDigitOrUnderscore: | |
* OctalDigit | |
* _ | |
* }</pre> | |
* For convenience: | |
* <pre>{@code | |
* BinaryNumeral: | |
* 0 b BinaryDigits | |
* 0 B BinaryDigits | |
* BinaryDigits: | |
* BinaryDigit | |
* BinaryDigit [BinaryDigitsAndUnderscores] BinaryDigit | |
* BinaryDigit: | |
* (one of) | |
* 0 1 | |
* BinaryDigitsAndUnderscores: | |
* BinaryDigitOrUnderscore {BinaryDigitOrUnderscore} | |
* BinaryDigitOrUnderscore: | |
* BinaryDigit | |
* _ | |
* }</pre> | |
*/ | |
< 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"])? > | |
| | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10.2 | |
* <pre>{@code | |
* FloatingPointLiteral: | |
* DecimalFloatingPointLiteral | |
* HexadecimalFloatingPointLiteral | |
* DecimalFloatingPointLiteral: | |
* Digits . [Digits] [ExponentPart] [FloatTypeSuffix] | |
* . Digits [ExponentPart] [FloatTypeSuffix] | |
* Digits ExponentPart [FloatTypeSuffix] | |
* Digits [ExponentPart] FloatTypeSuffix | |
* ExponentPart: | |
* ExponentIndicator SignedInteger | |
* ExponentIndicator: | |
* (one of) | |
* e E | |
* SignedInteger: | |
* [Sign] Digits | |
* Sign: | |
* (one of) | |
* + - | |
* FloatTypeSuffix: | |
* (one of) | |
* f F d D | |
* }</pre> | |
* <pre>{@code | |
* HexadecimalFloatingPointLiteral: | |
* HexSignificand BinaryExponent [FloatTypeSuffix] | |
* HexSignificand: | |
* HexNumeral [.] | |
* 0 x [HexDigits] . HexDigits | |
* 0 X [HexDigits] . HexDigits | |
* BinaryExponent: | |
* BinaryExponentIndicator SignedInteger | |
* BinaryExponentIndicator: | |
* (one of) | |
* p P | |
* }</pre> | |
*/ | |
< 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"])? > | |
| | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.3 | |
* <pre>{@code | |
* UnicodeInputCharacter: | |
* UnicodeEscape | |
* RawInputCharacter | |
* UnicodeEscape: | |
* \ UnicodeMarker HexDigit HexDigit HexDigit HexDigit | |
* UnicodeMarker: | |
* u {u} | |
* HexDigit: | |
* (one of) | |
* 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F | |
* RawInputCharacter: | |
* any Unicode character | |
* }</pre> | |
*/ | |
< #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"] > | |
| | |
/** | |
* TODO: Verify this. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10.4 | |
* <pre>{@code | |
* CharacterLiteral: | |
* ' SingleCharacter ' | |
* ' EscapeSequence ' | |
* SingleCharacter: | |
* InputCharacter but not ' or \ | |
* }</pre> | |
* <pre>{@code | |
* LineTerminator: | |
* the ASCII LF character, also known as "newline" | |
* the ASCII CR character, also known as "return" | |
* the ASCII CR character followed by the ASCII LF character | |
* InputCharacter: | |
* UnicodeInputCharacter but not CR or LF | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10.7 | |
* <pre>{@code | |
* EscapeSequence: | |
* \ b (backspace BS, Unicode \u0008) | |
* \ s (space SP, Unicode \u0020) | |
* \ t (horizontal tab HT, Unicode \u0009) | |
* \ n (linefeed LF, Unicode \u000a) | |
* \ f (form feed FF, Unicode \u000c) | |
* \ r (carriage return CR, Unicode \u000d) | |
* \ LineTerminator (line continuation, no Unicode representation) | |
* \ " (double quote ", Unicode \u0022) | |
* \ ' (single quote ', Unicode \u0027) | |
* \ \ (backslash \, Unicode \u005c) | |
* OctalEscape (octal value, Unicode \u0000 to \u00ff) | |
* OctalEscape: | |
* \ OctalDigit | |
* \ OctalDigit OctalDigit | |
* \ ZeroToThree OctalDigit OctalDigit | |
* OctalDigit: | |
* (one of) | |
* 0 1 2 3 4 5 6 7 | |
* ZeroToThree: | |
* (one of) | |
* 0 1 2 3 | |
* }</pre> | |
*/ | |
< CHARACTER_LITERAL: | |
"'" | |
// TODO: Could (and the duplicate code in STRING_LITERAL) this be extracted out? | |
( | |
(~["'","\\","\n","\r"]) | |
| | |
// starts off with unicode backslash | |
("\\u005" ["c", "C"] | |
// regular escape sequences | |
(["n","t","b","r","f","\\","'","\""] | |
// escapes another unicode backslash | |
| ("\\u005" ["c", "C"]))) | |
| | |
( // TODO: Could these escape sequences be extracted out? | |
"\\" | |
( | |
["n","t","b","r","f","\\","'","\""] | |
| | |
["0"-"7"] ( ["0"-"7"] )? | |
| | |
["0"-"3"] ["0"-"7"] ["0"-"7"] | |
) | |
) | |
| | |
<UNICODE_ESCAPE> | |
) | |
"'" | |
> | |
| | |
/** | |
* TODO: Verify this. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10.5 | |
* <pre>{@code | |
* StringLiteral: | |
* " {StringCharacter} " | |
* StringCharacter: | |
* InputCharacter but not " or \ | |
* EscapeSequence | |
* }</pre> | |
* <pre>{@code | |
* LineTerminator: | |
* the ASCII LF character, also known as "newline" | |
* the ASCII CR character, also known as "return" | |
* the ASCII CR character followed by the ASCII LF character | |
* InputCharacter: | |
* UnicodeInputCharacter but not CR or LF | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10.7 | |
* <pre>{@code | |
* EscapeSequence: | |
* \ b (backspace BS, Unicode \u0008) | |
* \ s (space SP, Unicode \u0020) | |
* \ t (horizontal tab HT, Unicode \u0009) | |
* \ n (linefeed LF, Unicode \u000a) | |
* \ f (form feed FF, Unicode \u000c) | |
* \ r (carriage return CR, Unicode \u000d) | |
* \ LineTerminator (line continuation, no Unicode representation) | |
* \ " (double quote ", Unicode \u0022) | |
* \ ' (single quote ', Unicode \u0027) | |
* \ \ (backslash \, Unicode \u005c) | |
* OctalEscape (octal value, Unicode \u0000 to \u00ff) | |
* OctalEscape: | |
* \ OctalDigit | |
* \ OctalDigit OctalDigit | |
* \ ZeroToThree OctalDigit OctalDigit | |
* OctalDigit: | |
* (one of) | |
* 0 1 2 3 4 5 6 7 | |
* ZeroToThree: | |
* (one of) | |
* 0 1 2 3 | |
* }</pre> | |
*/ | |
< STRING_LITERAL: | |
"\"" | |
// TODO: Could (and the duplicate code in CHARACTER_LITERAL) this be extracted out? | |
( | |
(~["\"","\\","\n","\r"]) | |
| | |
( // TODO: Could these escape sequences be extracted out? | |
"\\" | |
( | |
["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"] | |
) | |
)* | |
"\"" | |
> | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10.6 | |
* <pre>{@code | |
* TextBlock: | |
* " " " {TextBlockWhiteSpace} LineTerminator {TextBlockCharacter} " " " | |
* TextBlockWhiteSpace: | |
* WhiteSpace but not LineTerminator | |
* TextBlockCharacter: | |
* InputCharacter but not \ | |
* EscapeSequence | |
* LineTerminator | |
* }</pre> | |
* <pre>{@code | |
* WhiteSpace: | |
* the ASCII SP character, also known as "space" | |
* the ASCII HT character, also known as "horizontal tab" | |
* the ASCII FF character, also known as "form feed" | |
* LineTerminator | |
* LineTerminator: | |
* the ASCII LF character, also known as "newline" | |
* the ASCII CR character, also known as "return" | |
* the ASCII CR character followed by the ASCII LF character | |
* InputCharacter: | |
* UnicodeInputCharacter but not CR or LF | |
* UnicodeInputCharacter: | |
* UnicodeEscape | |
* RawInputCharacter | |
* UnicodeEscape: | |
* \ UnicodeMarker HexDigit HexDigit HexDigit HexDigit | |
* RawInputCharacter: | |
* any Unicode character | |
* }</pre> | |
*/ | |
/* TEXT BLOCK LITERAL */ | |
MORE: { <ENTER_TEXT_BLOCK: "\"\"\"" >: IN_TEXT_BLOCK } | |
<IN_TEXT_BLOCK> TOKEN : { <TEXT_BLOCK_LITERAL: "\"\"\"" >: DEFAULT } | |
// Need to recognize an escaped " to prevent it from parsing as "backslash doublequote" - | |
// which might match that doublequote with following doublequotes. | |
<IN_TEXT_BLOCK> MORE :{ <TEXT_BLOCK_CONTENT: ( "\\" "\"" | ~[] ) > } | |
/* 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", "\u037f", "\u0386", | |
"\u0388"-"\u038a", "\u038c", "\u038e"-"\u03a1", "\u03a3"-"\u03f5", "\u03f7"-"\u0481", "\u048a"-"\u052f", | |
"\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", "\u0860"-"\u086a", "\u08a0"-"\u08b4", "\u08b6"-"\u08bd", "\u0904"-"\u0939", | |
"\u093d", "\u0950", "\u0958"-"\u0961", "\u0971"-"\u0980", "\u0985"-"\u098c", "\u098f"-"\u0990", | |
"\u0993"-"\u09a8", "\u09aa"-"\u09b0", "\u09b2", "\u09b6"-"\u09b9", "\u09bd", "\u09ce", "\u09dc"-"\u09dd", | |
"\u09df"-"\u09e1", "\u09f0"-"\u09f3", "\u09fb"-"\u09fc", "\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", "\u0af9", "\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"-"\u0c39", "\u0c3d", "\u0c58"-"\u0c5a", | |
"\u0c60"-"\u0c61", "\u0c80", "\u0c85"-"\u0c8c", "\u0c8e"-"\u0c90", "\u0c92"-"\u0ca8", "\u0caa"-"\u0cb3", | |
"\u0cb5"-"\u0cb9", "\u0cbd", "\u0cde", "\u0ce0"-"\u0ce1", "\u0cf1"-"\u0cf2", "\u0d05"-"\u0d0c", | |
"\u0d0e"-"\u0d10", "\u0d12"-"\u0d3a", "\u0d3d", "\u0d4e", "\u0d54"-"\u0d56", "\u0d5f"-"\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"-"\u13f5", | |
"\u13f8"-"\u13fd", "\u1401"-"\u166c", "\u166f"-"\u167f", "\u1681"-"\u169a", "\u16a0"-"\u16ea", | |
"\u16ee"-"\u16f8", "\u1700"-"\u170c", "\u170e"-"\u1711", "\u1720"-"\u1731", "\u1740"-"\u1751", | |
"\u1760"-"\u176c", "\u176e"-"\u1770", "\u1780"-"\u17b3", "\u17d7", "\u17db"-"\u17dc", "\u1820"-"\u1877", | |
"\u1880"-"\u1884", "\u1887"-"\u18a8", "\u18aa", "\u18b0"-"\u18f5", "\u1900"-"\u191e", "\u1950"-"\u196d", | |
"\u1970"-"\u1974", "\u1980"-"\u19ab", "\u19b0"-"\u19c9", "\u1a00"-"\u1a16", "\u1a20"-"\u1a54", | |
"\u1aa7", "\u1b05"-"\u1b33", "\u1b45"-"\u1b4b", "\u1b83"-"\u1ba0", "\u1bae"-"\u1baf", "\u1bba"-"\u1be5", | |
"\u1c00"-"\u1c23", "\u1c4d"-"\u1c4f", "\u1c5a"-"\u1c7d", "\u1c80"-"\u1c88", "\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"-"\u20bf", "\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"-"\u312e", "\u3131"-"\u318e", | |
"\u31a0"-"\u31ba", "\u31f0"-"\u31ff", "\u3400"-"\u4db5", "\u4e00"-"\u9fea", "\ua000"-"\ua48c", | |
"\ua4d0"-"\ua4fd", "\ua500"-"\ua60c", "\ua610"-"\ua61f", "\ua62a"-"\ua62b", "\ua640"-"\ua66e", | |
"\ua67f"-"\ua69d", "\ua6a0"-"\ua6ef", "\ua717"-"\ua71f", "\ua722"-"\ua788", "\ua78b"-"\ua7ae", | |
"\ua7b0"-"\ua7b7", "\ua7f7"-"\ua801", "\ua803"-"\ua805", "\ua807"-"\ua80a", "\ua80c"-"\ua822", | |
"\ua838", "\ua840"-"\ua873", "\ua882"-"\ua8b3", "\ua8f2"-"\ua8f7", "\ua8fb", "\ua8fd", "\ua90a"-"\ua925", | |
"\ua930"-"\ua946", "\ua960"-"\ua97c", "\ua984"-"\ua9b2", "\ua9cf", "\ua9e0"-"\ua9e4", "\ua9e6"-"\ua9ef", | |
"\ua9fa"-"\ua9fe", "\uaa00"-"\uaa28", "\uaa40"-"\uaa42", "\uaa44"-"\uaa4b", "\uaa60"-"\uaa76", | |
"\uaa7a", "\uaa7e"-"\uaaaf", "\uaab1", "\uaab5"-"\uaab6", "\uaab9"-"\uaabd", "\uaac0", "\uaac2", | |
"\uaadb"-"\uaadd", "\uaae0"-"\uaaea", "\uaaf2"-"\uaaf4", "\uab01"-"\uab06", "\uab09"-"\uab0e", | |
"\uab11"-"\uab16", "\uab20"-"\uab26", "\uab28"-"\uab2e", "\uab30"-"\uab5a", "\uab5c"-"\uab65", | |
"\uab70"-"\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", "\u037f", "\u0386", | |
"\u0388"-"\u038a", "\u038c", "\u038e"-"\u03a1", "\u03a3"-"\u03f5", "\u03f7"-"\u0481", "\u0483"-"\u0487", | |
"\u048a"-"\u052f", "\u0531"-"\u0556", "\u0559", "\u0561"-"\u0587", "\u058f", "\u0591"-"\u05bd", | |
"\u05bf", "\u05c1"-"\u05c2", "\u05c4"-"\u05c5", "\u05c7", "\u05d0"-"\u05ea", "\u05f0"-"\u05f2", | |
"\u0600"-"\u0605", "\u060b", "\u0610"-"\u061a", "\u061c", "\u0620"-"\u0669", "\u066e"-"\u06d3", | |
"\u06d5"-"\u06dd", "\u06df"-"\u06e8", "\u06ea"-"\u06fc", "\u06ff", "\u070f"-"\u074a", "\u074d"-"\u07b1", | |
"\u07c0"-"\u07f5", "\u07fa", "\u0800"-"\u082d", "\u0840"-"\u085b", "\u0860"-"\u086a", "\u08a0"-"\u08b4", | |
"\u08b6"-"\u08bd", "\u08d4"-"\u0963", "\u0966"-"\u096f", "\u0971"-"\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"-"\u09fc", "\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", "\u0af9"-"\u0aff", "\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", "\u0c00"-"\u0c03", "\u0c05"-"\u0c0c", "\u0c0e"-"\u0c10", | |
"\u0c12"-"\u0c28", "\u0c2a"-"\u0c39", "\u0c3d"-"\u0c44", "\u0c46"-"\u0c48", "\u0c4a"-"\u0c4d", | |
"\u0c55"-"\u0c56", "\u0c58"-"\u0c5a", "\u0c60"-"\u0c63", "\u0c66"-"\u0c6f", "\u0c80"-"\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", "\u0d00"-"\u0d03", "\u0d05"-"\u0d0c", "\u0d0e"-"\u0d10", | |
"\u0d12"-"\u0d44", "\u0d46"-"\u0d48", "\u0d4a"-"\u0d4e", "\u0d54"-"\u0d57", "\u0d5f"-"\u0d63", | |
"\u0d66"-"\u0d6f", "\u0d7a"-"\u0d7f", "\u0d82"-"\u0d83", "\u0d85"-"\u0d96", "\u0d9a"-"\u0db1", | |
"\u0db3"-"\u0dbb", "\u0dbd", "\u0dc0"-"\u0dc6", "\u0dca", "\u0dcf"-"\u0dd4", "\u0dd6", "\u0dd8"-"\u0ddf", | |
"\u0de6"-"\u0def", "\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"-"\u13f5", | |
"\u13f8"-"\u13fd", "\u1401"-"\u166c", "\u166f"-"\u167f", "\u1681"-"\u169a", "\u16a0"-"\u16ea", | |
"\u16ee"-"\u16f8", "\u1700"-"\u170c", "\u170e"-"\u1714", "\u1720"-"\u1734", "\u1740"-"\u1753", | |
"\u1760"-"\u176c", "\u176e"-"\u1770", "\u1772"-"\u1773", "\u1780"-"\u17d3", "\u17d7", "\u17db"-"\u17dd", | |
"\u17e0"-"\u17e9", "\u180b"-"\u180e", "\u1810"-"\u1819", "\u1820"-"\u1877", "\u1880"-"\u18aa", | |
"\u18b0"-"\u18f5", "\u1900"-"\u191e", "\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", "\u1ab0"-"\u1abd", | |
"\u1b00"-"\u1b4b", "\u1b50"-"\u1b59", "\u1b6b"-"\u1b73", "\u1b80"-"\u1bf3", "\u1c00"-"\u1c37", | |
"\u1c40"-"\u1c49", "\u1c4d"-"\u1c7d", "\u1c80"-"\u1c88", "\u1cd0"-"\u1cd2", "\u1cd4"-"\u1cf9", | |
"\u1d00"-"\u1df9", "\u1dfb"-"\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", "\u2066"-"\u206f", "\u2071", "\u207f", "\u2090"-"\u209c", "\u20a0"-"\u20bf", | |
"\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"-"\u312e", "\u3131"-"\u318e", | |
"\u31a0"-"\u31ba", "\u31f0"-"\u31ff", "\u3400"-"\u4db5", "\u4e00"-"\u9fea", "\ua000"-"\ua48c", | |
"\ua4d0"-"\ua4fd", "\ua500"-"\ua60c", "\ua610"-"\ua62b", "\ua640"-"\ua66f", "\ua674"-"\ua67d", | |
"\ua67f"-"\ua6f1", "\ua717"-"\ua71f", "\ua722"-"\ua788", "\ua78b"-"\ua7ae", "\ua7b0"-"\ua7b7", | |
"\ua7f7"-"\ua827", "\ua838", "\ua840"-"\ua873", "\ua880"-"\ua8c5", "\ua8d0"-"\ua8d9", "\ua8e0"-"\ua8f7", | |
"\ua8fb", "\ua8fd", "\ua900"-"\ua92d", "\ua930"-"\ua953", "\ua960"-"\ua97c", "\ua980"-"\ua9c0", | |
"\ua9cf"-"\ua9d9", "\ua9e0"-"\ua9fe", "\uaa00"-"\uaa36", "\uaa40"-"\uaa4d", "\uaa50"-"\uaa59", | |
"\uaa60"-"\uaa76", "\uaa7a"-"\uaac2", "\uaadb"-"\uaadd", "\uaae0"-"\uaaef", "\uaaf2"-"\uaaf6", | |
"\uab01"-"\uab06", "\uab09"-"\uab0e", "\uab11"-"\uab16", "\uab20"-"\uab26", "\uab28"-"\uab2e", | |
"\uab30"-"\uab5a", "\uab5c"-"\uab65", "\uab70"-"\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"-"\ufe2f", | |
"\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 */ | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.11 | |
* Twelve tokens, formed from ASCII characters, are the separators (punctuators). | |
* <pre>{@code | |
* Separator: | |
* (one of) | |
* ( ) { } [ ] ; , . ... @ :: | |
* }</pre | |
*/ | |
TOKEN : | |
{ | |
< LPAREN: "(" > | |
| < RPAREN: ")" > | |
| < LBRACE: "{" > | |
| < RBRACE: "}" > | |
| < LBRACKET: "[" > | |
| < RBRACKET: "]" > | |
| < SEMICOLON: ";" > | |
| < COMMA: "," > | |
| < DOT: "." > | |
| < ELLIPSIS: "..." > | |
| < AT: "@" > | |
| < DOUBLECOLON: "::" > | |
} | |
/* OPERATORS */ | |
/** | |
* Note that {@code >}'s need special attention due to generics syntax, thus are listed separately. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.12 | |
* 38 tokens, formed from ASCII characters, are the operators. | |
* <pre>{@code | |
* Separator: | |
* (one of) | |
* = > < ! ~ ? : -> | |
* == >= <= != && || ++ -- | |
* + - * / & | ^ % << >> >>> | |
* += -= *= /= &= |= ^= %= <<= >>= >>>= | |
* }</pre | |
*/ | |
TOKEN : | |
{ | |
< ASSIGN: "=" > | |
// GT - see below | |
| < LT: "<" > | |
| < BANG: "!" > | |
| < TILDE: "~" > | |
| < HOOK: "?" > | |
| < COLON: ":" > | |
| < ARROW: "->" > | |
| < EQ: "==" > | |
| < GE: ">=" > | |
| < LE: "<=" > | |
| < NE: "!=" > | |
| < SC_AND: "&&" > | |
| < SC_OR: "||" > | |
| < INCR: "++" > | |
| < DECR: "--" > | |
| < PLUS: "+" > | |
| < MINUS: "-" > | |
| < STAR: "*" > | |
| < SLASH: "/" > | |
| < BIT_AND: "&" > | |
| < BIT_OR: "|" > | |
| < XOR: "^" > | |
| < REM: "%" > | |
| < LSHIFT: "<<" > | |
// RSIGNEDSHIFT - see below | |
// RUNSIGNEDSHIFT - see below | |
| < PLUSASSIGN: "+=" > | |
| < MINUSASSIGN: "-=" > | |
| < STARASSIGN: "*=" > | |
| < SLASHASSIGN: "/=" > | |
| < ANDASSIGN: "&=" > | |
| < ORASSIGN: "|=" > | |
| < XORASSIGN: "^=" > | |
| < REMASSIGN: "%=" > | |
| < LSHIFTASSIGN: "<<=" > | |
| < RSIGNEDSHIFTASSIGN: ">>=" > | |
| < RUNSIGNEDSHIFTASSIGN: ">>>=" > | |
} | |
/* | |
* Note that {@code >}'s need special attention due to generics syntax, thus are listed separately. | |
* TODO: Investigate (and comment) if the ordering matters, or if it's just that there's a code block associated with the token. | |
.*/ | |
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 * | |
* * | |
* https://javacc.github.io/javacc/documentation/grammar.html#bnf-production * | |
* <pre>{@code * | |
* bnf_production ::= java_access_modifier java_return_type java_identifier "(" java_parameter_list ")" ":" * | |
* java_block * | |
* "{" expansion_choices "}" * | |
* }</pre> * | |
*************************************************************************************************************/ | |
/* | |
* Program structuring syntax follows. | |
*/ | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-7.html#jls-7.3 | |
* <pre>{@code | |
* CompilationUnit: | |
* OrdinaryCompilationUnit | |
* ModularCompilationUnit | |
* OrdinaryCompilationUnit: | |
* [PackageDeclaration] {ImportDeclaration} {TypeDeclaration} | |
* ModularCompilationUnit: | |
* {ImportDeclaration} ModuleDeclaration | |
* }</pre> | |
* Note that {@code TypeDeclaration} is defined in the JLS as a class or interface. | |
* <ul> | |
* <li>A class is defined as a normal class or enum declaration.</li> | |
* <li>An interface declaration is defined as a normal interface or annotation declaration.</li> | |
* </ul> | |
* For that reason, within this grammar, we combine them. | |
* | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-7.html#jls-TypeDeclaration | |
* <pre>{@code | |
* TypeDeclaration: | |
* ClassDeclaration | |
* InterfaceDeclaration | |
* ; | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-ClassDeclaration | |
* <pre>{@code | |
* TypeDeclaration: | |
* ClassDeclaration | |
* InterfaceDeclaration | |
* ; | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-9.html#jls-InterfaceDeclaration | |
* <pre>{@code | |
* InterfaceDeclaration: | |
* NormalInterfaceDeclaration | |
* AnnotationTypeDeclaration | |
* }</pre> | |
*/ | |
public CompilationUnit CompilationUnit(): | |
{ | |
PackageDeclaration packageDeclaration = null; | |
NodeList<ImportDeclaration> imports = emptyNodeList(); | |
ImportDeclaration in = null; | |
NodeList<TypeDeclaration<?>> types = emptyNodeList(); | |
ModifierHolder modifier; | |
TypeDeclaration<?> typeDeclaration = null; | |
ModuleDeclaration module = null; | |
} | |
{ | |
try { | |
( LOOKAHEAD(2)";" )* | |
[ LOOKAHEAD(PackageDeclaration()) packageDeclaration = PackageDeclaration() ] | |
( | |
in = ImportDeclaration() { imports = add(imports, in); } | |
| | |
( | |
modifier = Modifiers() | |
( | |
typeDeclaration = ClassOrInterfaceDeclaration(modifier) { types = add(types, typeDeclaration); } | |
| | |
typeDeclaration = RecordDeclaration(modifier) { types = add(types, typeDeclaration); } | |
| | |
typeDeclaration = EnumDeclaration(modifier) { types = add(types, typeDeclaration); } | |
| | |
typeDeclaration = AnnotationTypeDeclaration(modifier) { types = add(types, typeDeclaration); } | |
| | |
module = ModuleDeclaration(modifier) | |
| | |
";" | |
) | |
) | |
)* | |
(<EOF> | <CTRL_Z>) | |
{ return new CompilationUnit(range(token_source.getHomeToken(), token()), packageDeclaration, 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; | |
} | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-7.html#jls-7.4.1 | |
* <pre>{@code | |
* PackageDeclaration: | |
* {PackageModifier} package Identifier {. Identifier} ; | |
* PackageModifier: | |
* Annotation | |
* }</pre> | |
*/ | |
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); } | |
} | |
/** | |
* Import declaration types are not differentiated in the class hierarchy. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-7.html#jls-7.5 | |
* <pre>{@code | |
* ImportDeclaration: | |
* SingleTypeImportDeclaration | |
* TypeImportOnDemandDeclaration | |
* SingleStaticImportDeclaration | |
* StaticImportOnDemandDeclaration | |
* }</pre> | |
* Note that the JLS terminology "On Demand" and JavaParser terminology "Asterisk" are equivalent | |
* <pre>{@code | |
* SingleTypeImportDeclaration: | |
* import TypeName ; | |
* TypeImportOnDemandDeclaration: | |
* import PackageOrTypeName . * ; | |
* SingleStaticImportDeclaration: | |
* import static TypeName . Identifier ; | |
* StaticImportOnDemandDeclaration: | |
* import static TypeName . * ; | |
* }</pre> | |
*/ | |
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. | |
* Class Modifiers: https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.1.1 | |
* <pre>{@code | |
* ClassModifier: | |
* (one of) | |
* Annotation public protected private | |
* abstract static final strictfp | |
* }</pre> | |
* Field Modifiers: https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.3.1 | |
* <pre>{@code | |
* FieldModifier: | |
* (one of) | |
* Annotation public protected private | |
* static final transient volatile | |
* }</pre> | |
* Method Modifiers: https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.4.3 | |
* <pre>{@code | |
* MethodModifier: | |
* (one of) | |
* Annotation public protected private | |
* abstract static final synchronized native strictfp | |
* }</pre> | |
* Constructor Modifiers: https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.8.3 | |
* <pre>{@code | |
* ConstructorModifier: | |
* (one of) | |
* Annotation public protected private | |
* }</pre> | |
*/ | |
ModifierHolder Modifiers(): | |
{ | |
JavaToken begin = INVALID; | |
NodeList<Modifier> modifiers = new NodeList<Modifier>(); | |
NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); | |
AnnotationExpr ann; | |
} | |
{ | |
( | |
LOOKAHEAD(2) | |
( | |
"public" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PUBLIC)); begin = orIfInvalid(begin, token()); } | |
| | |
"static" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.STATIC)); begin = orIfInvalid(begin, token()); } | |
| | |
"protected" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PROTECTED)); begin = orIfInvalid(begin, token()); } | |
| | |
"private" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PRIVATE)); begin = orIfInvalid(begin, token()); } | |
| | |
"final" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.FINAL)); begin = orIfInvalid(begin, token()); } | |
| | |
"abstract" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.ABSTRACT)); begin = orIfInvalid(begin, token()); } | |
| | |
"synchronized" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.SYNCHRONIZED)); begin = orIfInvalid(begin, token()); } | |
| | |
"native" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.NATIVE)); begin = orIfInvalid(begin, token()); } | |
| | |
"transient" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.TRANSIENT)); begin = orIfInvalid(begin, token()); } | |
| | |
"volatile" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.VOLATILE)); begin = orIfInvalid(begin, token()); } | |
| | |
"strictfp" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.STRICTFP)); begin = orIfInvalid(begin, token()); } | |
| | |
"transitive" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.TRANSITIVE)); begin = orIfInvalid(begin, token()); } | |
| | |
"default" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.DEFAULT)); begin = orIfInvalid(begin, token()); } | |
| | |
ann = Annotation() { annotations = add(annotations, ann); begin = orIfInvalid(begin, ann); } | |
) | |
)* | |
{ | |
return new ModifierHolder(begin, modifiers, annotations); | |
} | |
} | |
/* | |
* Declaration syntax follows. | |
*/ | |
/** | |
* <strong> | |
* Note that this grammar is deliberately permissive. As a result, this grammar allows any combinations of | |
* class/interface and extends/implements (e.g. an interface implementing an interface). | |
* </strong> | |
* Validations of these combinations are handled at the same time as validating language features used. | |
* Also note that JavaParser handles the hierarchy/specialisations of classes, interfaces, and enums differently to the JLS. | |
* <ul> | |
* <li>This {@code ClassOrInterfaceDeclaration} refers to the {@code NormalClassDeclaration} and {@code NormalInterfaceDeclaration},</li> | |
* <li>while {@code AnnotationTypeDeclaration} and {@code EnumDeclaration} are handled separately within this grammar.</li> | |
* </ul> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.1 | |
* <pre>{@code | |
* ClassDeclaration: | |
* NormalClassDeclaration | |
* EnumDeclaration | |
* NormalClassDeclaration: | |
* {ClassModifier} class TypeIdentifier [TypeParameters] [Superclass] [Superinterfaces] ClassBody | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-9.html#jls-9.1 | |
* <pre>{@code | |
* InterfaceDeclaration: | |
* NormalInterfaceDeclaration | |
* AnnotationTypeDeclaration | |
* NormalInterfaceDeclaration: | |
* {InterfaceModifier} interface TypeIdentifier [TypeParameters] [ExtendsInterfaces] InterfaceBody | |
* }</pre> | |
*/ | |
ClassOrInterfaceDeclaration ClassOrInterfaceDeclaration(ModifierHolder modifier): | |
{ | |
boolean isInterface; | |
SimpleName name; | |
RangedList<TypeParameter> typePar = new RangedList<TypeParameter>(emptyNodeList()); | |
NodeList<ClassOrInterfaceType> extList = emptyNodeList(); | |
NodeList<ClassOrInterfaceType> impList = emptyNodeList(); | |
NodeList<BodyDeclaration<?>> members = emptyNodeList(); | |
JavaToken begin = modifier.begin; | |
} | |
{ | |
( | |
"class" { isInterface = false; } | |
| | |
"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); } | |
} | |
/** | |
* https://openjdk.java.net/jeps/395#Java-grammar | |
* <pre>{@code | |
* RecordDeclaration: | |
* {ClassModifier} `record` TypeIdentifier [TypeParameters] | |
* RecordHeader [SuperInterfaces] RecordBody | |
* | |
* RecordHeader: | |
* `(` [RecordComponentList] `)` | |
* | |
* RecordComponentList: | |
* RecordComponent { `,` RecordComponent} | |
* | |
* RecordComponent: | |
* {Annotation} UnannType Identifier | |
* VariableArityRecordComponent | |
* | |
* VariableArityRecordComponent: | |
* {Annotation} UnannType {Annotation} `...` Identifier | |
* | |
* RecordBody: | |
* `{` {RecordBodyDeclaration} `}` | |
* | |
* RecordBodyDeclaration: | |
* ClassBodyDeclaration | |
* CompactConstructorDeclaration | |
* | |
* CompactConstructorDeclaration: | |
* {ConstructorModifier} SimpleTypeName ConstructorBody | |
* }</pre> | |
*/ | |
RecordDeclaration RecordDeclaration(ModifierHolder modifier): | |
{ | |
SimpleName name; | |
Pair<NodeList<Parameter>, ReceiverParameter> parameters; | |
RangedList<TypeParameter> typePar = new RangedList<TypeParameter>(emptyNodeList()); | |
NodeList<ClassOrInterfaceType> impList = emptyNodeList(); | |
NodeList<BodyDeclaration<?>> members = emptyNodeList(); | |
JavaToken begin = modifier.begin; | |
} | |
{ | |
// Note that BlockStatement and ClassOrInterfaceBodyDeclaration have extended lookaheads that should be maintained | |
// Note that `record` is a "restricted identifier", not a keyword - JLS 3.9 has more detail. | |
"record" { begin = orIfInvalid(begin, token()); } | |
name = SimpleName() | |
[ typePar = TypeParameters() ] | |
parameters = Parameters() | |
[ impList = ImplementsList() ] | |
members = RecordBody() | |
{ return new RecordDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, name, parameters.a, typePar.list, impList, members, parameters.b); } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.1.4 | |
* <pre>{@code | |
* Superclass: | |
* extends ClassType | |
* }</pre> | |
* For convenience: | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.3 | |
* <pre>{@code | |
* ClassOrInterfaceType: | |
* ClassType | |
* InterfaceType | |
* ClassType: | |
* {Annotation} TypeIdentifier [TypeArguments] | |
* PackageName . {Annotation} TypeIdentifier [TypeArguments] | |
* ClassOrInterfaceType . {Annotation} TypeIdentifier [TypeArguments] | |
* InterfaceType: | |
* ClassType | |
* }</pre> | |
*/ | |
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; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.1.5 | |
* <pre>{@code | |
* Superinterfaces: | |
* implements InterfaceTypeList | |
* InterfaceTypeList: | |
* InterfaceType {, InterfaceType} | |
* }</pre> | |
* For convenience: | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.3 | |
* <pre>{@code | |
* ClassOrInterfaceType: | |
* ClassType | |
* InterfaceType | |
* ClassType: | |
* {Annotation} TypeIdentifier [TypeArguments] | |
* PackageName . {Annotation} TypeIdentifier [TypeArguments] | |
* ClassOrInterfaceType . {Annotation} TypeIdentifier [TypeArguments] | |
* InterfaceType: | |
* ClassType | |
* }</pre> | |
*/ | |
NodeList<ClassOrInterfaceType> ImplementsList(): | |
{ | |
NodeList<ClassOrInterfaceType> ret = new NodeList<ClassOrInterfaceType>(); | |
ClassOrInterfaceType cit; | |
} | |
{ | |
"implements" cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } | |
( "," cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } )* | |
{ return ret; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.9 | |
* <pre>{@code | |
* EnumDeclaration: | |
* {ClassModifier} enum TypeIdentifier [Superinterfaces] EnumBody | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.9.1 | |
* <pre>{@code | |
* EnumBody: | |
* { [EnumConstantList] [,] [EnumBodyDeclarations] } | |
* EnumConstantList: | |
* EnumConstant {, EnumConstant} | |
* EnumConstant: | |
* {EnumConstantModifier} Identifier [( [ArgumentList] )] [ClassBody] | |
* EnumConstantModifier: | |
* Annotation | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.9.2 | |
* <pre>{@code | |
* EnumBodyDeclarations: | |
* ; {ClassBodyDeclaration} | |
* }</pre> | |
*/ | |
EnumDeclaration EnumDeclaration(ModifierHolder modifier): | |
{ | |
SimpleName name; | |
NodeList<ClassOrInterfaceType> impList = emptyNodeList(); | |
EnumConstantDeclaration entry; | |
NodeList<EnumConstantDeclaration> entries = emptyNodeList(); | |
BodyDeclaration<?> member; | |
NodeList<BodyDeclaration<?>> members = emptyNodeList(); | |
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); } | |
} | |
/** | |
* Note that the {@code EnumConstantModifier} is defined as an {@code Annotation}. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.9.1 | |
* <pre>{@code | |
* EnumConstant: | |
* {EnumConstantModifier} Identifier [( [ArgumentList] )] [ClassBody] | |
* EnumConstantModifier: | |
* Annotation | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.9.2 | |
* <pre>{@code | |
* EnumBodyDeclarations: | |
* ; {ClassBodyDeclaration} | |
* }</pre> | |
*/ | |
EnumConstantDeclaration EnumConstantDeclaration(): | |
{ | |
NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); | |
AnnotationExpr ann; | |
SimpleName name; | |
NodeList<Expression> args = emptyNodeList(); | |
NodeList<BodyDeclaration<?>> classBody = emptyNodeList(); | |
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>. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.1.2 | |
* <pre>{@code | |
* TypeParameters: | |
* < TypeParameterList > | |
* TypeParameterList: | |
* TypeParameter {, TypeParameter} | |
* }</pre> | |
* For Convenience: | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.4 | |
* <pre>{@code | |
* TypeParameter: | |
* {TypeParameterModifier} TypeIdentifier [TypeBound] | |
* TypeParameterModifier: | |
* Annotation | |
* TypeBound: | |
* extends TypeVariable | |
* extends ClassOrInterfaceType {AdditionalBound} | |
* AdditionalBound: | |
* & InterfaceType | |
* }</pre> | |
*/ | |
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; } | |
} | |
/** | |
* Note that the {@code TypeParameterModifier} is defined as an {@code Annotation}. | |
* Note that the annotations are passed as a parameter to this grammar entry. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.4 | |
* <pre>{@code | |
* TypeParameter: | |
* {TypeParameterModifier} TypeIdentifier [TypeBound] | |
* TypeParameterModifier: | |
* Annotation | |
* TypeBound: | |
* extends TypeVariable | |
* extends ClassOrInterfaceType {AdditionalBound} | |
* AdditionalBound: | |
* & InterfaceType | |
* }</pre> | |
*/ | |
TypeParameter TypeParameter(NodeList<AnnotationExpr> annotations): | |
{ | |
SimpleName name; | |
NodeList<ClassOrInterfaceType> typeBound = emptyNodeList(); | |
JavaToken begin; | |
} | |
{ | |
// Annotations are passed as a parameter to this grammar entry. | |
name = SimpleName() { begin=token(); } | |
[ typeBound = TypeBound() ] | |
{ return new TypeParameter(range(begin, token()), name, typeBound, annotations); } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.4 | |
* <pre>{@code | |
* TypeBound: | |
* extends TypeVariable | |
* extends ClassOrInterfaceType {AdditionalBound} | |
* AdditionalBound: | |
* & InterfaceType | |
* }</pre> | |
* For Convenience: | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.3 | |
* <pre>{@code | |
* ClassOrInterfaceType: | |
* ClassType | |
* InterfaceType | |
* ClassType: | |
* {Annotation} TypeIdentifier [TypeArguments] | |
* PackageName . {Annotation} TypeIdentifier [TypeArguments] | |
* ClassOrInterfaceType . {Annotation} TypeIdentifier [TypeArguments] | |
* InterfaceType: | |
* ClassType | |
* TypeVariable: | |
* {Annotation} TypeIdentifier | |
* }</pre> | |
*/ | |
NodeList<ClassOrInterfaceType> TypeBound(): | |
{ | |
NodeList<ClassOrInterfaceType> ret = emptyNodeList(); | |
ClassOrInterfaceType cit; | |
} | |
{ | |
"extends" cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } | |
( | |
"&" | |
cit = AnnotatedClassOrInterfaceType() { ret.add(cit); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.1.6 | |
* <pre>{@code | |
* ClassBody: | |
* { {ClassBodyDeclaration} } | |
* ClassBodyDeclaration: | |
* ClassMemberDeclaration | |
* InstanceInitializer | |
* StaticInitializer | |
* ConstructorDeclaration | |
* ClassMemberDeclaration: | |
* FieldDeclaration | |
* MethodDeclaration | |
* ClassDeclaration | |
* InterfaceDeclaration | |
* ; | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-9.html#jls-9.1.4 | |
* <pre>{@code | |
* InterfaceBody: | |
* { {InterfaceMemberDeclaration} } | |
* InterfaceMemberDeclaration: | |
* ConstantDeclaration | |
* InterfaceMethodDeclaration | |
* ClassDeclaration | |
* InterfaceDeclaration | |
* ; | |
* }</pre> | |
*/ | |
NodeList<BodyDeclaration<?>> ClassOrInterfaceBody(): | |
{ | |
NodeList<BodyDeclaration<?>> ret = emptyNodeList(); | |
BodyDeclaration member; | |
} | |
{ | |
"{" | |
( | |
member = ClassOrInterfaceBodyDeclaration() { ret.add(member); } | |
| | |
";" | |
)* | |
"}" | |
{ return ret; } | |
} | |
/** | |
* Everything that can go into a "regular" class or interface declaration, | |
* can also (usually) be included within a record. | |
* Exceptions to this are handled within the validators. | |
* | |
* Note: This is HEAVILY based on ClassOrInterfaceBody() and ClassOrInterfaceBodyDeclaration(), | |
* and there may be some scope/potential to optimise this and merge some parts together. | |
* | |
* https://docs.oracle.com/javase/specs/jls/se16/html/jls-8.html#jls-8.10.2 | |
*/ | |
NodeList<BodyDeclaration<?>> RecordBody(): | |
{ | |
NodeList<BodyDeclaration<?>> ret = emptyNodeList(); | |
BodyDeclaration member; | |
} | |
{ | |
"{" | |
( | |
member = RecordBodyDeclaration() { ret.add(member); } | |
| | |
";" | |
)* | |
"}" | |
{ return ret; } | |
} | |
/** | |
* Almost identical to ClassOrInterfaceBodyDeclaration, but: | |
* - with a CompactConstructorDeclaration | |
* As a result, there may be some scope/potential to optimize this and merge some parts together. | |
* | |
* https://docs.oracle.com/javase/specs/jls/se16/html/jls-8.html#jls-8.10.2 | |
* <pre>{@code | |
* RecordBody: | |
* { {RecordBodyDeclaration} } | |
* RecordBodyDeclaration: | |
* ClassBodyDeclaration | |
* CompactConstructorDeclaration | |
* }</pre> | |
* | |
* For convenience: | |
* https://docs.oracle.com/javase/specs/jls/se16/html/jls-8.html#jls-8.10.2 | |
* <pre>{@code | |
* ClassBodyDeclaration: | |
* ClassMemberDeclaration | |
* InstanceInitializer | |
* StaticInitializer | |
* ConstructorDeclaration | |
* ClassMemberDeclaration: | |
* FieldDeclaration | |
* MethodDeclaration | |
* ClassDeclaration | |
* InterfaceDeclaration | |
* ; | |
* }</pre> | |
*/ | |
BodyDeclaration<?> RecordBodyDeclaration(): | |
{ | |
ModifierHolder modifiers; | |
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 | |
modifiers = Modifiers() | |
( | |
ret = ClassOrInterfaceDeclaration(modifiers) | |
| | |
LOOKAHEAD("enum") | |
ret = EnumDeclaration(modifiers) | |
| | |
LOOKAHEAD("@" "interface") | |
ret = AnnotationTypeDeclaration(modifiers) | |
| | |
// Compact Record Constructors | |
LOOKAHEAD( [ TypeParameters() ] Identifier() "{" ) | |
ret = CompactConstructorDeclaration(modifiers) | |
| | |
// "Normal" Record Constructors | |
LOOKAHEAD( [ TypeParameters() ] Identifier() "(" ) | |
ret = ConstructorDeclaration(modifiers) | |
| | |
LOOKAHEAD( Type() Identifier() ( ArrayBracketPair() )* ( "," | "=" | ";" ) ) | |
ret = FieldDeclaration(modifiers) | |
| | |
ret = MethodDeclaration(modifiers) | |
) | |
) | |
{ return ret; } | |
} | |
/** | |
* https://openjdk.java.net/jeps/359#Grammar | |
* <pre>{@code | |
* CompactConstructorDeclaration: | |
* {Annotation} {ConstructorModifier} [TypeParameters] SimpleTypeName | |
* [Throws] ConstructorBody | |
* }</pre> | |
*/ | |
CompactConstructorDeclaration CompactConstructorDeclaration(ModifierHolder modifier): | |
{ | |
RangedList<TypeParameter> typeParameters = new RangedList<TypeParameter>(emptyNodeList()); | |
SimpleName name; | |
Pair<NodeList<Parameter>, ReceiverParameter> parameters = new Pair<NodeList<Parameter>, ReceiverParameter>(emptyNodeList(), null); | |
NodeList<ReferenceType> throws_ = emptyNodeList(); | |
ExplicitConstructorInvocationStmt exConsInv = null; | |
NodeList<Statement> stmts = emptyNodeList(); | |
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 CompactConstructorDeclaration(range(begin, token()), modifier.modifiers, modifier.annotations, typeParameters.list, name, throws_, new BlockStmt(range(blockBegin, token()), stmts)); | |
} | |
} | |
/** | |
* Note that {@code ClassDeclaration} and {@code InterfaceDeclaration} (in the JLS) include enum and annotation declarations. | |
* Note that {@code InstanceInitializer} and {@code StaticInitializer} are treated as an {@code Initializer} with an | |
* optional {@code static} modifier in JavaParser. | |
* TODO: Investigate the {@code ClassBodyDeclaration} parts existing within an interface - is permitting this a potential problem? | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.1.6 | |
* <pre>{@code | |
* ClassBody: | |
* { {ClassBodyDeclaration} } | |
* ClassBodyDeclaration: | |
* ClassMemberDeclaration | |
* InstanceInitializer | |
* StaticInitializer | |
* ConstructorDeclaration | |
* ClassMemberDeclaration: | |
* FieldDeclaration | |
* MethodDeclaration | |
* ClassDeclaration | |
* InterfaceDeclaration | |
* ; | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-9.html#jls-9.1.4 | |
* <pre>{@code | |
* InterfaceBody: | |
* { {InterfaceMemberDeclaration} } | |
* InterfaceMemberDeclaration: | |
* ConstantDeclaration | |
* InterfaceMethodDeclaration | |
* ClassDeclaration | |
* InterfaceDeclaration | |
* ; | |
* }</pre> | |
*/ | |
BodyDeclaration<?> ClassOrInterfaceBodyDeclaration(): | |
{ | |
ModifierHolder modifiers; | |
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 | |
modifiers = Modifiers() | |
( | |
ret = ClassOrInterfaceDeclaration(modifiers) | |
| | |
LOOKAHEAD("record" SimpleName() [ TypeParameters() ] Parameters() ) | |
ret = RecordDeclaration(modifiers) | |
| | |
LOOKAHEAD("enum") | |
ret = EnumDeclaration(modifiers) | |
| | |
LOOKAHEAD("@" "interface") | |
ret = AnnotationTypeDeclaration(modifiers) | |
| | |
LOOKAHEAD( [ TypeParameters() ] Identifier() "(" ) | |
ret = ConstructorDeclaration(modifiers) | |
| | |
LOOKAHEAD( Type() Identifier() ( ArrayBracketPair() )* ( "," | "=" | ";" ) ) | |
ret = FieldDeclaration(modifiers) | |
| | |
ret = MethodDeclaration(modifiers) | |
) | |
) | |
{ return ret; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.3 | |
* <pre>{@code | |
* FieldDeclaration: | |
* {FieldModifier} UnannType VariableDeclaratorList ; | |
* VariableDeclaratorList: | |
* VariableDeclarator {, VariableDeclarator} | |
* VariableDeclarator: | |
* VariableDeclaratorId [= VariableInitializer] | |
* VariableDeclaratorId: | |
* Identifier [Dims] | |
* VariableInitializer: | |
* Expression | |
* ArrayInitializer | |
* }</pre> | |
*/ | |
FieldDeclaration FieldDeclaration(ModifierHolder modifier): | |
{ | |
Type partialType; | |
NodeList<VariableDeclarator> variables = new NodeList<VariableDeclarator>(); | |
VariableDeclarator val; | |
} | |
{ | |
// Modifiers are already matched in the caller | |
partialType = Type(emptyNodeList()) | |
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); | |
} | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.3 | |
* <pre>{@code | |
* VariableDeclarator: | |
* VariableDeclaratorId [= VariableInitializer] | |
* VariableDeclaratorId: | |
* Identifier [Dims] | |
* VariableInitializer: | |
* Expression | |
* ArrayInitializer | |
* }</pre> | |
*/ | |
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); } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.3 | |
* <pre>{@code | |
* VariableDeclaratorId: | |
* Identifier [Dims] | |
* }</pre> | |
* For convenience: | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-Identifier | |
* <pre>{@code | |
* Identifier: | |
* IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral | |
* IdentifierChars: | |
* JavaLetter {JavaLetterOrDigit} | |
* JavaLetter: | |
* any Unicode character that is a "Java letter" | |
* JavaLetterOrDigit: | |
* any Unicode character that is a "Java letter-or-digit" | |
* }</pre> | |
* For convenience: | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-Dims | |
* <pre>{@code | |
* Dims: | |
* {Annotation} [ ] {{Annotation} [ ]} | |
* }</pre> | |
*/ | |
Pair<SimpleName, List<ArrayBracketPair>> VariableDeclaratorId(): | |
{ | |
SimpleName name; | |
JavaToken begin; | |
ArrayBracketPair arrayBracketPair; | |
List<ArrayBracketPair> arrayBracketPairs = new ArrayList<ArrayBracketPair>(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); | |
} | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.3 | |
* <pre>{@code | |
* VariableInitializer: | |
* Expression | |
* ArrayInitializer | |
* }</pre> | |
*/ | |
Expression VariableInitializer(): | |
{ | |
Expression ret; | |
} | |
{ | |
( | |
ret = ArrayInitializer() | |
| | |
ret = Expression() | |
) | |
{ return ret; } | |
} | |
/** | |
* An array initializer is written as a comma-separated list of expressions, enclosed by braces { and }. | |
* A trailing comma may appear after the last expression in an array initializer and is ignored. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-10.html#jls-10.6 | |
* <pre>{@code | |
* ArrayInitializer: | |
* { [VariableInitializerList] [,] } | |
* VariableInitializerList: | |
* VariableInitializer {, VariableInitializer} | |
* }</pre> | |
* <pre>{@code | |
* VariableInitializer: | |
* Expression | |
* ArrayInitializer | |
* }</pre> | |
*/ | |
ArrayInitializerExpr ArrayInitializer(): | |
{ | |
NodeList<Expression> values = emptyNodeList(); | |
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); | |
} | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.4 | |
* <pre>{@code | |
* MethodDeclaration: | |
* {MethodModifier} MethodHeader MethodBody | |
* MethodHeader: | |
* Result MethodDeclarator [Throws] | |
* TypeParameters {Annotation} Result MethodDeclarator [Throws] | |
* MethodDeclarator: | |
* Identifier ( [ReceiverParameter ,] [FormalParameterList] ) [Dims] | |
* ReceiverParameter: | |
* {Annotation} UnannType [Identifier .] this | |
* }</pre> | |
*/ | |
MethodDeclaration MethodDeclaration(ModifierHolder modifier): | |
{ | |
RangedList<TypeParameter> typeParameters = new RangedList<TypeParameter>(emptyNodeList()); | |
Type type; | |
SimpleName name; | |
Pair<NodeList<Parameter>, ReceiverParameter> parameters = new Pair<NodeList<Parameter>, ReceiverParameter>(emptyNodeList(), null); | |
ArrayBracketPair arrayBracketPair; | |
List<ArrayBracketPair> arrayBracketPairs = new ArrayList<ArrayBracketPair>(0); | |
NodeList<ReferenceType> throws_ = emptyNodeList(); | |
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(emptyNodeList()) { 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); | |
} | |
} | |
// TODO: JLS Has type and unannotated type, while JavaParser has type and annotated type. | |
ReferenceType AnnotatedReferenceType(): | |
{ | |
NodeList<AnnotationExpr> annotations; | |
ReferenceType type; | |
} | |
{ | |
annotations = Annotations() | |
type = ReferenceType(annotations) | |
{ return type; } | |
} | |
// TODO: JLS Has type and unannotated type, while JavaParser has type and annotated type. | |
Type AnnotatedType(): | |
{ | |
NodeList<AnnotationExpr> annotations; | |
Type type; | |
} | |
{ | |
annotations = Annotations() | |
type = Type(annotations) | |
{ return type; } | |
} | |
/** | |
* The JLS refers to parameters as {@code FormalParameter}. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.4.1 | |
* <pre>{@code | |
* FormalParameterList: | |
* FormalParameter {, FormalParameter} | |
* FormalParameter: | |
* {VariableModifier} UnannType VariableDeclaratorId | |
* VariableArityParameter | |
* VariableArityParameter: | |
* {VariableModifier} UnannType {Annotation} ... Identifier | |
* VariableModifier: | |
* Annotation | |
* final | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.4 | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-ReceiverParameter | |
* <pre>{@code | |
* MethodDeclarator: | |
* Identifier ( [ReceiverParameter ,] [FormalParameterList] ) [Dims] | |
* ReceiverParameter: | |
* {Annotation} UnannType [Identifier .] this | |
* }</pre> | |
*/ | |
Pair<NodeList<Parameter>, ReceiverParameter> Parameters(): | |
{ | |
NodeList<Parameter> ret = emptyNodeList(); | |
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); } | |
} | |
/** | |
* Note: Similar, but not identical to, {@code FormalParameter}. | |
* Note: Distinction between {@code LambdaParameters} and {@code InferredLambdaParameters} is presence of types. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.27.1 | |
* <pre>{@code | |
* LambdaParameters: | |
* ( [LambdaParameterList] ) | |
* Identifier | |
* LambdaParameterList: | |
* LambdaParameter {, LambdaParameter} | |
* Identifier {, Identifier} | |
* LambdaParameter: | |
* {VariableModifier} LambdaParameterType VariableDeclaratorId | |
* VariableArityParameter | |
* LambdaParameterType: | |
* UnannType | |
* var | |
* }</pre> | |
* For Convenience: | |
* <pre>{@code | |
* VariableArityParameter: | |
* {VariableModifier} UnannType {Annotation} ... Identifier | |
* VariableModifier: | |
* Annotation | |
* final | |
* VariableDeclaratorId: | |
* Identifier [Dims] | |
* Dims: | |
* {Annotation} [ ] {{Annotation} [ ]} | |
* }</pre> | |
*/ | |
NodeList<Parameter> LambdaParameters(): | |
{ | |
NodeList<Parameter> ret = null; | |
Parameter par; | |
} | |
{ | |
par = Parameter() { ret = add(ret, par); } | |
( "," par = Parameter() { ret = add(ret, par); } )* | |
{ return ret; } | |
} | |
/** | |
* Note: Similar, but not identical to, {@code FormalParameter}. | |
* Note: Distinction between {@code LambdaParameters} and {@code InferredLambdaParameters} is presence of types. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.27.1 | |
* <pre>{@code | |
* LambdaParameters: | |
* ( [LambdaParameterList] ) | |
* Identifier | |
* LambdaParameterList: | |
* LambdaParameter {, LambdaParameter} | |
* Identifier {, Identifier} | |
* LambdaParameter: | |
* {VariableModifier} LambdaParameterType VariableDeclaratorId | |
* VariableArityParameter | |
* LambdaParameterType: | |
* UnannType | |
* var | |
* }</pre> | |
* For Convenience: | |
* <pre>{@code | |
* VariableArityParameter: | |
* {VariableModifier} UnannType {Annotation} ... Identifier | |
* VariableModifier: | |
* Annotation | |
* final | |
* VariableDeclaratorId: | |
* Identifier [Dims] | |
* Dims: | |
* {Annotation} [ ] {{Annotation} [ ]} | |
* }</pre> | |
*/ | |
NodeList<Parameter> InferredLambdaParameters(): | |
{ | |
NodeList<Parameter> ret = null; | |
Pair<SimpleName, List<ArrayBracketPair>> id; | |
} | |
{ | |
id = VariableDeclaratorId() { ret = add(ret, new Parameter(range(id.a, id.a), new NodeList<Modifier>(), emptyNodeList(), new UnknownType(), false, emptyNodeList(), id.a)); } | |
( | |
"," id = VariableDeclaratorId() { ret = add(ret, new Parameter(range(id.a, id.a), new NodeList<Modifier>(), emptyNodeList(), new UnknownType(), false, emptyNodeList(), id.a)); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.4.1 | |
* <pre>{@code | |
* FormalParameter: | |
* {VariableModifier} UnannType VariableDeclaratorId | |
* VariableArityParameter | |
* VariableArityParameter: | |
* {VariableModifier} UnannType {Annotation} ... Identifier | |
* VariableModifier: | |
* Annotation | |
* final | |
* }</pre> | |
*/ | |
Parameter Parameter(): | |
{ | |
ModifierHolder modifier; | |
Type partialType; | |
boolean isVarArg = false; | |
Pair<SimpleName, List<ArrayBracketPair>> id; | |
NodeList<AnnotationExpr> varArgAnnotations = emptyNodeList(); | |
} | |
{ | |
modifier = Modifiers() | |
partialType = Type(emptyNodeList()) | |
[ | |
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); | |
} | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.4 | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-ReceiverParameter | |
* <pre>{@code | |
* MethodDeclarator: | |
* Identifier ( [ReceiverParameter ,] [FormalParameterList] ) [Dims] | |
* ReceiverParameter: | |
* {Annotation} UnannType [Identifier .] this | |
* }</pre> | |
*/ | |
ReceiverParameter ReceiverParameter(): | |
{ | |
Type partialType; | |
Name id; | |
NodeList<AnnotationExpr> annotations = emptyNodeList(); | |
} | |
{ | |
annotations = Annotations() | |
partialType = Type(emptyNodeList()) | |
id = ReceiverParameterId() | |
{ | |
return new ReceiverParameter(range(partialType, token()), annotations, partialType, id); | |
} | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.4 | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-ReceiverParameter | |
* <pre>{@code | |
* MethodDeclarator: | |
* Identifier ( [ReceiverParameter ,] [FormalParameterList] ) [Dims] | |
* ReceiverParameter: | |
* {Annotation} UnannType [Identifier .] this | |
* }</pre> | |
*/ | |
Name ReceiverParameterId(): | |
{ | |
Name ret = null; | |
} | |
{ | |
[ LOOKAHEAD(Name()) ret = Name() "."] "this" | |
{ return new Name(tokenRange(), ret, token.image); } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.8 | |
* <pre>{@code | |
* ConstructorDeclaration: | |
* {ConstructorModifier} ConstructorDeclarator [Throws] ConstructorBody | |
* ConstructorDeclarator: | |
* [TypeParameters] SimpleTypeName ( [ReceiverParameter ,] [FormalParameterList] ) | |
* SimpleTypeName: | |
* TypeIdentifier | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.8.7 | |
* <pre>{@code | |
* ConstructorBody: | |
* { [ExplicitConstructorInvocation] [BlockStatements] } | |
* }</pre> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.8.7.1 | |
* <pre>{@code | |
* ExplicitConstructorInvocation: | |
* [TypeArguments] this ( [ArgumentList] ) ; | |
* [TypeArguments] super ( [ArgumentList] ) ; | |
* ExpressionName . [TypeArguments] super ( [ArgumentList] ) ; | |
* Primary . [TypeArguments] super ( [ArgumentList] ) ; | |
* }</pre> | |
*/ | |
ConstructorDeclaration ConstructorDeclaration(ModifierHolder modifier): | |
{ | |
RangedList<TypeParameter> typeParameters = new RangedList<TypeParameter>(emptyNodeList()); | |
SimpleName name; | |
Pair<NodeList<Parameter>, ReceiverParameter> parameters = new Pair<NodeList<Parameter>, ReceiverParameter>(emptyNodeList(), null); | |
NodeList<ReferenceType> throws_ = emptyNodeList(); | |
ExplicitConstructorInvocationStmt exConsInv = null; | |
NodeList<Statement> stmts = emptyNodeList(); | |
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); | |
} | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.8.7.1 | |
* <pre>{@code | |
* ExplicitConstructorInvocation: | |
* [TypeArguments] this ( [ArgumentList] ) ; | |
* [TypeArguments] super ( [ArgumentList] ) ; | |
* ExpressionName . [TypeArguments] super ( [ArgumentList] ) ; | |
* Primary . [TypeArguments] super ( [ArgumentList] ) ; | |
* }</pre> | |
* The same, but aligned on {@code super}, to emphasise how this grammar relates: | |
* <pre>{@code | |
* ExplicitConstructorInvocation: | |
* [TypeArguments] this ( [ArgumentList] ) ; | |
* [TypeArguments] super ( [ArgumentList] ) ; | |
* ExpressionName . [TypeArguments] super ( [ArgumentList] ) ; | |
* Primary . [TypeArguments] super ( [ArgumentList] ) ; | |
* }</pre> | |
*/ | |
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); } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-14.html#jls-14.5 | |
* <pre>{@code | |
* Statement: | |
* StatementWithoutTrailingSubstatement | |
* LabeledStatement | |
* IfThenStatement | |
* IfThenElseStatement | |
* WhileStatement | |
* ForStatement | |
* StatementNoShortIf: | |
* StatementWithoutTrailingSubstatement | |
* LabeledStatementNoShortIf | |
* IfThenElseStatementNoShortIf | |
* WhileStatementNoShortIf | |
* ForStatementNoShortIf | |
* StatementWithoutTrailingSubstatement: | |
* Block | |
* EmptyStatement | |
* ExpressionStatement | |
* AssertStatement | |
* SwitchStatement | |
* DoStatement | |
* BreakStatement | |
* ContinueStatement | |
* ReturnStatement | |
* SynchronizedStatement | |
* ThrowStatement | |
* TryStatement | |
* YieldStatement | |
* }</pre> | |
*/ | |
NodeList<Statement> Statements(): | |
{ | |
NodeList<Statement> ret = emptyNodeList(); | |
Statement stmt; | |
} | |
{ | |
( LOOKAHEAD(2) stmt = BlockStatement() { ret = add(ret, stmt); } )* | |
{ return ret; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.6 | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8. | |
* <pre>{@code | |
* InstanceInitializer: | |
* Block | |
* }</pre> | |
* <pre>{@code | |
* StaticInitializer: | |
* static Block | |
* }</pre> | |
*/ | |
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. | |
*/ | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.1 | |
* <pre>{@code | |
* Type: | |
* PrimitiveType | |
* ReferenceType | |
* }<pre> | |
*/ | |
Type Type(NodeList<AnnotationExpr> annotations): | |
{ | |
Type ret; | |
} | |
{ | |
( | |
LOOKAHEAD(PrimitiveType(annotations) Annotations() "[" | ClassOrInterfaceType(annotations)) | |
ret = ReferenceType(annotations) | |
| | |
ret = PrimitiveType(annotations) | |
) | |
{ return ret; } | |
} | |
/** | |
* // TODO: JLS Has type and unannotated type, while JavaParser has type and annotated type. | |
* Note that an array of primitives is considered a reference type. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.1 | |
* <pre>{@code | |
* ReferenceType: | |
* ClassOrInterfaceType | |
* TypeVariable | |
* ArrayType | |
* ClassOrInterfaceType: | |
* ClassType | |
* InterfaceType | |
* ClassType: | |
* {Annotation} TypeIdentifier [TypeArguments] | |
* PackageName . {Annotation} TypeIdentifier [TypeArguments] | |
* ClassOrInterfaceType . {Annotation} TypeIdentifier [TypeArguments] | |
* InterfaceType: | |
* ClassType | |
* TypeVariable: | |
* {Annotation} TypeIdentifier | |
* ArrayType: | |
* PrimitiveType Dims | |
* ClassOrInterfaceType Dims | |
* TypeVariable Dims | |
* Dims: | |
* {Annotation} [ ] {{Annotation} [ ]} | |
* }<pre> | |
*/ | |
ReferenceType ReferenceType(NodeList<AnnotationExpr> annotations): | |
{ | |
Type type; | |
ArrayBracketPair arrayBracketPair; | |
List<ArrayBracketPair> arrayBracketPairs = new ArrayList<ArrayBracketPair>(0); | |
} | |
{ | |
( | |
// Note that an array of primitives is considered a reference type. | |
type = PrimitiveType(annotations) | |
( | |
LOOKAHEAD(Annotations() "[") | |
arrayBracketPair = ArrayBracketPair(Origin.TYPE) { arrayBracketPairs=add(arrayBracketPairs, arrayBracketPair); } | |
)+ // MUST have one or more array bracket pairs to be considered a reference type. | |
| | |
type = ClassOrInterfaceType(annotations) | |
( | |
LOOKAHEAD(Annotations() "[") | |
arrayBracketPair = ArrayBracketPair(Origin.TYPE) { arrayBracketPairs=add(arrayBracketPairs, arrayBracketPair); } | |
)* // Optionally MAY have zero or more array bracket pairs. | |
) | |
{ return (ReferenceType)wrapInArrayTypes(type, arrayBracketPairs); } | |
} | |
/** | |
* Array bracket pairs is referred to as {@code Dims} within the JLS. | |
* <pre>{@code | |
* Dims: | |
* {Annotation} [ ] {{Annotation} [ ]} | |
* }</pre> | |
* | |
*/ | |
ArrayBracketPair ArrayBracketPair(Origin origin): | |
{ | |
NodeList<AnnotationExpr> annotations; | |
JavaToken begin = INVALID; | |
} | |
{ | |
annotations = Annotations() | |
"[" { begin = orIfInvalid(begin, token()); } | |
"]" | |
{ return new ArrayBracketPair(range(begin, token()), origin, annotations); } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.9 | |
* <blockquote> | |
* An intersection type takes the form T1 & ... & Tn (n > 0), where Ti (1 ≤ i ≤ n) are types. | |
* </blockquote> | |
*/ | |
IntersectionType IntersectionType(NodeList<AnnotationExpr> annotations): | |
{ | |
JavaToken begin = INVALID; | |
ReferenceType elementType; | |
NodeList<ReferenceType> elements = emptyNodeList(); | |
} | |
{ | |
elementType = ReferenceType(annotations) { begin = orIfInvalid(begin, elementType); elements = add(elements, elementType); } | |
"&" | |
(elementType = AnnotatedReferenceType() { elements = add(elements, elementType); } )+ | |
{ return new IntersectionType(range(begin, token()), elements); } | |
} | |
// TODO: JLS Has type and unannotated type, while JavaParser has type and annotated type. | |
ClassOrInterfaceType AnnotatedClassOrInterfaceType(): | |
{ | |
NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>(); | |
ClassOrInterfaceType cit; | |
} | |
{ | |
annotations = Annotations() | |
cit = ClassOrInterfaceType(annotations) | |
{ return cit; } | |
} | |
// TODO: JLS Has type and unannotated type, while JavaParser has type and annotated type. | |
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; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.5.1 | |
* <pre>{@code | |
* TypeArguments: | |
* < TypeArgumentList > | |
* TypeArgumentList: | |
* TypeArgument {, TypeArgument} | |
* TypeArgument: | |
* ReferenceType | |
* Wildcard | |
* }<pre> | |
*/ | |
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; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.5.1 | |
* <pre>{@code | |
* TypeArguments: | |
* < TypeArgumentList > | |
* TypeArgumentList: | |
* TypeArgument {, TypeArgument} | |
* TypeArgument: | |
* ReferenceType | |
* Wildcard | |
* }<pre> | |
*/ | |
Type TypeArgument(): | |
{ | |
Type ret; | |
NodeList<AnnotationExpr> annotations; | |
} | |
{ | |
annotations = Annotations() | |
( | |
ret = Type(annotations) | |
| | |
ret = Wildcard(annotations) | |
) | |
{ return ret; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.5.1 | |
* <pre>{@code | |
* Wildcard: | |
* {Annotation} ? [WildcardBounds] | |
* WildcardBounds: | |
* extends ReferenceType | |
* super ReferenceType | |
* }<pre> | |
*/ | |
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);} | |
} | |
/** | |
* Note that {@code char} and {@code byte} are treated as an {@code IntegralType}, which is a subtype of {@code NumericType}. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.2 | |
* <pre>{@code | |
* PrimitiveType: | |
* {Annotation} NumericType | |
* {Annotation} boolean | |
* NumericType: | |
* IntegralType | |
* FloatingPointType | |
* IntegralType: | |
* (one of) | |
* byte short int long char | |
* FloatingPointType: | |
* (one of) | |
* float double | |
* }<pre> | |
*/ | |
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; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-8.html#jls-8.4.5 | |
* <pre>{@code | |
* Result: | |
* UnannType | |
* void | |
* }<pre> | |
*/ | |
Type ResultType(NodeList<AnnotationExpr> annotations): | |
{ | |
Type ret; | |
} | |
{ | |
( | |
"void" { ret = new VoidType(tokenRange()); } | |
| | |
ret = Type(annotations) | |
) | |
{ return ret; } | |
} | |
/** | |
* A {@code SimpleName} is just an identifier. | |
* A {@code Name} can be a {@code SimpleName} or a {@code SimpleName} with qualifiers (e.g. a class or object reference). | |
* Note that no disambiguation is made as to exactly what type of name it is - e.g. whether it is a package, subclass, or field. That happens within JavaParser, rather than the grammar. | |
*/ | |
Name Name(): | |
/* | |
* A lookahead is required below since "Name" can be followed | |
* by a ".*" when used in the context of an "ImportDeclaration". | |
*/ | |
{ | |
Name ret; | |
} | |
{ | |
Identifier() { ret = new Name(tokenRange(), null, token.image); } | |
( | |
LOOKAHEAD(2) | |
"." | |
Identifier() | |
{ ret = new Name(range(ret, token()), ret, token.image); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* A {@code SimpleName} is just an identifier. | |
* A {@code Name} can be a {@code SimpleName} or a {@code SimpleName} with qualifiers (e.g. a class or object reference). | |
* Note that no disambiguation is made as to exactly what type of name it is - e.g. whether it is a package, subclass, or field. That happens within JavaParser, rather than the grammar. | |
*/ | |
SimpleName SimpleName(): | |
{ | |
SimpleName ret; | |
} | |
{ | |
Identifier() { ret = new SimpleName(tokenRange(), token.image); } | |
{ return ret; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.8 | |
* <pre>{@code | |
* Identifier: | |
* IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral | |
* IdentifierChars: | |
* JavaLetter {JavaLetterOrDigit} | |
* JavaLetter: | |
* any Unicode character that is a "Java letter" | |
* }</pre> | |
* For Convenience: | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.9 | |
* <blockquote> | |
* 51 character sequences, formed from ASCII letters, are reserved for use as keywords and cannot be used as identifiers (§3.8). | |
* </blockquote> | |
* <pre>{@code | |
* Keyword: | |
* (one of) | |
* | |
* abstract continue for new switch | |
* assert default if package synchronized | |
* boolean do goto private this | |
* break double implements protected throw | |
* byte else import public throws | |
* case enum instanceof return transient | |
* catch extends int short try | |
* char final interface static void | |
* class finally long strictfp volatile | |
* const float native super while | |
* _ (underscore) | |
* }</pre> | |
*/ | |
String Identifier(): | |
{ | |
String ret; | |
} | |
{ | |
( | |
// TODO: Explain why these keywords are explicitly flagged up as "included", and why they're not already covered by {@code <IDENTIFIER>}. | |
// TODO: Explain how / where boolean and null literals are excluded. | |
// 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> | <YIELD> | <RECORD> | | |
// 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() | |
{ | |
ret = generateLambda(ret, lambdaBody); | |
} | |
| | |
"::" | |
[typeArgs = TypeArguments()] | |
(Identifier() | "new") { ret = new MethodReferenceExpr(range(ret, token()), ret, typeArgs.list, token.image); } | |
) | |
] | |
{ return ret; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.26 | |
* <pre>{@code | |
* AssignmentExpression: | |
* ConditionalExpression | |
* Assignment | |
* Assignment: | |
* LeftHandSide AssignmentOperator Expression | |
* LeftHandSide: | |
* ExpressionName | |
* FieldAccess | |
* ArrayAccess | |
* AssignmentOperator: | |
* (one of) | |
* = *= /= %= += -= <<= >>= >>>= &= ^= |= | |
* }<pre> | |
*/ | |
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; } | |
} | |
/** | |
* // TODO: Examine further re: missing(?) {@code LambdaExpression} or whether it is permissive enough to include it. | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.25 | |
* <pre>{@code | |
* ConditionalExpression: | |
* ConditionalOrExpression | |
* ConditionalOrExpression ? Expression : ConditionalExpression | |
* ConditionalOrExpression ? Expression : LambdaExpression | |
* }<pre> | |
*/ | |
Expression ConditionalExpression(): | |
{ | |
Expression ret; | |
Expression left; | |
Expression right; | |
} | |
{ | |
ret = ConditionalOrExpression() | |
[ | |
"?" | |
left = Expression() | |
":" | |
right = Expression() | |
// TODO: Examine further re: missing(?) {@code LambdaExpression} or whether it is permissive enough to include it. | |
{ | |
ret = new ConditionalExpr(range(ret, token()), ret, left, right); | |
} | |
] | |
{ return ret; } | |
} | |
/** | |
* <strong> | |
* Note subtle distinctions between inclusive and exclusive expressions. | |
* </strong> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.24 | |
* <pre>{@code | |
* ConditionalOrExpression: | |
* ConditionalAndExpression | |
* ConditionalOrExpression || ConditionalAndExpression | |
* }<pre> | |
*/ | |
Expression ConditionalOrExpression(): | |
{ | |
Expression ret; | |
Expression right; | |
} | |
{ | |
// First consider a higher-precedence operator, before considering the token as the left-hand part of this expression. | |
ret = ConditionalAndExpression() | |
( | |
"||" | |
right = ConditionalAndExpression() | |
{ ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.OR); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* <strong> | |
* Note subtle distinctions between inclusive and exclusive expressions. | |
* </strong> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.23 | |
* <pre>{@code | |
* ConditionalAndExpression: | |
* InclusiveOrExpression | |
* ConditionalAndExpression && InclusiveOrExpression | |
* }<pre> | |
* For Convenience: | |
* <pre>{@code | |
* AndExpression: | |
* EqualityExpression | |
* AndExpression & EqualityExpression | |
* ExclusiveOrExpression: | |
* AndExpression | |
* ExclusiveOrExpression ^ AndExpression | |
* InclusiveOrExpression: | |
* ExclusiveOrExpression | |
* InclusiveOrExpression | ExclusiveOrExpression | |
* }<pre> | |
*/ | |
Expression ConditionalAndExpression(): | |
{ | |
Expression ret; | |
Expression right; | |
} | |
{ | |
// First consider a higher-precedence operator, before considering the token as the left-hand part of this expression. | |
ret = InclusiveOrExpression() | |
( | |
"&&" | |
right = InclusiveOrExpression() | |
{ ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.AND); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* <strong> | |
* Note subtle distinctions between inclusive and exclusive expressions. | |
* </strong> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.22 | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-InclusiveOrExpression | |
* <pre>{@code | |
* AndExpression: | |
* EqualityExpression | |
* AndExpression & EqualityExpression | |
* ExclusiveOrExpression: | |
* AndExpression | |
* ExclusiveOrExpression ^ AndExpression | |
* InclusiveOrExpression: | |
* ExclusiveOrExpression | |
* InclusiveOrExpression | ExclusiveOrExpression | |
* }<pre> | |
*/ | |
Expression InclusiveOrExpression(): | |
{ | |
Expression ret; | |
Expression right; | |
} | |
{ | |
// First consider a higher-precedence operator, before considering the token as the left-hand part of this expression. | |
ret = ExclusiveOrExpression() | |
( | |
"|" | |
right = ExclusiveOrExpression() | |
{ ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.BINARY_OR); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* <strong> | |
* Note subtle distinctions between inclusive and exclusive expressions. | |
* </strong> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.22 | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-ExclusiveOrExpression | |
* <pre>{@code | |
* AndExpression: | |
* EqualityExpression | |
* AndExpression & EqualityExpression | |
* ExclusiveOrExpression: | |
* AndExpression | |
* ExclusiveOrExpression ^ AndExpression | |
* InclusiveOrExpression: | |
* ExclusiveOrExpression | |
* InclusiveOrExpression | ExclusiveOrExpression | |
* }<pre> | |
*/ | |
Expression ExclusiveOrExpression(): | |
{ | |
Expression ret; | |
Expression right; | |
} | |
{ | |
// First consider a higher-precedence operator, before considering the token as the left-hand part of this expression. | |
ret = AndExpression() ( | |
"^" | |
right = AndExpression() | |
{ ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.XOR); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* <strong> | |
* Note subtle distinctions between inclusive and exclusive expressions. | |
* </strong> | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.22 | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-AndExpression | |
* <pre>{@code | |
* AndExpression: | |
* EqualityExpression | |
* AndExpression & EqualityExpression | |
* ExclusiveOrExpression: | |
* AndExpression | |
* ExclusiveOrExpression ^ AndExpression | |
* InclusiveOrExpression: | |
* ExclusiveOrExpression | |
* InclusiveOrExpression | ExclusiveOrExpression | |
* }<pre> | |
*/ | |
Expression AndExpression(): | |
{ | |
Expression ret; | |
Expression right; | |
} | |
{ | |
// First consider a higher-precedence operator, before considering the token as the left-hand part of this expression. | |
ret = EqualityExpression() ( | |
"&" | |
right = EqualityExpression() | |
{ ret = new BinaryExpr(range(ret, token()), ret, right, BinaryExpr.Operator.BINARY_AND); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* // Note that instanceof is a {@code RelationalExpression} within the JLS, which differs from JavaParser | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.21 | |
* <pre>{@code | |
* EqualityExpression: | |
* RelationalExpression | |
* EqualityExpression == RelationalExpression | |
* EqualityExpression != RelationalExpression | |
* }<pre> | |
* For Convenience: | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.20 | |
* <pre>{@code | |
* RelationalExpression: | |
* ShiftExpression | |
* RelationalExpression < ShiftExpression | |
* RelationalExpression > ShiftExpression | |
* RelationalExpression <= ShiftExpression | |
* RelationalExpression >= ShiftExpression | |
* RelationalExpression instanceof ReferenceType | |
* }<pre> | |
*/ | |
Expression EqualityExpression(): | |
{ | |
Expression ret; | |
Expression right; | |
BinaryExpr.Operator op; | |
} | |
{ | |
// First consider a higher-precedence operator, before considering the token as the left-hand part of this expression. | |
// Note that instanceof is a {@code RelationalExpression} within the JLS, which differs from JavaParser | |
ret = InstanceOfExpression() | |
( | |
( | |
"==" { op = BinaryExpr.Operator.EQUALS; } | |
| | |
"!=" { op = BinaryExpr.Operator.NOT_EQUALS; } | |
) | |
right = InstanceOfExpression() | |
{ ret = new BinaryExpr(range(ret, token()), ret, right, op); } | |
)* | |
{ return ret; } | |
} | |
/** | |
* https://openjdk.java.net/jeps/375 | |
* The instanceof grammar is extended accordingly: | |
* <pre>{@code | |
* Pattern: | |
* ReferenceType Identifier | |
* }<pre> | |
*/ | |
PatternExpr PatternExpression(): | |
{ | |
ReferenceType type; | |
SimpleName name; | |
} | |
{ | |
type = AnnotatedReferenceType() | |
name = SimpleName() | |
{ return new PatternExpr(range(type, token()), type, name); } | |
} | |
/** | |
* // Note that instanceof is a {@code RelationalExpression} within the JLS, which differs from JavaParser | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.20 | |
* <pre>{@code | |
* RelationalExpression: | |
* ShiftExpression | |
* RelationalExpression < ShiftExpression | |
* RelationalExpression > ShiftExpression | |
* RelationalExpression <= ShiftExpression | |
* RelationalExpression >= ShiftExpression | |
* RelationalExpression instanceof ReferenceType | |
* }<pre> | |
*/ | |
Expression InstanceOfExpression(): | |
{ | |
Expression ret; | |
ReferenceType type; | |
NodeList<AnnotationExpr> annotations; | |
PatternExpr pattern; | |
} | |
{ | |
ret = RelationalExpression() | |
[ | |
"instanceof" | |
( | |
LOOKAHEAD(PatternExpression()) | |
pattern = PatternExpression() | |
{ ret = new InstanceOfExpr(range(ret, token()), ret, pattern.getType(), pattern); } | |
| | |
type = AnnotatedReferenceType() | |
{ ret = new InstanceOfExpr(range(ret, token()), ret, type, null); } | |
) | |
] | |
{ return ret; } | |
} | |
/** | |
* // Note that instanceof is a {@code RelationalExpression} within the JLS, which differs from JavaParser | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.20 | |
* <pre>{@code | |
* RelationalExpression: | |
* ShiftExpression | |
* RelationalExpression < ShiftExpression | |
* RelationalExpression > ShiftExpression | |
* RelationalExpression <= ShiftExpression | |
* RelationalExpression >= ShiftExpression | |
* RelationalExpression instanceof ReferenceType | |
* }<pre> | |
* // Note that JDK 13/14 introduce pattern Matching for instanceof | |
* https://openjdk.java.net/jeps/375 | |
* The instanceof grammar is extended accordingly: | |
* <pre>{@code | |
* RelationalExpression: | |
* ... | |
* RelationalExpression instanceof ReferenceType | |
* RelationalExpression instanceof Pattern | |
* | |
* Pattern: | |
* ReferenceType Identifier | |
* }<pre> | |
*/ | |
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; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.19 | |
* <pre>{@code | |
* ShiftExpression: | |
* AdditiveExpression | |
* ShiftExpression << AdditiveExpression | |
* ShiftExpression >> AdditiveExpression | |
* ShiftExpression >>> AdditiveExpression | |
* }<pre> | |
*/ | |
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; } | |
} | |
/** | |
* https://docs.oracle.com/javase/specs/jls/se15/html/jls-15.html#jls-15.18 | |
* <pre>{@code | |
* AdditiveExpression: | |
* MultiplicativeExpression | |
* AdditiveExpression + MultiplicativeExpression | |
* AdditiveExpression - MultiplicativeExpression | |
* }<pre> | |
*/ | |
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; } | |
} | |