2014-09-30 19:51:42 +02:00
|
|
|
/**
|
2024-07-26 18:50:04 +02:00
|
|
|
* Support "JEP 455: Primitive Types in Patterns, instanceof, and switch (Preview)" (Java 23)
|
|
|
|
* Changes in InstanceOfExpression
|
2024-07-20 17:51:31 +02:00
|
|
|
* Support "JEP 476: Module Import Declarations (Preview)" (Java 23)
|
|
|
|
* Changes in ImportDeclaration
|
2024-07-29 20:21:13 +02:00
|
|
|
* Support "JEP 477: Implicitly Declared Classes and Instance Main Methods (Third Preview)" (Java 23)
|
|
|
|
* Changes in CompilationUnit, added new node ImplicitClassDeclaration
|
2024-07-20 17:51:31 +02:00
|
|
|
* Andreas Dangel 07/2024
|
|
|
|
*====================================================================
|
2024-02-15 13:20:46 +01:00
|
|
|
* Support "JEP 447: Statements before super(...) (Preview)" (Java 22)
|
|
|
|
* Changes in ConstructorBlock
|
2024-02-15 12:12:12 +01:00
|
|
|
* Support "JEP 456: Unnamed Variables & Patterns" (Java 22)
|
|
|
|
* This is now a regular language feature. Otherwise no changes.
|
2024-02-15 11:26:12 +01:00
|
|
|
* Support "JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)" (Java 22)
|
|
|
|
* No changes.
|
2024-02-15 11:04:54 +01:00
|
|
|
* Support "JEP 459: String Templates (Second Preview)" (Java 22)
|
|
|
|
* Use ASTTemplate.setContent instead of setImage.
|
2024-02-15 10:03:37 +01:00
|
|
|
* Remove support for Record pattern in enhanced for statements. This was only a Java 20 Preview feature.
|
|
|
|
* Remove support for ParenthesizedPatterns. This was only a Java 20 Preview feature.
|
|
|
|
* Andreas Dangel 02/2024
|
|
|
|
*====================================================================
|
2023-12-13 10:51:47 +01:00
|
|
|
* Renamed various nodes:
|
|
|
|
* ClassOrInterfaceType -> ClassType
|
|
|
|
* ClassOrInterfaceDeclaration -> ClassDeclaration
|
|
|
|
* ClassOrInterfaceBody -> ClassBody
|
|
|
|
* AnyTypeDeclaration -> TypeDeclaration
|
|
|
|
* MethodOrConstructorDeclaration -> ExecutableDeclaration
|
|
|
|
* VariableDeclaratorId -> VariableId
|
|
|
|
* Andreas Dangel 12/2023
|
|
|
|
*====================================================================
|
2023-08-05 15:13:49 +02:00
|
|
|
* Support "JEP 443: Unnamed Patterns and Variables" for Java 21 Preview.
|
|
|
|
* New AST nodes: ASTUnnamedPattern
|
2023-08-04 17:13:48 +02:00
|
|
|
* Support "JEP 430: String Templates" for Java 21 Preview.
|
|
|
|
* New AST nodes: ASTTemplateExpression, ASTTemplate, ASTTemplateFragment
|
2023-08-04 11:47:45 +02:00
|
|
|
* Promote "JEP 441: Pattern Matching for switch" as permanent language feature for Java 21.
|
|
|
|
* Renamed SwitchGuard to Guard.
|
2023-08-04 12:32:36 +02:00
|
|
|
* Promote "JEP 440: Record Patterns" as permanent language feature for Java 21.
|
|
|
|
* Renamed ComponentPatternList to PatternList
|
2023-08-04 11:47:45 +02:00
|
|
|
* Andreas Dangel 08/2023
|
|
|
|
*====================================================================
|
2023-02-03 19:37:28 +01:00
|
|
|
* Support "JEP 433: Pattern Matching for switch (Fourth Preview)" for Java 20 Preview
|
|
|
|
* SwitchLabel simplified
|
|
|
|
* Support "JEP 432: Record Patterns (Second Preview)" for Java 20 Preview
|
|
|
|
* ForStatement allows record patterns
|
2023-02-03 19:54:19 +01:00
|
|
|
* Removed named record patterns (optional VariableDeclaratorId following the pattern)
|
2023-02-03 19:37:28 +01:00
|
|
|
* Remove support for Java 18 preview language features
|
|
|
|
* GuardedPattern is removed
|
|
|
|
* Andreas Dangel 02/2023
|
|
|
|
*====================================================================
|
2022-07-07 14:07:49 +02:00
|
|
|
* Support "JEP 427: Pattern Matching for switch (Third Preview)" for Java 19 Preview
|
|
|
|
* Note: GuardedPattern is deprecated and only valid for 17-preview and 18-preview
|
2022-07-10 14:29:03 +02:00
|
|
|
* New AST node: ASTSwitchGuard (production "Guard") - used within switch case labels for refining a pattern
|
2022-07-07 15:06:52 +02:00
|
|
|
* Support "JEP 405: Record Patterns (Preview)" for Java 19 Preview
|
2022-07-10 14:29:03 +02:00
|
|
|
* New AST node: ASTRecordPattern and ASTComponentPatternList (production "RecordStructurePattern")
|
2022-07-07 15:24:49 +02:00
|
|
|
* Remove support for Java 17 preview language features
|
2022-07-07 14:07:49 +02:00
|
|
|
* Andreas Dangel 07/2022
|
|
|
|
*====================================================================
|
2022-04-01 18:56:16 +02:00
|
|
|
* Improve module grammar.
|
|
|
|
* Type names in "provides" directives are disambiguated like any other type name.
|
|
|
|
* ASTName is made redundant and removed for good.
|
|
|
|
* Clément Fournier 03/2022
|
|
|
|
*====================================================================
|
2022-03-10 15:33:22 +01:00
|
|
|
* Support "JEP 420: Pattern Matching for switch (Second Preview)" for Java 18 Preview
|
|
|
|
* There were no grammar changes between 18-preview and 17-preview
|
|
|
|
* Remove support for Java 16 preview language features
|
|
|
|
* Andreas Dangel 03/2022
|
|
|
|
*====================================================================
|
2021-07-01 10:39:49 +02:00
|
|
|
* Promote "JEP 409: Sealed Classes" as permanent language feature with Java 17.
|
2021-07-01 11:51:30 +02:00
|
|
|
* Support "JEP 406: Pattern Matching for switch (Preview)" for Java 17 Preview.
|
2021-07-01 12:11:54 +02:00
|
|
|
* Remove support for Java 15 preview language features
|
2021-07-01 10:39:49 +02:00
|
|
|
* Andreas Dangel 07/2021
|
|
|
|
*====================================================================
|
2021-03-05 11:48:05 +01:00
|
|
|
* Fix #3117 - infinite loop when parsing invalid code nested in lambdas
|
|
|
|
* Andreas Dangel 03/2021
|
|
|
|
*====================================================================
|
2021-03-04 07:44:05 +01:00
|
|
|
* Fix #3145 - parse exception with local records
|
|
|
|
* Clément Fournier 03/2021
|
|
|
|
*====================================================================
|
2021-02-15 19:51:48 +01:00
|
|
|
* Remove support for Java 14 preview language features
|
2021-02-15 19:33:36 +01:00
|
|
|
* JEP 397: Sealed Classes (Second Preview) for Java16 Preview
|
2021-02-14 19:42:59 +01:00
|
|
|
* JEP 395: Records for Java16
|
2021-02-12 12:44:08 +01:00
|
|
|
* JEP 394: Pattern Matching for instanceof for Java16
|
|
|
|
* Andreas Dangel 02/2021
|
|
|
|
*====================================================================
|
2020-08-13 19:58:21 +02:00
|
|
|
* Remove support for Java 13 preview language features.
|
|
|
|
* Promote text blocks as a permanent language features with Java 15.
|
2020-08-13 20:11:25 +02:00
|
|
|
* Support Pattern Matching for instanceof with Java 15 Preview.
|
2020-08-13 20:41:55 +02:00
|
|
|
* Support Records with Java 15 Preview.
|
2020-08-14 18:46:09 +02:00
|
|
|
* Support Local Records with Java 15 Preview.
|
2020-08-14 22:16:41 +02:00
|
|
|
* Support Sealed Classes with Java 15 Preview.
|
2020-08-13 19:15:02 +02:00
|
|
|
* Andreas Dangel 08/2020
|
|
|
|
*====================================================================
|
2020-02-28 14:58:52 +01:00
|
|
|
* Add support for record types introduced as a preview language
|
|
|
|
* feature with Java 14. See JEP 359.
|
|
|
|
* Andreas Dangel 02/2020
|
2019-07-01 12:36:29 +02:00
|
|
|
*====================================================================
|
2020-02-28 14:58:52 +01:00
|
|
|
* Add support for pattern matching for instance of introduced
|
2020-02-28 10:51:38 +01:00
|
|
|
* as a preview language feature with Java 14. See JEP 305.
|
|
|
|
* Clément Fournier 02/2020
|
2019-06-18 17:44:40 +02:00
|
|
|
*====================================================================
|
2020-02-27 18:30:39 +01:00
|
|
|
* Switch Expressions are now a standard feature of Java 14.
|
|
|
|
* Andreas Dangel 02/2020
|
2019-02-16 16:47:42 +01:00
|
|
|
*====================================================================
|
2019-08-13 18:33:53 +02:00
|
|
|
* Add support for the yield statement introduced as a preview language
|
|
|
|
* feature with Java 13. See JEP 354.
|
2019-08-13 20:00:40 +02:00
|
|
|
* Add support for text block literals introduces as a preview language
|
|
|
|
* feature with Java 13. See JEP 355.
|
2019-08-13 18:33:53 +02:00
|
|
|
* Andreas Dangel 08/2019
|
|
|
|
*====================================================================
|
2019-05-30 15:06:50 +02:00
|
|
|
* Fix #1848 Local classes should preserve their modifiers
|
|
|
|
* Clément Fournier 05/2019
|
|
|
|
*====================================================================
|
2019-03-31 00:21:34 +01:00
|
|
|
* Add support for Java 12 switch expressions and switch rules.
|
|
|
|
* Andreas Dangel, Clément Fournier 03/2019
|
|
|
|
*====================================================================
|
2018-04-30 20:41:45 +02:00
|
|
|
* Add support for Java 10 Local Variable Type Inference
|
|
|
|
* See #743. In Java 10 mode, "var" as local variable type is handled special.
|
|
|
|
* Andreas Dangel 04/2018
|
|
|
|
*====================================================================
|
2018-01-29 14:10:40 -03:00
|
|
|
* Fixes #888 [java] ParseException occurs with valid '<>' in Java 1.8 mode
|
|
|
|
* Juan Martin Sotuyo Dodero 01/2018
|
|
|
|
*====================================================================
|
2017-12-20 22:37:49 +01:00
|
|
|
* Fixes #793 [java] Parser error with private method in nested classes in interfaces
|
|
|
|
* Andreas Dangel 12/2017
|
|
|
|
*====================================================================
|
2017-09-22 14:31:24 +02:00
|
|
|
* Add support for Java 9 changes:
|
|
|
|
* Private interface methods are only allowed with java9.
|
|
|
|
* A single underscore "_" is an invalid identifier in java9.
|
|
|
|
* Diamond operator for anonymous classes is only allowed with java9.
|
2017-09-22 21:35:24 +02:00
|
|
|
* Add support for module-info.java.
|
2017-09-23 00:15:08 +02:00
|
|
|
* Allow more concise try-with-resources statements with java9.
|
2017-09-22 12:16:51 +02:00
|
|
|
* Andreas Dangel 09/2017
|
|
|
|
*====================================================================
|
2017-06-01 11:56:48 -03:00
|
|
|
* Add support for new Java 8 annotation locations.
|
|
|
|
* Bugs #414, #415, #417
|
|
|
|
* @Snap252 06/2017
|
|
|
|
*====================================================================
|
2017-05-20 21:28:39 +02:00
|
|
|
* Allow empty statements (";") between package, import
|
|
|
|
* and type declarations.
|
|
|
|
* Bug #378
|
|
|
|
* Andreas Dangel 05/2017
|
|
|
|
*====================================================================
|
2017-03-27 21:06:09 +02:00
|
|
|
* Allow method references to specify generics also for
|
|
|
|
* constructor references ("new").
|
|
|
|
* Bug #309
|
|
|
|
* Andreas Dangel 03/2017
|
|
|
|
*====================================================================
|
2017-02-14 02:10:51 -03:00
|
|
|
* Provide a better fix for CastExpression, getting rid of most hacks.
|
|
|
|
* Bug #257
|
|
|
|
*
|
|
|
|
* Juan Martin Sotuyo Dodero 02/2017
|
|
|
|
*====================================================================
|
2017-01-25 14:42:25 -03:00
|
|
|
* Allow local classes to carry more than one annotation.
|
|
|
|
* Bug #208
|
|
|
|
*
|
|
|
|
* Juan Martin Sotuyo Dodero 01/2017
|
|
|
|
*====================================================================
|
2017-01-25 13:11:07 -03:00
|
|
|
* Change lookahead for AnnotationMethodDeclaration in AnnotationTypeMemberDeclaration.
|
|
|
|
* Bug #206
|
|
|
|
*
|
|
|
|
* Juan Martin Sotuyo Dodero 01/2017
|
|
|
|
*====================================================================
|
2017-01-25 12:44:40 -03:00
|
|
|
* Allow method references to specify generics.
|
|
|
|
* Bug #207
|
|
|
|
*
|
|
|
|
* Juan Martin Sotuyo Dodero 01/2017
|
|
|
|
*====================================================================
|
2016-10-14 10:06:29 -03:00
|
|
|
* Simplify VariableDeclaratorId, forbidding illegal sequences such as
|
|
|
|
* this[] and MyClass.this[]
|
|
|
|
*
|
|
|
|
* Juan Martin Sotuyo Dodero 10/2016
|
|
|
|
*====================================================================
|
2016-10-13 14:14:34 -03:00
|
|
|
* Improve lambda detection in PrimaryPrefix to improve parsing performance.
|
|
|
|
*
|
|
|
|
* Juan Martin Sotuyo Dodero 10/2016
|
|
|
|
*====================================================================
|
2016-10-12 16:58:33 -03:00
|
|
|
* Fix for regression introduced in previous changeset.
|
|
|
|
* The syntactic lookahead was not properly handled by javacc,
|
|
|
|
* so it was converted to a semantic one
|
|
|
|
* Bug #1530
|
|
|
|
*
|
|
|
|
* Juan Martin Sotuyo Dodero 10/2016
|
|
|
|
*====================================================================
|
2016-05-21 11:37:10 +02:00
|
|
|
* Fix for an expression within an additive expression that was
|
|
|
|
* wrongly taken as a cast expression.
|
|
|
|
* Bug #1484
|
|
|
|
*
|
|
|
|
* Andreas Dangel 05/2016
|
|
|
|
*====================================================================
|
2016-04-30 19:14:46 +02:00
|
|
|
* Fix for Lambda expression with one variable
|
|
|
|
* Bug #1470
|
|
|
|
*
|
|
|
|
* Andreas Dangel 04/2016
|
|
|
|
*====================================================================
|
2016-01-25 10:29:00 +01:00
|
|
|
* Added support for explicit receiver parameters.
|
|
|
|
* Bug #1455
|
|
|
|
*
|
|
|
|
* Andreas Dangel 01/2016
|
|
|
|
*====================================================================
|
2015-10-06 11:04:22 +05:30
|
|
|
* Added capability for Tracking Tokens.
|
|
|
|
*
|
|
|
|
* Amit Kumar Prasad 10/2015
|
|
|
|
*====================================================================
|
2015-10-10 16:08:38 +02:00
|
|
|
* Fix for Cast Expression not detected properly in Return statements
|
|
|
|
* Bug #1429
|
|
|
|
*
|
|
|
|
* Andreas Dangel 10/2015
|
|
|
|
*====================================================================
|
2014-11-02 10:47:51 +01:00
|
|
|
* Fix for Lambda expressions without variables.
|
|
|
|
*
|
|
|
|
* Andreas Dangel 11/2014
|
|
|
|
*====================================================================
|
2014-09-30 19:51:42 +02:00
|
|
|
* Fix for Lambda expressions with two or three variables.
|
|
|
|
*
|
|
|
|
* Andreas Dangel 07/2014
|
|
|
|
*====================================================================
|
|
|
|
* Added support for Java 8 language constructs.
|
|
|
|
*
|
|
|
|
* Andreas Dangel 01/2014
|
|
|
|
* ===================================================================
|
|
|
|
* Fix ForStatement to allow Annotations within the initializer.
|
|
|
|
*
|
|
|
|
* Andreas Dangel 01/2013
|
|
|
|
* ===================================================================
|
2019-01-08 23:30:51 +01:00
|
|
|
* Fix wrong consumption of modifiers (e.g. "final") in a for-each loop.
|
2014-09-30 19:51:42 +02:00
|
|
|
* Check for wrong java usage when catching multiple exceptions.
|
|
|
|
*
|
|
|
|
* Andreas Dangel 12/2012
|
|
|
|
* ===================================================================
|
|
|
|
* Enhance grammar to use LocalVariableDeclaration in a for-each loop.
|
|
|
|
* This enhances the symbol table to recognize variables declared in such
|
|
|
|
* a for-each loop.
|
|
|
|
*
|
|
|
|
* Andreas Dangel 10/2012
|
|
|
|
* ===================================================================
|
|
|
|
* Fix parser problem #3530124 with generics
|
|
|
|
*
|
|
|
|
* Modified the grammar, so that the different usages of generics work.
|
|
|
|
* Adjusted the rules, that use "super", as super is no longer a PrimarySuffix.
|
|
|
|
* It's now either a ExplicitConstructorInvocation or a PrimaryPrefix.
|
|
|
|
* See also test case ParserCornersTest/testParsersCases
|
|
|
|
*
|
|
|
|
* Andreas Dangel 05/2012
|
|
|
|
* ===================================================================
|
|
|
|
* Added support for Java 7 language constructs
|
|
|
|
*
|
|
|
|
* Dinesh Bolkensteyn (SonarSource), 10/2011
|
|
|
|
* ===================================================================
|
|
|
|
* Changed the CastLookahead production to use 3 lookaheads for primitive types as suggested by Andreas Dangel
|
|
|
|
*
|
|
|
|
* Brian Remedios 07/2011
|
|
|
|
* ===================================================================
|
|
|
|
* Added in support for assert as a name using lookaheads
|
|
|
|
*
|
|
|
|
* Tom Copeland, 09/03
|
|
|
|
* ===================================================================
|
|
|
|
* Copied over the changes made by Andrea Gini and Marco Savard to
|
|
|
|
* support JDK 1.4 language constructs, i.e., asserts.
|
|
|
|
* See the java1_4c.jj distributed in the javacc2.1/examples/JavaGrammers directory.
|
|
|
|
* Made numerous other modifications to support PMD.
|
|
|
|
*
|
|
|
|
* Tom Copeland, 6/02
|
|
|
|
* ===================================================================
|
|
|
|
* This file is a modified version of one originally found in the
|
|
|
|
* VTransformer Examples directory of JavaCC1_1. It has been
|
|
|
|
* modified to accept Java source code for Java 1.2. Basically,
|
|
|
|
* this means a new key word was added, 'strictfp', and that keyword
|
|
|
|
* added to the appropriate productions and LOOKAHEADs (where other,
|
|
|
|
* similar keywords are listed as possible choices). This involved
|
|
|
|
* changing 11 lines.
|
|
|
|
*
|
|
|
|
* Some other minor changes were made, which can be found by doing
|
|
|
|
* a search on 'DW, 7/99'.
|
|
|
|
*
|
|
|
|
* The goal of this effort was for the grammar to be able to parse
|
|
|
|
* any legal Java 1.2 source code. It does not reject all illegal
|
|
|
|
* cases, but neither did the original. Plus, when it comes to
|
|
|
|
* the new 'strictfp' keyword, the Java Compiler from Sun (JDK1.2.1)
|
|
|
|
* also does not reject all illegal cases, as defined by the
|
|
|
|
* "Updates" document found at
|
|
|
|
* http://java.sun.com/docs/books/jls/strictfp-changes.pdf
|
|
|
|
* (see the testcases.txt file for details).
|
|
|
|
*
|
|
|
|
* David Williams, 7/99
|
|
|
|
* ===================================================================
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Copyright (C) 1996, 1997 Sun Microsystems Inc.
|
|
|
|
*
|
|
|
|
* Use of this file and the system it is part of is constrained by the
|
|
|
|
* file COPYRIGHT in the root directory of this system. You may, however,
|
|
|
|
* make any modifications you wish to this file.
|
|
|
|
*
|
|
|
|
* Java files generated by running JavaCC on this file (or modified versions
|
|
|
|
* of this file) may be used in exactly the same manner as Java files
|
|
|
|
* generated from any grammar developed by you.
|
|
|
|
*
|
|
|
|
* Author: Sriram Sankar
|
|
|
|
* Date: 3/5/97
|
|
|
|
*
|
|
|
|
* This file contains a Java grammar and actions that implement a front-end.
|
|
|
|
*/
|
|
|
|
|
|
|
|
options {
|
2020-01-11 05:22:29 +01:00
|
|
|
UNICODE_INPUT=true;
|
2014-09-30 19:51:42 +02:00
|
|
|
CACHE_TOKENS = true;
|
|
|
|
STATIC = false;
|
|
|
|
MULTI = true;
|
|
|
|
VISITOR = true;
|
|
|
|
NODE_PACKAGE="net.sourceforge.pmd.lang.java.ast";
|
|
|
|
|
2021-03-04 20:16:37 +01:00
|
|
|
// disable the calculation of expected tokens when a parse error occurs
|
|
|
|
// depending on the possible allowed next tokens, this
|
|
|
|
// could be expensive (see https://github.com/pmd/pmd/issues/3117)
|
|
|
|
//ERROR_REPORTING = false;
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
//DEBUG_PARSER = true;
|
|
|
|
//DEBUG_LOOKAHEAD = true;
|
2019-08-13 20:00:40 +02:00
|
|
|
//DEBUG_TOKEN_MANAGER = true;
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 05:22:29 +01:00
|
|
|
PARSER_BEGIN(JavaParserImpl)
|
2014-09-30 19:51:42 +02:00
|
|
|
package net.sourceforge.pmd.lang.java.ast;
|
2023-08-10 11:27:53 +02:00
|
|
|
import java.util.ArrayDeque;
|
2014-09-30 19:51:42 +02:00
|
|
|
import java.util.ArrayList;
|
2019-07-01 15:55:14 +02:00
|
|
|
import java.util.Collections;
|
2023-08-10 11:27:53 +02:00
|
|
|
import java.util.Deque;
|
2019-07-01 15:55:14 +02:00
|
|
|
import java.util.EnumSet;
|
2014-09-30 19:51:42 +02:00
|
|
|
import java.util.List;
|
2019-07-01 15:55:14 +02:00
|
|
|
import java.util.Set;
|
2014-09-30 19:51:42 +02:00
|
|
|
import java.util.Map;
|
2019-12-16 07:36:47 +01:00
|
|
|
import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken;
|
2020-08-16 21:37:39 +02:00
|
|
|
import net.sourceforge.pmd.lang.ast.Node;
|
New typeres framework
Ceci est la combinaison de 338+ commits.
Make set of classes to mirror types
Implement capture conversion
Document
Doc
Implement contains for targs
Implement toString
Fully implement subtyping
Check for reifiability
Implement unchecked, fix array subtyping
Test rec typevar building
Test primitive subtyping
Test array subtyping
Test wildcards subtyping
Doc
Rename primitiveType
Reify conversions
Test boxing
Make constants for common types
Test type param mutual recursion
More defensive validation
Implement numeric promotion
Checkstyle
Implement supertype set
Implement lub
Fix infinite recursion
Fix lub bugs
Use linkedhashset for stable ordering
Add primitives to common types
Move common types into type factory
Try a lazy class resolver, needs a symbol table
Improve lazy resolver
Implement conditional expr typing
remove poly impl
Represent primitive wrappers differently
Better compromise for primitive wrappers
Extract wildcard interface
Extract array type interface
Refactor to extract interfaces
Don't depend on initialization of jprimitiveType
Finish pretty printer
Remove dependency on reflection
Fix class initialization trouble
Move to type constants
Use regular impl for OBJECT
Encapsulate ops into TypeOps
Add inference var to model
Impl some ops
Add some type inference algos
Invocation context compatibility
Add incorporation
Generify bound set with ExprOps
Add applicability tests
Fix compil
Add incorporation actions
Implement incorporation
Add inference steps
Implement brute force walk strategy
Remove some type params
Wire in everything
Implement methodtype
Access methods from JClassType
Represent enclosing types
Work on overriding
Implement expr ops
Catch easy cases
Diamond inference
Fix pretty printer
Fix concurrent mod
Test
Add reflect info to JModifier
Add symbolic type declaration
Most specific check
Test with nested invocation
Test lub
Add constraints for lambdas and all subexpressions
Resolve full call chain with lambdas
Set partial results on nodes
Test chain
Doc
Generalise expr mirrors
Fix context
Add invocation mirror
Add support for method references
make infer static
Cleanup interface
Fix constructor access
Test method reference
Cleanup method ref types
Test constructor reference
Test overload resolution, fix TODO
Fix ctdecl of mref on non-ground target type
Add graph walk strategy
Document
Use toposort
Make enum constant implement ctor invoc mirror
Work on context
Test conditional expr type
Handle switch exprs uniformly
Fix bugs
Add type inference performance test case
Add overload resolution tests
Cache result of overload selection, only recompute invocation
Optimise common case in graph building
Optimise propagation by merging variables
Fix some tests, cleanup
Preserve applicability phase
Improve jsinglechildnode
Add way to get a field's type
Make more complex stress test
Cache bound check results
Type projection for inference
Simplify lazy type inference of var ids
Improve memory usage
- reuse constant enum sets (by far the biggest leak, given the number of PropagateBounds created)
- implement substitution without a visitor
Optimise imports
Cache hash of classes
Cleanup
Add overloads test
Fix context fetching
Fix lub bug
Test switch expr
Fix rebase
Remove useless type
Factorise poly check
Remove base poly expr
Fix array initializer
Remove duplicated numeric literal typing
Fix inferred iterable type
Move method resolution phase to upper level
Delete useless var
Commit pr plan
Remove useless method
Fix enclosing type comb rule
REVERT ME Remove partial enclosing type support
Add package info
Put task list in branch description
Fix old rebases
Fix rebase
Simplify for left recursive ops
Fix comments
Fix rebase
Revert "REVERT ME Remove partial enclosing type support"
This reverts commit 8080ff1585b3a760fafc957282771baf716f3c7f.
WIP base type mirrors on symbols
Make JMethodType not a JTypeMirror
Figure out getSymbol & type vars
make type factory non-static
Add a parameter to visitors
Fix compilation
Use symbol table in lazy type resolver
Move package
Fix most tests
Move internal api around
Specify some stuff
Split reflect impl from API
Make AST impl
Equality routines
Fix tests
Move internal symtable doc
Improve symtableResolver ergonomics
Poly res tests
Make AST type factory
Update
Make lambda expressions not a MethodlikeNode
Build local var sym
Update for switches
Make Infer not static, fix logging
Don't expose visitor nature of SymbolResolver
Cleanup
Improve type error handling
Don't throw away CTdecls for an arg mismatch
Fix more tests
Local symbol tables
Symbol table looks in interfaces
Incompatible changes that should stay on this branch and not be squashed
ResolveResult
Explicitly typed lambdas
Fix some static bugs
Fix a lot of bugs
Use FQCN symtable
Move parsing contexts to upper level
Cleanup
DSL to test types
test subst
Dont create an exception for each failure
Stack trace creation takes a significant amount of time
Remove laziness for fetching method streams
Streams obfuscate performance analysis by
delaying the computation until the last
moment.
Fix some bugs with unresolved classes
Also measure performance: full typeres
is around same time as parsing. This is
great. At this point 80% of all types
are resolved (though some type inference
results are probably incorrect). Mostly
this comes from the fact that there are
still AmbiguousNames in the tree.
Fix problem with varargs
Handle enclosing types
Enclosing types
Fix compil
Add another stress test
Refactor primitive subtyping
Fix rebase
Fix rebase: tests
Figure out type factories WIP
Move type ops into TypeOps
Move AsSuper
Figure out type factories WIP
Make TypeSystem object
wip
WIP
WIP
Make typeops static
Fix grounding routine
Fix bug with return type
Start fixing tests
Cleanup primitive types
Fix some tests
Add todo
Remove JDK test dependency
Test cases lubbing String and
StringBuilder produce different
outputs on JDK [8, 11[ and 11+, because
StringBuilder was made a Comparable<StringBuilder>
in JDK 11
Implement most specific method selection
Drop JVariableSig from symbol table
Use asOuterSuper instead
Fix local var type inference with foreach.
Fix a lot of stuff based on jdk 12 run
Make type system own symbol factories
Fix intersection with bound
Fix standalone ternary types
Capture field access type
Eg class Foo<T> { T[] field; }
Foo<? extends T>.field : capture(T)[]
Add tests
Delete lexical substs
Fix reflected owner type
Add graph viz
Fix bug with graph reduction
Optimise ivar dependency reduction
by a lot. The previous 60s stress
test now takes 600ms.
Btw at this point type res for the
whole JDK 12 codebase takes 25 secs,
down from 175 on 6.20.0 (7x speedup).
Implement inherited field/class lookup
Fix scoping inside switch statements
Fix a few bugs
Handle inherited methods
Interfaces should inherit Object methods
Move lub into TypeSystem
Handle class types induced by intersections
Fix lambda congruence
Test lambda with intersection type
Fix inference
Fix same type check using equals
Simplify intersection type induction
Remove type sys extension
Simplify sym factories
Finish symbol factory streamlining
Document
Cache non-erased symbols separately
Doc
Revert, erased types are only raw
Get rid of generic constants in TypeSystem
Remove some dead code
Fix exact method reference
Improve unchecked conversion handling
Fix dependency of delegated ivars
Improve logging, fix a few bugs
Test enclosing types
Improve loggin
Print file location
Fix subtyping for wildcards
Fix standalone method types
Fix boxing conversion
Fix promotion on unary exprs
Implement special treatment of getClass()
Add tests for anon classes
Make symbol tables use lists for methods
Fix method reference with void target type
Move graphUtils
Make unresolved types bottom
(instead of top)
It's more likely to be useful. Eg.
Unresolved var = ...;
knownMethod(var);
Here, var must conform to the parameter,
if it is unresolved, we assume that's the
case. Otherwise we would fail resolution
of knownMethod for this call site.
The reverse situation is rarer.
Fix conversions in loose phase
Make JInferenceVar a class
Hide TypePair
Remove special string type
Fix toString of anon classes
Implement overload specificity for generic methdos
Fix anon class ctors
Fix Object methods not in scope in interfaces
Fixing anon class ctors WIP
Fix rebase
Cleanup
Print type var bounds
Fix tests, improve pretty printing
Hide ast sym factory
Fix array method erasure
Fix superclass, uncover bug with substitution
Substitute type param bounds
Make Array have Object methods
Fix duplicated logging categories
Make root symbolFactory thread safe
Fix overload ambiguity with hiding
Fix exact method when they shadow each other
Make PMultimap type
Make shadowGroup
Make a few utilities to replace import tables
Replace other tables
Cleanup
Compat with old impl
Fix rebase
Port to using sigs
Make base class for shadow groups
Fix method group
Test shadowing of inherited members
Fix bugs with tparams
Specialize to StringMultimap
Big optimizations
Simplify a lot of things, remove caching
of getAllMethods
Factorize group implementations
Add resolveFirst
Fix bug with ctor invocation
Fix type parsing for union types
Generify multimap
Implement nextShadowGroup
Remove unused API of pmultimap
Use interface where possible
Fix tests
Use singleton resolvers more frequently
Remove commons collections dependency
Tries don't make a significant difference
in execution time. Mostly because tries
used in symbol tables are very small.
Remove some api of jtypemirror
Fix shadow barriers
Fix accessibility check for protected member
Qualified ctor invocations have access to inner class name
Make strict stream for profiling
LOOK AT ME strict streams
Strict streams are actually *much* more
efficient for our use case
Extract some stuff into CollectionUtil
Make methods shadow each other
doc
Simplify OptionalBool
Improve strict stream
Eventually I'll remove it
Doc newer symtable
Make PMultimap type
Make shadowGroup
Make a few utilities to replace import tables
Cleanup
Checkout newer sym table from typeres branch
Port
Checkout tests
Port tests, remove old impl
Extract augment function
Move classes back into internal package
Abstract stuff away for pmd-core
Optimise singular map case even more
Fix nextShadowGroup WIP
Make ShadowIterator to replace getNextGroup
Use chain iterator
Add tests
Finish impl
Add tests for supertype enumerator
Add tests for method shadowing in imports
Port to using types etc
Fix tests
Fix outdated tests
Fix anon class ctors
Fix more outdated tests
Object methods should be in scope in interfaces
Fix compil
Make simple signature parser
Make stubs
Figure out loading logic
Progress on type param parsing
Do away with nested classes
Class signatures
It works!
Parse tvar bounds lazily
Fix a lot of stuff
No errors on pmd-core
JDK 13 under 80s
Implement toString everywhere
Try to make the whole thing thread safe
Still a spurious NPE, access flags are weird.
For j.l.invoke.DelegatingMethodHandle
(declared as `final class Holder {}`) the
access flags from the class file are 0x32, and
the enclosing type is null, while when accessed
through reflection, the access flags are correctly
0x10. The class is engineered through VM magic
so idk what happens
Remove shared caching of TypeSystem
The sub caches are not useful anymore
and creating them all the time is wasteful
Add some tests
Fix improper locking
Reorganise typeSystem initialization
Change the name
Doc
Opts
Optimise away some expensive lookaheads in the parser
Doc
Fix modifiers
Optimise big switches in parser
Placing token decls that are frequently used together closer
increases the chance that the compiler generate a TABLESWITCH
instruction instead of a LOOKUPSWITCH. Table switches take
constant lookup time, while lookupswitch is linear. Selection
of table switch is now done for the biggest switches of the
parser: the one in types, in modifiers, in statements, and
at the start of expressions. Other lookup switches are unimportant
because they have very few labels (typically 2).
Optimise variable initializer lookahead
make test rule noop
PARSER Optimise common branches in expressions
PARSER opt blocks & statements
doc
Don't accept void by default
Split signature parsers
Simplify type param parsing
Simplify type params parsing
Some optimisations
Tests
Simplify synchronization
Factorize synchronization logic
Move ConsList into pmd-core
Prune more empty nodes
Use single map for asm resolver
Remove changes to parser
Add option to suppress type inference log entry creation
Use soft references to allow class stubs to be GCed
Fix rebase
2020-02-11 04:43:54 +01:00
|
|
|
import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind;
|
2018-11-06 04:22:31 +01:00
|
|
|
|
2020-01-11 05:22:29 +01:00
|
|
|
class JavaParserImpl {
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
|
|
private int jdkVersion = 0;
|
2019-09-11 20:18:12 +02:00
|
|
|
private boolean preview = false;
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
|
|
public void setJdkVersion(int jdkVersion) {
|
|
|
|
this.jdkVersion = jdkVersion;
|
|
|
|
}
|
|
|
|
|
2019-09-11 20:18:12 +02:00
|
|
|
public void setPreview(boolean preview) {
|
|
|
|
this.preview = preview;
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
private void throwParseException(String message) {
|
2023-03-19 22:49:45 +01:00
|
|
|
throw new ParseException(message).withLocation(token);
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-08-22 20:48:21 +02:00
|
|
|
|
|
|
|
private boolean isRecordTypeSupported() {
|
2022-03-10 16:08:48 +01:00
|
|
|
return jdkVersion >= 16;
|
2020-08-22 20:48:21 +02:00
|
|
|
}
|
|
|
|
|
2020-08-23 15:38:21 +02:00
|
|
|
private boolean localTypesSupported() {
|
|
|
|
return isRecordTypeSupported();
|
|
|
|
}
|
|
|
|
|
2019-03-15 20:51:53 +01:00
|
|
|
/**
|
|
|
|
* Keeps track during tree construction, whether we are currently building a switch label.
|
|
|
|
* A switch label must not contain a LambdaExpression.
|
|
|
|
* Unfortunately, we have added LambdaExpression as part of PrimaryPrefix, which is wrong.
|
|
|
|
* To keep compatibility, this flag is used, whether a LambdaExpression should be parsed
|
|
|
|
* in PrimaryPrefix.
|
|
|
|
* See also comment at #Expression().
|
|
|
|
*/
|
|
|
|
private boolean inSwitchLabel = false;
|
2019-03-16 10:47:12 +01:00
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
// This is a semantic LOOKAHEAD to determine if we're dealing with an assert
|
|
|
|
// Note that this can't be replaced with a syntactic lookahead
|
|
|
|
// since "assert" isn't a string literal token
|
2020-08-23 15:38:21 +02:00
|
|
|
private boolean isAssertStart() {
|
2018-04-30 12:54:08 -03:00
|
|
|
if (jdkVersion <= 3) {
|
|
|
|
return false;
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
2019-09-27 06:21:08 +02:00
|
|
|
|
2020-02-07 23:43:26 +01:00
|
|
|
return getToken(1).getImage().equals("assert");
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-08-23 15:38:21 +02:00
|
|
|
private boolean isRecordStart() {
|
2021-03-05 11:54:58 +01:00
|
|
|
return isRecordTypeSupported() && isKeyword("record") && isToken(2, IDENTIFIER);
|
2020-08-23 15:38:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isEnumStart() {
|
|
|
|
return jdkVersion >= 5 && isKeyword("enum");
|
|
|
|
}
|
|
|
|
|
2017-09-22 23:43:43 +02:00
|
|
|
/**
|
|
|
|
* Semantic lookahead to check if the next identifier is a
|
|
|
|
* specific restricted keyword.
|
2020-08-14 22:16:41 +02:00
|
|
|
*
|
|
|
|
* <p>Restricted keywords are:
|
2020-08-16 18:22:45 +02:00
|
|
|
* var, yield, record, sealed, permits, "non" + "-" + "sealed"
|
2020-08-14 22:16:41 +02:00
|
|
|
*
|
|
|
|
* <p>enum and assert is used like restricted keywords, as they were not keywords
|
|
|
|
* in the early java versions.
|
2017-09-22 23:43:43 +02:00
|
|
|
*/
|
2020-08-16 18:22:45 +02:00
|
|
|
private boolean isKeyword(String image) {
|
|
|
|
return isKeyword(1, image);
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isKeyword(int index, String image) {
|
|
|
|
Token token = getToken(index);
|
|
|
|
return token.kind == IDENTIFIER && token.image.equals(image);
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isToken(int index, int kind) {
|
|
|
|
return getToken(index).kind == kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Semantic lookahead which matches "non-sealed".
|
|
|
|
*
|
|
|
|
* <p>"non-sealed" cannot be a token, for several reasons:
|
|
|
|
* It is only a keyword with java15 preview+, it consists actually
|
|
|
|
* of several separate tokens, which are valid on their own.
|
2017-09-22 23:43:43 +02:00
|
|
|
*/
|
2020-08-16 18:22:45 +02:00
|
|
|
private boolean isNonSealedModifier() {
|
|
|
|
if (isKeyword(1, "non") && isToken(2, MINUS) && isKeyword(3, "sealed")) {
|
2020-08-22 20:48:21 +02:00
|
|
|
JavaccToken nonToken = getToken(1);
|
|
|
|
JavaccToken minusToken = getToken(2);
|
|
|
|
JavaccToken sealedToken = getToken(3);
|
2023-12-14 09:40:26 +01:00
|
|
|
return nonToken.getReportLocation().getEndColumn() == minusToken.getReportLocation().getStartColumn()
|
|
|
|
&& minusToken.getReportLocation().getEndColumn() == sealedToken.getReportLocation().getStartColumn();
|
2020-08-16 18:22:45 +02:00
|
|
|
}
|
|
|
|
return false;
|
2017-09-22 23:43:43 +02:00
|
|
|
}
|
|
|
|
|
2021-07-30 11:06:51 +02:00
|
|
|
private boolean classModifierForLocalTypesLookahead() {
|
2020-08-16 21:37:39 +02:00
|
|
|
Token next = getToken(1);
|
|
|
|
return next.kind == AT
|
|
|
|
|| next.kind == PUBLIC
|
|
|
|
|| next.kind == PROTECTED
|
|
|
|
|| next.kind == PRIVATE
|
|
|
|
|| next.kind == ABSTRACT
|
|
|
|
|| next.kind == STATIC
|
|
|
|
|| next.kind == FINAL
|
2021-07-30 11:06:51 +02:00
|
|
|
|| next.kind == STRICTFP;
|
2020-08-16 21:37:39 +02:00
|
|
|
}
|
|
|
|
|
2020-08-23 15:38:21 +02:00
|
|
|
private boolean localTypeDeclAfterModifiers() {
|
2020-08-16 21:37:39 +02:00
|
|
|
Token next = getToken(1);
|
|
|
|
return next.kind == CLASS
|
2020-08-23 15:38:21 +02:00
|
|
|
|| localTypesSupported() && (
|
|
|
|
next.kind == INTERFACE
|
|
|
|
|| next.kind == AT && isToken(2, INTERFACE)
|
|
|
|
|| next.kind == IDENTIFIER && next.getImage().equals("enum")
|
2021-03-05 11:54:58 +01:00
|
|
|
|| next.kind == IDENTIFIER && next.getImage().equals("record") && isToken(2, IDENTIFIER)
|
2020-08-23 15:38:21 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean localTypeDeclGivenNextIsIdent() {
|
2021-07-30 11:15:31 +02:00
|
|
|
return localTypesSupported() && (isRecordStart() || isEnumStart());
|
2017-09-22 23:43:43 +02:00
|
|
|
}
|
|
|
|
|
2020-03-17 20:27:14 +01:00
|
|
|
/**
|
|
|
|
* True if we're in a switch block, one precondition for parsing a yield
|
|
|
|
* statement.
|
|
|
|
*/
|
2020-03-17 21:36:15 +01:00
|
|
|
private boolean inSwitchExprBlock = false;
|
2020-03-17 20:27:14 +01:00
|
|
|
|
|
|
|
private boolean isYieldStart() {
|
2020-04-04 18:54:49 +02:00
|
|
|
return inSwitchExprBlock
|
2020-03-17 20:27:14 +01:00
|
|
|
&& isKeyword("yield")
|
|
|
|
&& mayStartExprAfterYield(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean mayStartExprAfterYield(final int offset) {
|
|
|
|
// based off of https://hg.openjdk.java.net/jdk/jdk/file/bc3da0226ffa/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java#l2580
|
|
|
|
// please don't sue me
|
2020-04-08 21:06:19 +02:00
|
|
|
JavaccToken token = getToken(offset);
|
2020-03-17 20:27:14 +01:00
|
|
|
if (token == null) return false; // eof
|
|
|
|
switch (token.kind) {
|
|
|
|
case PLUS: case MINUS: case STRING_LITERAL: case CHARACTER_LITERAL:
|
|
|
|
case INTEGER_LITERAL: case FLOATING_POINT_LITERAL: case HEX_FLOATING_POINT_LITERAL:
|
|
|
|
case NULL: case IDENTIFIER: case TRUE: case FALSE:
|
|
|
|
case NEW: case SWITCH: case THIS: case SUPER:
|
|
|
|
return true;
|
|
|
|
case INCR: case DECR:
|
|
|
|
return getToken(offset + 1).kind != SEMICOLON; // eg yield++;
|
|
|
|
case LPAREN:
|
|
|
|
int lookahead = offset + 1;
|
|
|
|
int balance = 1;
|
2020-04-08 21:06:19 +02:00
|
|
|
JavaccToken t;
|
2020-03-17 20:27:14 +01:00
|
|
|
while ((t = getToken(lookahead)) != null && balance > 0) {
|
|
|
|
switch (t.kind) {
|
|
|
|
case LPAREN: balance++; break;
|
|
|
|
case RPAREN: balance--; break;
|
|
|
|
case COMMA: if (balance == 1) return false; // a method call, eg yield(1, 2);
|
|
|
|
}
|
|
|
|
lookahead++;
|
|
|
|
}
|
|
|
|
// lambda: yield () -> {};
|
|
|
|
// method call: yield ();
|
2020-03-17 21:36:15 +01:00
|
|
|
return t != null
|
|
|
|
&& (lookahead != offset + 2 // ie ()
|
|
|
|
|| t.kind == LAMBDA);
|
2020-03-17 20:27:14 +01:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-30 15:48:55 +02:00
|
|
|
private boolean shouldStartStatementInSwitch() {
|
|
|
|
switch (getToken(1).kind) {
|
|
|
|
case _DEFAULT:
|
|
|
|
case CASE:
|
|
|
|
case RBRACE:
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
public Map<Integer, String> getSuppressMap() {
|
|
|
|
return token_source.getSuppressMap();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setSuppressMarker(String marker) {
|
|
|
|
token_source.setSuppressMarker(marker);
|
|
|
|
}
|
|
|
|
|
2020-05-02 20:54:41 +02:00
|
|
|
private void setLastTokenImage(AbstractJavaNode node) {
|
2019-02-17 11:36:18 +01:00
|
|
|
node.setImage(getToken(0).getImage());
|
|
|
|
}
|
2014-09-30 19:51:42 +02:00
|
|
|
|
2020-08-23 15:38:21 +02:00
|
|
|
private void fixLastToken() {
|
|
|
|
AbstractJavaNode top = (AbstractJavaNode) jjtree.peekNode();
|
|
|
|
top.setLastToken(getToken(0));
|
|
|
|
}
|
|
|
|
|
2019-03-21 20:47:23 +01:00
|
|
|
private void forceExprContext() {
|
2020-01-28 14:01:40 +01:00
|
|
|
AbstractJavaNode top = jjtree.peekNode();
|
2019-03-21 20:47:23 +01:00
|
|
|
|
|
|
|
if (top instanceof ASTAmbiguousName) {
|
|
|
|
// see doc on the method
|
2020-01-28 14:01:40 +01:00
|
|
|
AbstractJavaNode replacement = (AbstractJavaNode) ((ASTAmbiguousName) top).forceExprContext();
|
2019-03-21 20:47:23 +01:00
|
|
|
jjtree.popNode();
|
|
|
|
jjtree.pushNode(replacement);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
private void pushEmptyModifierList() {
|
|
|
|
ASTModifierList emptyMods = new ASTModifierList(JJTMODIFIERLIST);
|
|
|
|
|
|
|
|
emptyMods.setDeclaredModifiers(Collections.emptySet());
|
|
|
|
|
2020-03-02 22:42:18 +01:00
|
|
|
JavaccToken tok = JavaccToken.implicitBefore(getToken(1));
|
2020-05-02 20:54:41 +02:00
|
|
|
emptyMods.setFirstToken(tok);
|
|
|
|
emptyMods.setLastToken(tok);
|
2019-07-01 15:55:14 +02:00
|
|
|
|
|
|
|
jjtree.pushNode(emptyMods);
|
|
|
|
}
|
|
|
|
|
2021-02-18 12:58:13 +01:00
|
|
|
private void insertEmptyModifierListWithAnnotations(AbstractJavaNode node, AbstractJavaNode nodeWithAnnotations) {
|
|
|
|
ASTModifierList emptyMods = new ASTModifierList(JJTMODIFIERLIST);
|
|
|
|
|
|
|
|
emptyMods.setDeclaredModifiers(Collections.emptySet());
|
|
|
|
|
|
|
|
JavaccToken tok = JavaccToken.implicitBefore(node.getFirstToken());
|
|
|
|
emptyMods.setFirstToken(tok);
|
|
|
|
emptyMods.setLastToken(tok);
|
|
|
|
|
|
|
|
List<ASTAnnotation> annotations = new ArrayList<ASTAnnotation>();
|
|
|
|
while (nodeWithAnnotations.getNumChildren() > 0 && nodeWithAnnotations.getChild(0) instanceof ASTAnnotation) {
|
|
|
|
ASTAnnotation annotation = (ASTAnnotation) nodeWithAnnotations.getChild(0);
|
|
|
|
nodeWithAnnotations.removeChildAtIndex(0);
|
|
|
|
annotations.add(annotation);
|
|
|
|
}
|
|
|
|
for (int i = 0; i < annotations.size(); i++) {
|
|
|
|
emptyMods.addChild(annotations.get(i), i);
|
|
|
|
}
|
|
|
|
if (!annotations.isEmpty()) {
|
|
|
|
emptyMods.setFirstToken(annotations.get(0).getFirstToken());
|
|
|
|
emptyMods.setLastToken(annotations.get(annotations.size() - 1).getLastToken());
|
|
|
|
}
|
|
|
|
|
|
|
|
node.insertChild(emptyMods, 0);
|
|
|
|
}
|
|
|
|
|
2019-04-03 14:48:48 +02:00
|
|
|
private void forceTypeContext() {
|
2020-01-28 14:01:40 +01:00
|
|
|
AbstractJavaNode top = jjtree.peekNode();
|
2019-04-03 14:48:48 +02:00
|
|
|
|
2019-05-28 19:16:04 +02:00
|
|
|
if (top instanceof ASTAmbiguousName) {
|
|
|
|
// see doc on the method
|
2020-01-28 14:01:40 +01:00
|
|
|
AbstractJavaNode replacement = ((ASTAmbiguousName) top).forceTypeContext();
|
2019-05-28 19:16:04 +02:00
|
|
|
jjtree.popNode();
|
|
|
|
jjtree.pushNode(replacement);
|
|
|
|
}
|
2019-04-03 14:48:48 +02:00
|
|
|
}
|
2014-09-30 19:51:42 +02:00
|
|
|
|
2019-05-28 19:16:04 +02:00
|
|
|
|
2019-05-29 13:12:43 +02:00
|
|
|
// make the top node the last child of the second node on the stack
|
|
|
|
// If the stack ends with ..[A][B], then it becomes ..[A[B]]
|
2019-05-24 16:33:48 +02:00
|
|
|
private void injectTop() {
|
|
|
|
AbstractJavaNode top = (AbstractJavaNode) jjtree.popNode();
|
|
|
|
AbstractJavaNode prev = (AbstractJavaNode) jjtree.peekNode();
|
2020-05-02 20:54:41 +02:00
|
|
|
prev.addChild(top, prev.getNumChildren());
|
|
|
|
prev.setLastToken(top.getLastToken());
|
2019-05-24 16:33:48 +02:00
|
|
|
}
|
|
|
|
|
2023-08-10 12:13:12 +02:00
|
|
|
/**
|
2019-05-24 17:29:36 +02:00
|
|
|
* Keeps track during tree construction, whether we are currently building an
|
|
|
|
* explicit constructor invocation. Then the PrimaryExpression that may prefix
|
|
|
|
* a qualified super constructor call may not consume "super" tokens.
|
|
|
|
*/
|
|
|
|
private boolean inExplicitConstructorInvoc = false;
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
2020-01-11 05:22:29 +01:00
|
|
|
PARSER_END(JavaParserImpl)
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
|
|
TOKEN_MGR_DECLS :
|
|
|
|
{
|
2022-03-07 22:00:14 +01:00
|
|
|
protected List<JavaComment> comments = new ArrayList<JavaComment>();
|
2024-04-12 17:59:10 +02:00
|
|
|
private Deque<Boolean> savedTemplateKind = new ArrayDeque<Boolean>();
|
|
|
|
private Deque<Integer> braceDepthInTemplate = new ArrayDeque<Integer>();
|
|
|
|
private int braceDepthCurrentTemplate;
|
|
|
|
private boolean templateKind;
|
2023-08-04 17:13:48 +02:00
|
|
|
|
|
|
|
private static final java.util.regex.Pattern TEXT_BLOCK_TEMPLATE_END_PATTERN =
|
|
|
|
java.util.regex.Pattern.compile("^}[^\"]*\"\"\"");
|
|
|
|
private static final java.util.regex.Pattern STRING_TEMPLATE_MID_OR_END_PATTERN =
|
|
|
|
java.util.regex.Pattern.compile("^}(?:[^\"\\\\\n\r]|\\\\(?:[ntbrfs\\\\'\"]|[0-7][0-7]?|[0-3][0-7][0-7]))*(\\{|\")");
|
|
|
|
|
2024-04-12 17:59:10 +02:00
|
|
|
private void pushBrace() {
|
|
|
|
braceDepthCurrentTemplate++;
|
|
|
|
}
|
|
|
|
private void pushTemplate(boolean isTextBlockTemplate) {
|
|
|
|
braceDepthInTemplate.push(braceDepthCurrentTemplate);
|
|
|
|
savedTemplateKind.push(templateKind);
|
|
|
|
templateKind = isTextBlockTemplate;
|
|
|
|
braceDepthCurrentTemplate = 1;
|
|
|
|
}
|
|
|
|
private boolean isInTemplate() {
|
|
|
|
return braceDepthCurrentTemplate > 0;
|
|
|
|
}
|
|
|
|
private void popBrace() {
|
|
|
|
if (!isInTemplate())
|
|
|
|
return;
|
|
|
|
if (--braceDepthCurrentTemplate == 0) {
|
|
|
|
// this brace ends the template
|
|
|
|
popTemplate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void popTemplate() {
|
|
|
|
boolean isInTextBlockTemplate = templateKind;
|
|
|
|
if (!braceDepthInTemplate.isEmpty()) {
|
|
|
|
braceDepthCurrentTemplate = braceDepthInTemplate.pop();
|
|
|
|
templateKind = savedTemplateKind.pop();
|
|
|
|
if (isInTextBlockTemplate) {
|
|
|
|
SwitchTo(JavaTokenKinds.IN_TEXT_BLOCK_LITERAL);
|
|
|
|
} else {
|
|
|
|
SwitchTo(JavaTokenKinds.IN_STRING_TEMPLATE);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SwitchTo(JavaTokenKinds.DEFAULT);
|
|
|
|
}
|
2023-08-04 17:13:48 +02:00
|
|
|
}
|
|
|
|
private net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken rereadTokenAs(int kind, int length) {
|
|
|
|
input_stream.backup(lengthOfMatch);
|
|
|
|
try {
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
input_stream.readChar();
|
|
|
|
}
|
|
|
|
} catch (java.io.EOFException eofException) {
|
|
|
|
throw new IllegalStateException(eofException);
|
|
|
|
}
|
|
|
|
jjmatchedKind = kind;
|
|
|
|
return jjFillToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
private net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken handleBlock() {
|
|
|
|
net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken matchedToken = rereadTokenAs(JavaTokenKinds.RBRACE, 1);
|
|
|
|
if (!"}".equals(input_stream.getTokenImage())) {
|
|
|
|
throw new IllegalStateException("Expected '}'");
|
|
|
|
}
|
|
|
|
return matchedToken;
|
|
|
|
}
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* WHITE SPACE */
|
|
|
|
|
|
|
|
SPECIAL_TOKEN :
|
|
|
|
{
|
2020-01-10 18:26:50 +01:00
|
|
|
// those are private, just for code organisation
|
2019-09-14 15:31:03 +02:00
|
|
|
< #HORIZONTAL_WHITESPACE: [" ", "\t", "\f"] >
|
|
|
|
| < #LINE_TERMINATOR: "\n" | "\r" | "\r\n" >
|
|
|
|
// this one is pushed, notice the (..)+ construct, to avoid
|
|
|
|
// creating one token per character
|
|
|
|
| < WHITESPACE: ([" ", "\t", "\f", "\n", "\r"])+ >
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-09-14 15:31:03 +02:00
|
|
|
/* COMMENTS */
|
|
|
|
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
SPECIAL_TOKEN :
|
|
|
|
{
|
2019-09-14 15:31:03 +02:00
|
|
|
< SINGLE_LINE_COMMENT: "//"(~["\n","\r"])* ("\n"|"\r"|"\r\n")? >
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-06-08 22:05:10 +02:00
|
|
|
int startOfNOPMD = matchedToken.getImage().indexOf(suppressMarker);
|
2014-09-30 19:51:42 +02:00
|
|
|
if (startOfNOPMD != -1) {
|
2024-02-08 09:56:55 +01:00
|
|
|
suppressMap.put(matchedToken.getReportLocation().getStartLine(), matchedToken.getImage().substring(startOfNOPMD + suppressMarker.length()));
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
2022-03-07 22:00:14 +01:00
|
|
|
comments.add(new JavaComment(matchedToken));
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MORE :
|
|
|
|
{
|
|
|
|
<"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
|
|
|
|
|
|
|
|
|
"/*" : IN_MULTI_LINE_COMMENT
|
|
|
|
}
|
|
|
|
|
|
|
|
<IN_FORMAL_COMMENT>
|
|
|
|
SPECIAL_TOKEN :
|
|
|
|
{
|
2021-12-22 20:04:03 +01:00
|
|
|
<FORMAL_COMMENT: "*/" > { comments.add(new JavadocComment(matchedToken)); } : DEFAULT
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
<IN_MULTI_LINE_COMMENT>
|
|
|
|
SPECIAL_TOKEN :
|
|
|
|
{
|
2022-03-07 22:00:14 +01:00
|
|
|
<MULTI_LINE_COMMENT: "*/" > { comments.add(new JavaComment(matchedToken)); } : DEFAULT
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
<IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
|
|
|
|
MORE :
|
|
|
|
{
|
|
|
|
< ~[] >
|
|
|
|
}
|
|
|
|
|
|
|
|
/* RESERVED WORDS AND LITERALS */
|
|
|
|
|
|
|
|
TOKEN :
|
|
|
|
{
|
|
|
|
< ABSTRACT: "abstract" >
|
|
|
|
| < 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" >
|
|
|
|
| < EXTENDS: "extends" >
|
|
|
|
| < FALSE: "false" >
|
|
|
|
| < FINAL: "final" >
|
|
|
|
| < FINALLY: "finally" >
|
|
|
|
| < FLOAT: "float" >
|
|
|
|
| < FOR: "for" >
|
|
|
|
| < GOTO: "goto" >
|
|
|
|
| < IF: "if" >
|
|
|
|
| < IMPLEMENTS: "implements" >
|
|
|
|
| < IMPORT: "import" >
|
|
|
|
| < INSTANCEOF: "instanceof" >
|
|
|
|
| < INT: "int" >
|
|
|
|
| < INTERFACE: "interface" >
|
|
|
|
| < LONG: "long" >
|
|
|
|
| < NATIVE: "native" >
|
|
|
|
| < NEW: "new" >
|
|
|
|
| < NULL: "null" >
|
|
|
|
| < PACKAGE: "package">
|
|
|
|
| < PRIVATE: "private" >
|
|
|
|
| < PROTECTED: "protected" >
|
|
|
|
| < PUBLIC: "public" >
|
|
|
|
| < RETURN: "return" >
|
|
|
|
| < SHORT: "short" >
|
|
|
|
| < STATIC: "static" >
|
|
|
|
| < SUPER: "super" >
|
|
|
|
| < SWITCH: "switch" >
|
|
|
|
| < SYNCHRONIZED: "synchronized" >
|
|
|
|
| < THIS: "this" >
|
|
|
|
| < THROW: "throw" >
|
|
|
|
| < THROWS: "throws" >
|
|
|
|
| < TRANSIENT: "transient" >
|
|
|
|
| < TRUE: "true" >
|
|
|
|
| < TRY: "try" >
|
|
|
|
| < VOID: "void" >
|
|
|
|
| < VOLATILE: "volatile" >
|
|
|
|
| < WHILE: "while" >
|
|
|
|
| < STRICTFP: "strictfp" >
|
2017-09-22 23:43:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Restricted Keywords */
|
|
|
|
// Note: These are commented out, since these keywords
|
|
|
|
// can still be used as identifiers.
|
|
|
|
// see isKeyword() semantic lookup
|
|
|
|
/*
|
|
|
|
TOKEN :
|
|
|
|
{
|
|
|
|
< OPEN: "open" >
|
2017-09-22 21:35:24 +02:00
|
|
|
| < MODULE: "module" >
|
|
|
|
| < REQUIRES: "requires" >
|
|
|
|
| < TRANSITIVE: "transitive" >
|
|
|
|
| < EXPORTS: "exports" >
|
|
|
|
| < OPENS: "opens" >
|
|
|
|
| < TO: "to" >
|
|
|
|
| < USES: "uses" >
|
|
|
|
| < PROVIDES: "provides" >
|
|
|
|
| < WITH: "with" >
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
2017-09-22 23:43:43 +02:00
|
|
|
*/
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
|
|
/* LITERALS */
|
|
|
|
|
|
|
|
TOKEN :
|
|
|
|
{
|
|
|
|
< INTEGER_LITERAL:
|
2020-01-25 07:05:51 +01:00
|
|
|
<DECIMAL_NUMERAL> (["l","L"])?
|
|
|
|
| <HEX_NUMERAL> (["l","L"])?
|
|
|
|
| <BINARY_NUMERAL> (["l","L"])?
|
|
|
|
| <OCTAL_NUMERAL> (["l","L"])?
|
2014-09-30 19:51:42 +02:00
|
|
|
>
|
2020-01-25 07:05:51 +01:00
|
|
|
| < #DECIMAL_NUMERAL: ["1"-"9"] (("_")* ["0"-"9"])* >
|
|
|
|
| < #HEX_NUMERAL: "0" ["x","X"] <HEX_DIGIT_SEQ> >
|
|
|
|
| < #BINARY_NUMERAL: "0" ["b","B"] ["0","1"] (("_")* ["0","1"])* >
|
|
|
|
| < #OCTAL_NUMERAL: "0" (("_")* ["0"-"7"])* >
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
|
|
|
< FLOATING_POINT_LITERAL:
|
2020-01-25 07:05:51 +01:00
|
|
|
<DECIMAL_FLOATING_POINT_LITERAL>
|
|
|
|
| <HEX_FLOATING_POINT_LITERAL>
|
2014-09-30 19:51:42 +02:00
|
|
|
>
|
2020-01-25 07:05:51 +01:00
|
|
|
| < #DECIMAL_FLOATING_POINT_LITERAL:
|
|
|
|
<DIGIT_SEQ> "." (<DIGIT_SEQ>)? (<EXPONENT>)? (["f","F", "d","D"])?
|
|
|
|
| "." <DIGIT_SEQ> (<EXPONENT>)? (["f","F", "d","D"])?
|
|
|
|
| <DIGIT_SEQ> <EXPONENT> (["f","F", "d","D"])?
|
|
|
|
| <DIGIT_SEQ> (<EXPONENT>)? ["f","F", "d","D"]
|
2019-09-06 15:21:08 +02:00
|
|
|
>
|
2020-01-25 07:05:51 +01:00
|
|
|
| < #HEX_FLOATING_POINT_LITERAL:
|
|
|
|
"0" ["x","X"] <HEX_DIGIT_SEQ> (".")? <HEX_EXPONENT> (["f","F", "d","D"])?
|
|
|
|
| "0" ["x","X"] (<HEX_DIGIT_SEQ>)? "." <HEX_DIGIT_SEQ> <HEX_EXPONENT> (["f","F", "d","D"])?
|
2014-09-30 19:51:42 +02:00
|
|
|
>
|
2020-01-25 07:05:51 +01:00
|
|
|
| < #DIGIT_SEQ: ["0"-"9"] (("_")* ["0"-"9"])* >
|
|
|
|
| < #HEX_DIGIT_SEQ: ["0"-"9","a"-"f","A"-"F"] (("_")* ["0"-"9","a"-"f","A"-"F"])* >
|
|
|
|
|
|
|
|
| < #EXPONENT: ["e","E"] <EXPONENT_TAIL> >
|
|
|
|
| < #HEX_EXPONENT: ["p","P"] <EXPONENT_TAIL> >
|
|
|
|
| < #EXPONENT_TAIL: (["+","-"])? <DIGIT_SEQ> >
|
|
|
|
|
|
|
|
| < CHARACTER_LITERAL: "'" ( ~["'", "\\","\n","\r"] | <STRING_ESCAPE> ) "'" >
|
2023-08-04 17:13:48 +02:00
|
|
|
| < STRING_LITERAL: "\"" (<STRING_CHARACTER>)* "\"" >
|
|
|
|
| < #STRING_CHARACTER: ~["\"","\\","\n","\r"] | <STRING_ESCAPE> >
|
2020-01-25 07:05:51 +01:00
|
|
|
| < #STRING_ESCAPE:
|
|
|
|
"\\"
|
2020-03-02 21:05:21 +01:00
|
|
|
( ["n","t","b","r","f","s","\\","'","\""]
|
2020-01-25 07:05:51 +01:00
|
|
|
// octal escapes
|
|
|
|
| ["0"-"7"] ( ["0"-"7"] )?
|
|
|
|
| ["0"-"3"] ["0"-"7"] ["0"-"7"]
|
|
|
|
)
|
|
|
|
>
|
2023-08-04 17:13:48 +02:00
|
|
|
| < #TEXT_BLOCK_CHARACTER: ~["\\"] | <STRING_ESCAPE> | ("\\")? <LINE_TERMINATOR> >
|
2024-04-12 17:59:10 +02:00
|
|
|
| < #STRING_FRAGMENT: (<STRING_CHARACTER>)* >
|
|
|
|
| < STRING_TEMPLATE_BEGIN: "\"" <STRING_FRAGMENT> "\\{" > { pushTemplate(false); }
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2023-01-26 18:59:55 -03:00
|
|
|
/* TEXT BLOCKS */
|
2023-08-04 17:13:48 +02:00
|
|
|
// note: Text Blocks need an own lexical state, so that we can reliably determine
|
|
|
|
// the end of the text block (""") which is 3 characters long.
|
2023-01-26 18:59:55 -03:00
|
|
|
MORE :
|
|
|
|
{
|
|
|
|
< "\"\"\"" (<HORIZONTAL_WHITESPACE>)* <LINE_TERMINATOR> > : IN_TEXT_BLOCK_LITERAL
|
|
|
|
}
|
|
|
|
|
|
|
|
<IN_TEXT_BLOCK_LITERAL>
|
2024-04-12 17:59:10 +02:00
|
|
|
TOKEN : {
|
2023-01-26 18:59:55 -03:00
|
|
|
<TEXT_BLOCK_LITERAL: "\"\"\"" > : DEFAULT
|
2024-04-12 17:59:10 +02:00
|
|
|
| <TEXT_BLOCK_TEMPLATE_MID: "\\{"> { pushTemplate(true); }: DEFAULT
|
2023-01-26 18:59:55 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
<IN_TEXT_BLOCK_LITERAL>
|
|
|
|
MORE :
|
|
|
|
{
|
2023-08-04 17:13:48 +02:00
|
|
|
< <TEXT_BLOCK_CHARACTER> >
|
2019-08-13 20:00:40 +02:00
|
|
|
}
|
|
|
|
|
2024-04-12 17:59:10 +02:00
|
|
|
<IN_STRING_TEMPLATE>
|
|
|
|
TOKEN:
|
|
|
|
{
|
|
|
|
< STRING_TEMPLATE_END: <STRING_FRAGMENT> "\"" > : DEFAULT
|
|
|
|
| < STRING_TEMPLATE_MID: <STRING_FRAGMENT> "\\{" > { pushTemplate(false); } : DEFAULT
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
/* IDENTIFIERS */
|
|
|
|
|
|
|
|
TOKEN :
|
|
|
|
{
|
2020-01-25 09:52:36 +01:00
|
|
|
< IDENTIFIER : <LETTER> ( <PART_LETTER> )* >
|
|
|
|
// all chars for which Character.isJavaIdentifierStart is true
|
|
|
|
| < #LETTER : ["$","A"-"Z","_","a"-"z","\u00a2"-"\u00a5","\u00aa","\u00b5","\u00ba",
|
|
|
|
"\u00c0"-"\u00d6","\u00d8"-"\u00f6","\u00f8"-"\u021f","\u0222"-"\u0233","\u0250"-"\u02ad",
|
|
|
|
"\u02b0"-"\u02b8","\u02bb"-"\u02c1","\u02d0"-"\u02d1","\u02e0"-"\u02e4","\u02ee","\u037a",
|
|
|
|
"\u0386","\u0388"-"\u038a","\u038c","\u038e"-"\u03a1","\u03a3"-"\u03ce","\u03d0"-"\u03d7",
|
|
|
|
"\u03da"-"\u03f3","\u0400"-"\u0481","\u048c"-"\u04c4","\u04c7"-"\u04c8","\u04cb"-"\u04cc",
|
|
|
|
"\u04d0"-"\u04f5","\u04f8"-"\u04f9","\u0531"-"\u0556","\u0559","\u0561"-"\u0587",
|
|
|
|
"\u05d0"-"\u05ea","\u05f0"-"\u05f2","\u0621"-"\u063a","\u0640"-"\u064a","\u0671"-"\u06d3",
|
|
|
|
"\u06d5","\u06e5"-"\u06e6","\u06fa"-"\u06fc","\u0710","\u0712"-"\u072c","\u0780"-"\u07a5",
|
|
|
|
"\u0905"-"\u0939","\u093d","\u0950","\u0958"-"\u0961","\u0985"-"\u098c","\u098f"-"\u0990",
|
|
|
|
"\u0993"-"\u09a8","\u09aa"-"\u09b0","\u09b2","\u09b6"-"\u09b9","\u09dc"-"\u09dd",
|
|
|
|
"\u09df"-"\u09e1","\u09f0"-"\u09f3","\u0a05"-"\u0a0a","\u0a0f"-"\u0a10","\u0a13"-"\u0a28",
|
|
|
|
"\u0a2a"-"\u0a30","\u0a32"-"\u0a33","\u0a35"-"\u0a36","\u0a38"-"\u0a39","\u0a59"-"\u0a5c",
|
|
|
|
"\u0a5e","\u0a72"-"\u0a74","\u0a85"-"\u0a8b","\u0a8d","\u0a8f"-"\u0a91","\u0a93"-"\u0aa8",
|
|
|
|
"\u0aaa"-"\u0ab0","\u0ab2"-"\u0ab3","\u0ab5"-"\u0ab9","\u0abd","\u0ad0","\u0ae0",
|
|
|
|
"\u0b05"-"\u0b0c","\u0b0f"-"\u0b10","\u0b13"-"\u0b28","\u0b2a"-"\u0b30","\u0b32"-"\u0b33",
|
|
|
|
"\u0b36"-"\u0b39","\u0b3d","\u0b5c"-"\u0b5d","\u0b5f"-"\u0b61","\u0b85"-"\u0b8a",
|
|
|
|
"\u0b8e"-"\u0b90","\u0b92"-"\u0b95","\u0b99"-"\u0b9a","\u0b9c","\u0b9e"-"\u0b9f",
|
|
|
|
"\u0ba3"-"\u0ba4","\u0ba8"-"\u0baa","\u0bae"-"\u0bb5","\u0bb7"-"\u0bb9","\u0c05"-"\u0c0c",
|
|
|
|
"\u0c0e"-"\u0c10","\u0c12"-"\u0c28","\u0c2a"-"\u0c33","\u0c35"-"\u0c39","\u0c60"-"\u0c61",
|
|
|
|
"\u0c85"-"\u0c8c","\u0c8e"-"\u0c90","\u0c92"-"\u0ca8","\u0caa"-"\u0cb3","\u0cb5"-"\u0cb9",
|
|
|
|
"\u0cde","\u0ce0"-"\u0ce1","\u0d05"-"\u0d0c","\u0d0e"-"\u0d10","\u0d12"-"\u0d28",
|
|
|
|
"\u0d2a"-"\u0d39","\u0d60"-"\u0d61","\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"-"\u0edd","\u0f00",
|
|
|
|
"\u0f40"-"\u0f47","\u0f49"-"\u0f6a","\u0f88"-"\u0f8b","\u1000"-"\u1021","\u1023"-"\u1027",
|
|
|
|
"\u1029"-"\u102a","\u1050"-"\u1055","\u10a0"-"\u10c5","\u10d0"-"\u10f6","\u1100"-"\u1159",
|
|
|
|
"\u115f"-"\u11a2","\u11a8"-"\u11f9","\u1200"-"\u1206","\u1208"-"\u1246","\u1248",
|
|
|
|
"\u124a"-"\u124d","\u1250"-"\u1256","\u1258","\u125a"-"\u125d","\u1260"-"\u1286","\u1288",
|
|
|
|
"\u128a"-"\u128d","\u1290"-"\u12ae","\u12b0","\u12b2"-"\u12b5","\u12b8"-"\u12be","\u12c0",
|
|
|
|
"\u12c2"-"\u12c5","\u12c8"-"\u12ce","\u12d0"-"\u12d6","\u12d8"-"\u12ee","\u12f0"-"\u130e",
|
|
|
|
"\u1310","\u1312"-"\u1315","\u1318"-"\u131e","\u1320"-"\u1346","\u1348"-"\u135a",
|
|
|
|
"\u13a0"-"\u13f4","\u1401"-"\u166c","\u166f"-"\u1676","\u1681"-"\u169a","\u16a0"-"\u16ea",
|
|
|
|
"\u1780"-"\u17b3","\u17db","\u1820"-"\u1877","\u1880"-"\u18a8","\u1e00"-"\u1e9b",
|
2022-05-01 18:16:39 +02:00
|
|
|
"\u1ea0"-"\u1ef9","\u1d00"-"\u1eef","\u1f00"-"\u1f15","\u1f18"-"\u1f1d","\u1f20"-"\u1f45","\u1f48"-"\u1f4d",
|
2020-01-25 09:52:36 +01:00
|
|
|
"\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",
|
|
|
|
"\u207f","\u20a0"-"\u20af","\u2102","\u2107","\u210a"-"\u2113","\u2115","\u2119"-"\u211d",
|
|
|
|
"\u2124","\u2126","\u2128","\u212a"-"\u212d","\u212f"-"\u2131","\u2133"-"\u2139",
|
|
|
|
"\u2160"-"\u2183","\u3005"-"\u3007","\u3021"-"\u3029","\u3031"-"\u3035","\u3038"-"\u303a",
|
|
|
|
"\u3041"-"\u3094","\u309d"-"\u309e","\u30a1"-"\u30fe","\u3105"-"\u312c","\u3131"-"\u318e",
|
2022-05-01 17:47:06 +02:00
|
|
|
"\u31a0"-"\u31b7","\u3400"-"\u4db5","\u4e00"-"\u9fa5","\ua000"-"\ua48c","\ua490"-"\uabff","\uac00"-"\ud7a3",
|
2020-01-25 09:52:36 +01:00
|
|
|
"\uf900"-"\ufa2d","\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"-"\ufdfb",
|
|
|
|
"\ufe33"-"\ufe34","\ufe4d"-"\ufe4f","\ufe69","\ufe70"-"\ufe72","\ufe74","\ufe76"-"\ufefc",
|
|
|
|
"\uff04","\uff21"-"\uff3a","\uff3f","\uff41"-"\uff5a","\uff65"-"\uffbe","\uffc2"-"\uffc7",
|
|
|
|
"\uffca"-"\uffcf","\uffd2"-"\uffd7","\uffda"-"\uffdc","\uffe0"-"\uffe1","\uffe5"-"\uffe6"]>
|
|
|
|
|
|
|
|
|
|
|
|
// all chars for which Character.isJavaIdentifierPart is true
|
|
|
|
| < #PART_LETTER: ["\u0000"-"\b","\u000e"-"\u001b","$","0"-"9","A"-"Z","_","a"-"z",
|
|
|
|
"\u007f"-"\u009f","\u00a2"-"\u00a5","\u00aa","\u00b5","\u00ba","\u00c0"-"\u00d6",
|
|
|
|
"\u00d8"-"\u00f6","\u00f8"-"\u021f","\u0222"-"\u0233","\u0250"-"\u02ad","\u02b0"-"\u02b8",
|
|
|
|
"\u02bb"-"\u02c1","\u02d0"-"\u02d1","\u02e0"-"\u02e4","\u02ee","\u0300"-"\u034e",
|
|
|
|
"\u0360"-"\u0362","\u037a","\u0386","\u0388"-"\u038a","\u038c","\u038e"-"\u03a1",
|
|
|
|
"\u03a3"-"\u03ce","\u03d0"-"\u03d7","\u03da"-"\u03f3","\u0400"-"\u0481","\u0483"-"\u0486",
|
|
|
|
"\u048c"-"\u04c4","\u04c7"-"\u04c8","\u04cb"-"\u04cc","\u04d0"-"\u04f5","\u04f8"-"\u04f9",
|
|
|
|
"\u0531"-"\u0556","\u0559","\u0561"-"\u0587","\u0591"-"\u05a1","\u05a3"-"\u05b9",
|
|
|
|
"\u05bb"-"\u05bd","\u05bf","\u05c1"-"\u05c2","\u05c4","\u05d0"-"\u05ea","\u05f0"-"\u05f2",
|
|
|
|
"\u0621"-"\u063a","\u0640"-"\u0655","\u0660"-"\u0669","\u0670"-"\u06d3","\u06d5"-"\u06dc",
|
|
|
|
"\u06df"-"\u06e8","\u06ea"-"\u06ed","\u06f0"-"\u06fc","\u070f"-"\u072c","\u0730"-"\u074a",
|
|
|
|
"\u0780"-"\u07b0","\u0901"-"\u0903","\u0905"-"\u0939","\u093c"-"\u094d","\u0950"-"\u0954",
|
|
|
|
"\u0958"-"\u0963","\u0966"-"\u096f","\u0981"-"\u0983","\u0985"-"\u098c","\u098f"-"\u0990",
|
|
|
|
"\u0993"-"\u09a8","\u09aa"-"\u09b0","\u09b2","\u09b6"-"\u09b9","\u09bc","\u09be"-"\u09c4",
|
|
|
|
"\u09c7"-"\u09c8","\u09cb"-"\u09cd","\u09d7","\u09dc"-"\u09dd","\u09df"-"\u09e3",
|
|
|
|
"\u09e6"-"\u09f3","\u0a02","\u0a05"-"\u0a0a","\u0a0f"-"\u0a10","\u0a13"-"\u0a28",
|
|
|
|
"\u0a2a"-"\u0a30","\u0a32"-"\u0a33","\u0a35"-"\u0a36","\u0a38"-"\u0a39","\u0a3c",
|
|
|
|
"\u0a3e"-"\u0a42","\u0a47"-"\u0a48","\u0a4b"-"\u0a4d","\u0a59"-"\u0a5c","\u0a5e",
|
|
|
|
"\u0a66"-"\u0a74","\u0a81"-"\u0a83","\u0a85"-"\u0a8b","\u0a8d","\u0a8f"-"\u0a91",
|
|
|
|
"\u0a93"-"\u0aa8","\u0aaa"-"\u0ab0","\u0ab2"-"\u0ab3","\u0ab5"-"\u0ab9","\u0abc"-"\u0ac5",
|
|
|
|
"\u0ac7"-"\u0ac9","\u0acb"-"\u0acd","\u0ad0","\u0ae0","\u0ae6"-"\u0aef","\u0b01"-"\u0b03",
|
|
|
|
"\u0b05"-"\u0b0c","\u0b0f"-"\u0b10","\u0b13"-"\u0b28","\u0b2a"-"\u0b30","\u0b32"-"\u0b33",
|
|
|
|
"\u0b36"-"\u0b39","\u0b3c"-"\u0b43","\u0b47"-"\u0b48","\u0b4b"-"\u0b4d","\u0b56"-"\u0b57",
|
|
|
|
"\u0b5c"-"\u0b5d","\u0b5f"-"\u0b61","\u0b66"-"\u0b6f","\u0b82"-"\u0b83","\u0b85"-"\u0b8a",
|
|
|
|
"\u0b8e"-"\u0b90","\u0b92"-"\u0b95","\u0b99"-"\u0b9a","\u0b9c","\u0b9e"-"\u0b9f",
|
|
|
|
"\u0ba3"-"\u0ba4","\u0ba8"-"\u0baa","\u0bae"-"\u0bb5","\u0bb7"-"\u0bb9","\u0bbe"-"\u0bc2",
|
|
|
|
"\u0bc6"-"\u0bc8","\u0bca"-"\u0bcd","\u0bd7","\u0be7"-"\u0bef","\u0c01"-"\u0c03",
|
|
|
|
"\u0c05"-"\u0c0c","\u0c0e"-"\u0c10","\u0c12"-"\u0c28","\u0c2a"-"\u0c33","\u0c35"-"\u0c39",
|
|
|
|
"\u0c3e"-"\u0c44","\u0c46"-"\u0c48","\u0c4a"-"\u0c4d","\u0c55"-"\u0c56","\u0c60"-"\u0c61",
|
|
|
|
"\u0c66"-"\u0c6f","\u0c82"-"\u0c83","\u0c85"-"\u0c8c","\u0c8e"-"\u0c90","\u0c92"-"\u0ca8",
|
|
|
|
"\u0caa"-"\u0cb3","\u0cb5"-"\u0cb9","\u0cbe"-"\u0cc4","\u0cc6"-"\u0cc8","\u0cca"-"\u0ccd",
|
|
|
|
"\u0cd5"-"\u0cd6","\u0cde","\u0ce0"-"\u0ce1","\u0ce6"-"\u0cef","\u0d02"-"\u0d03",
|
|
|
|
"\u0d05"-"\u0d0c","\u0d0e"-"\u0d10","\u0d12"-"\u0d28","\u0d2a"-"\u0d39","\u0d3e"-"\u0d43",
|
|
|
|
"\u0d46"-"\u0d48","\u0d4a"-"\u0d4d","\u0d57","\u0d60"-"\u0d61","\u0d66"-"\u0d6f",
|
|
|
|
"\u0d82"-"\u0d83","\u0d85"-"\u0d96","\u0d9a"-"\u0db1","\u0db3"-"\u0dbb","\u0dbd",
|
|
|
|
"\u0dc0"-"\u0dc6","\u0dca","\u0dcf"-"\u0dd4","\u0dd6","\u0dd8"-"\u0ddf","\u0df2"-"\u0df3",
|
|
|
|
"\u0e01"-"\u0e3a","\u0e3f"-"\u0e4e","\u0e50"-"\u0e59","\u0e81"-"\u0e82","\u0e84",
|
|
|
|
"\u0e87"-"\u0e88","\u0e8a","\u0e8d","\u0e94"-"\u0e97","\u0e99"-"\u0e9f","\u0ea1"-"\u0ea3",
|
|
|
|
"\u0ea5","\u0ea7","\u0eaa"-"\u0eab","\u0ead"-"\u0eb9","\u0ebb"-"\u0ebd","\u0ec0"-"\u0ec4",
|
|
|
|
"\u0ec6","\u0ec8"-"\u0ecd","\u0ed0"-"\u0ed9","\u0edc"-"\u0edd","\u0f00","\u0f18"-"\u0f19",
|
|
|
|
"\u0f20"-"\u0f29","\u0f35","\u0f37","\u0f39","\u0f3e"-"\u0f47","\u0f49"-"\u0f6a",
|
|
|
|
"\u0f71"-"\u0f84","\u0f86"-"\u0f8b","\u0f90"-"\u0f97","\u0f99"-"\u0fbc","\u0fc6",
|
|
|
|
"\u1000"-"\u1021","\u1023"-"\u1027","\u1029"-"\u102a","\u102c"-"\u1032","\u1036"-"\u1039",
|
|
|
|
"\u1040"-"\u1049","\u1050"-"\u1059","\u10a0"-"\u10c5","\u10d0"-"\u10f6","\u1100"-"\u1159",
|
|
|
|
"\u115f"-"\u11a2","\u11a8"-"\u11f9","\u1200"-"\u1206","\u1208"-"\u1246","\u1248",
|
|
|
|
"\u124a"-"\u124d","\u1250"-"\u1256","\u1258","\u125a"-"\u125d","\u1260"-"\u1286",
|
|
|
|
"\u1288","\u128a"-"\u128d","\u1290"-"\u12ae","\u12b0","\u12b2"-"\u12b5","\u12b8"-"\u12be",
|
|
|
|
"\u12c0","\u12c2"-"\u12c5","\u12c8"-"\u12ce","\u12d0"-"\u12d6","\u12d8"-"\u12ee",
|
|
|
|
"\u12f0"-"\u130e","\u1310","\u1312"-"\u1315","\u1318"-"\u131e","\u1320"-"\u1346",
|
|
|
|
"\u1348"-"\u135a","\u1369"-"\u1371","\u13a0"-"\u13f4","\u1401"-"\u166c","\u166f"-"\u1676",
|
|
|
|
"\u1681"-"\u169a","\u16a0"-"\u16ea","\u1780"-"\u17d3","\u17db","\u17e0"-"\u17e9",
|
2022-05-01 16:00:25 +02:00
|
|
|
"\u180b"-"\u180e","\u1810"-"\u1819","\u1820"-"\u1877","\u1880"-"\u18a9","\u1d00"-"\u1d7f","\u1e00"-"\u1e9b",
|
2020-01-25 09:52:36 +01:00
|
|
|
"\u1ea0"-"\u1ef9","\u1f00"-"\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","\u200c"-"\u200f",
|
|
|
|
"\u202a"-"\u202e","\u203f"-"\u2040","\u206a"-"\u206f","\u207f","\u20a0"-"\u20af",
|
|
|
|
"\u20d0"-"\u20dc","\u20e1","\u2102","\u2107","\u210a"-"\u2113","\u2115","\u2119"-"\u211d",
|
|
|
|
"\u2124","\u2126","\u2128","\u212a"-"\u212d","\u212f"-"\u2131","\u2133"-"\u2139",
|
|
|
|
"\u2160"-"\u2183","\u3005"-"\u3007","\u3021"-"\u302f","\u3031"-"\u3035","\u3038"-"\u303a",
|
|
|
|
"\u3041"-"\u3094","\u3099"-"\u309a","\u309d"-"\u309e","\u30a1"-"\u30fe","\u3105"-"\u312c",
|
|
|
|
"\u3131"-"\u318e","\u31a0"-"\u31b7","\u3400"-"\u4db5","\u4e00"-"\u9fa5","\ua000"-"\ua48c",
|
2022-05-01 17:47:06 +02:00
|
|
|
"\ua490"-"\uabff",
|
2020-01-25 09:52:36 +01:00
|
|
|
"\uac00"-"\ud7a3","\uf900"-"\ufa2d","\ufb00"-"\ufb06","\ufb13"-"\ufb17","\ufb1d"-"\ufb28",
|
|
|
|
"\ufb2a"-"\ufb36","\ufb38"-"\ufb3c","\ufb3e","\ufb40"-"\ufb41","\ufb43"-"\ufb44",
|
|
|
|
"\ufb46"-"\ufbb1","\ufbd3"-"\ufd3d","\ufd50"-"\ufd8f","\ufd92"-"\ufdc7","\ufdf0"-"\ufdfb",
|
|
|
|
"\ufe20"-"\ufe23","\ufe33"-"\ufe34","\ufe4d"-"\ufe4f","\ufe69","\ufe70"-"\ufe72","\ufe74",
|
|
|
|
"\ufe76"-"\ufefc","\ufeff","\uff04","\uff10"-"\uff19","\uff21"-"\uff3a","\uff3f",
|
|
|
|
"\uff41"-"\uff5a","\uff65"-"\uffbe","\uffc2"-"\uffc7","\uffca"-"\uffcf","\uffd2"-"\uffd7",
|
|
|
|
"\uffda"-"\uffdc","\uffe0"-"\uffe1","\uffe5"-"\uffe6","\ufff9"-"\ufffb"]>
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* SEPARATORS */
|
|
|
|
|
|
|
|
TOKEN :
|
|
|
|
{
|
|
|
|
< LPAREN: "(" >
|
|
|
|
| < RPAREN: ")" >
|
2024-04-12 17:59:10 +02:00
|
|
|
| < LBRACE: "{" > { pushBrace(); }
|
|
|
|
| < RBRACE: "}" > { popBrace(); }
|
2014-09-30 19:51:42 +02:00
|
|
|
| < LBRACKET: "[" >
|
|
|
|
| < RBRACKET: "]" >
|
|
|
|
| < SEMICOLON: ";" >
|
|
|
|
| < COMMA: "," >
|
|
|
|
| < DOT: "." >
|
|
|
|
| < AT: "@" >
|
|
|
|
}
|
|
|
|
|
|
|
|
/* OPERATORS */
|
|
|
|
|
|
|
|
TOKEN :
|
|
|
|
{
|
|
|
|
< ASSIGN: "=" >
|
|
|
|
| < LT: "<" >
|
|
|
|
| < BANG: "!" >
|
|
|
|
| < TILDE: "~" >
|
|
|
|
| < HOOK: "?" >
|
|
|
|
| < COLON: ":" >
|
|
|
|
| < EQ: "==" >
|
|
|
|
| < LE: "<=" >
|
|
|
|
| < GE: ">=" >
|
|
|
|
| < NE: "!=" >
|
|
|
|
| < SC_OR: "||" >
|
|
|
|
| < SC_AND: "&&" >
|
|
|
|
| < INCR: "++" >
|
|
|
|
| < DECR: "--" >
|
|
|
|
| < PLUS: "+" >
|
|
|
|
| < MINUS: "-" >
|
|
|
|
| < STAR: "*" >
|
|
|
|
| < SLASH: "/" >
|
|
|
|
| < BIT_AND: "&" >
|
|
|
|
| < BIT_OR: "|" >
|
|
|
|
| < XOR: "^" >
|
|
|
|
| < REM: "%" >
|
|
|
|
| < LSHIFT: "<<" >
|
2018-06-25 12:42:34 +02:00
|
|
|
// Notice the absence of >> or >>>, to not conflict with generics
|
2014-09-30 19:51:42 +02:00
|
|
|
| < PLUSASSIGN: "+=" >
|
|
|
|
| < MINUSASSIGN: "-=" >
|
|
|
|
| < STARASSIGN: "*=" >
|
|
|
|
| < SLASHASSIGN: "/=" >
|
|
|
|
| < ANDASSIGN: "&=" >
|
|
|
|
| < ORASSIGN: "|=" >
|
|
|
|
| < XORASSIGN: "^=" >
|
|
|
|
| < REMASSIGN: "%=" >
|
|
|
|
| < LSHIFTASSIGN: "<<=" >
|
|
|
|
| < RSIGNEDSHIFTASSIGN: ">>=" >
|
|
|
|
| < RUNSIGNEDSHIFTASSIGN: ">>>=" >
|
|
|
|
| < ELLIPSIS: "..." >
|
|
|
|
| < LAMBDA: "->" >
|
|
|
|
| < METHOD_REF: "::" >
|
|
|
|
}
|
|
|
|
|
|
|
|
/* >'s need special attention due to generics syntax. */
|
|
|
|
TOKEN :
|
|
|
|
{
|
2019-06-08 22:05:10 +02:00
|
|
|
< RUNSIGNEDSHIFT: ">>>" > { input_stream.backup(2); }
|
|
|
|
| < RSIGNEDSHIFT: ">>" > { input_stream.backup(1); }
|
2014-09-30 19:51:42 +02:00
|
|
|
| < GT: ">" >
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************
|
|
|
|
* THE JAVA LANGUAGE GRAMMAR STARTS HERE *
|
|
|
|
*****************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Program structuring syntax follows.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ASTCompilationUnit CompilationUnit() :
|
|
|
|
{}
|
|
|
|
{
|
2019-12-14 03:32:17 +01:00
|
|
|
[ LOOKAHEAD( ( Annotation() )* "package" ) PackageDeclaration() ( EmptyDeclaration() )* ]
|
|
|
|
( ImportDeclaration() ( EmptyDeclaration() )* )*
|
2023-08-05 17:10:21 +02:00
|
|
|
|
|
|
|
// ModularCompilationUnit:
|
2019-05-25 07:24:55 +02:00
|
|
|
// the module decl lookahead needs to be before the type declaration branch,
|
|
|
|
// looking for annotations + "open" | "module" will fail faster if it's *not*
|
|
|
|
// a module (most common case)
|
2019-12-14 03:32:17 +01:00
|
|
|
[ LOOKAHEAD(ModuleDeclLahead()) ModuleDeclaration() ( EmptyDeclaration() )* ]
|
2023-08-05 17:10:21 +02:00
|
|
|
|
|
|
|
// OrdinaryCompilationUnit: -> TopLevelClassOrInterfaceDeclaration
|
2019-12-14 03:32:17 +01:00
|
|
|
( TypeDeclaration() ( EmptyDeclaration() )* )*
|
2023-08-05 17:10:21 +02:00
|
|
|
|
2024-02-15 11:26:12 +01:00
|
|
|
// SimpleCompilationUnit:
|
2023-08-05 17:10:21 +02:00
|
|
|
[
|
2024-07-29 20:21:13 +02:00
|
|
|
(
|
|
|
|
{ pushEmptyModifierList(); }
|
|
|
|
(
|
|
|
|
( LOOKAHEAD(3) ClassMemberDeclarationNoMethod() )*
|
|
|
|
ModifierList() MethodDeclaration()
|
|
|
|
( ClassOrInterfaceBodyDeclaration() )*
|
|
|
|
) #ClassBody
|
|
|
|
) #ImplicitClassDeclaration
|
2023-08-05 17:10:21 +02:00
|
|
|
]
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
<EOF>
|
2019-05-25 07:24:55 +02:00
|
|
|
{
|
|
|
|
jjtThis.setComments(token_source.comments);
|
|
|
|
return jjtThis;
|
|
|
|
}
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
2019-05-25 07:24:55 +02:00
|
|
|
|
2023-08-05 17:10:21 +02:00
|
|
|
// see ClassOrInterfaceBodyDeclaration()
|
|
|
|
void ClassMemberDeclarationNoMethod() #void:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
ModifierList()
|
|
|
|
( LOOKAHEAD(3) ClassOrInterfaceDeclaration()
|
|
|
|
| LOOKAHEAD({isKeyword("enum")}) EnumDeclaration()
|
|
|
|
| LOOKAHEAD({isKeyword("record")}) RecordDeclaration()
|
|
|
|
| LOOKAHEAD( [ TypeParameters() ] <IDENTIFIER> "(" ) ConstructorDeclaration()
|
|
|
|
| LOOKAHEAD( Type() <IDENTIFIER> (AnnotationList() "[" "]")* ( "," | "=" | ";" ) ) FieldDeclaration()
|
|
|
|
| LOOKAHEAD(2) AnnotationTypeDeclaration()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-05-25 07:24:55 +02:00
|
|
|
private void ModuleDeclLahead() #void:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
(Annotation())* LOOKAHEAD({isKeyword("open") || isKeyword("module")}) <IDENTIFIER>
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-05-25 07:24:55 +02:00
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
void PackageDeclaration() :
|
2019-06-26 18:14:30 +02:00
|
|
|
{String image;}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
ModAnnotationList() "package" image=VoidName() { jjtThis.setImage(image); } ";"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ImportDeclaration() :
|
2019-06-26 18:14:30 +02:00
|
|
|
{String image;}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2024-07-20 17:51:31 +02:00
|
|
|
"import"
|
|
|
|
(
|
|
|
|
"static" {jjtThis.setStatic();}
|
|
|
|
| LOOKAHEAD({isKeyword("module")}) <IDENTIFIER> {jjtThis.setModuleImport();}
|
|
|
|
)?
|
|
|
|
image=VoidName() { jjtThis.setImage(image); }
|
|
|
|
[ "." "*" {jjtThis.setImportOnDemand();} ] ";"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2019-01-08 23:30:51 +01:00
|
|
|
* Modifiers. We match all modifiers in a single rule to reduce the chances of
|
2014-09-30 19:51:42 +02:00
|
|
|
* syntax errors for simple modifier mistakes. It will also enable us to give
|
|
|
|
* better error messages.
|
|
|
|
*/
|
2019-07-01 15:55:14 +02:00
|
|
|
void ModifierList():
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
EnumSet<JModifier> modifiers = EnumSet.noneOf(JModifier.class);
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
{
|
|
|
|
(
|
2019-05-24 19:08:06 +02:00
|
|
|
LOOKAHEAD(2)
|
2014-09-30 19:51:42 +02:00
|
|
|
(
|
2019-07-01 15:55:14 +02:00
|
|
|
"public" { modifiers.add(JModifier.PUBLIC); }
|
|
|
|
| "static" { modifiers.add(JModifier.STATIC); }
|
|
|
|
| "protected" { modifiers.add(JModifier.PROTECTED); }
|
|
|
|
| "private" { modifiers.add(JModifier.PRIVATE); }
|
|
|
|
| "final" { modifiers.add(JModifier.FINAL); }
|
|
|
|
| "abstract" { modifiers.add(JModifier.ABSTRACT); }
|
|
|
|
| "synchronized" { modifiers.add(JModifier.SYNCHRONIZED); }
|
|
|
|
| "native" { modifiers.add(JModifier.NATIVE); }
|
|
|
|
| "transient" { modifiers.add(JModifier.TRANSIENT); }
|
|
|
|
| "volatile" { modifiers.add(JModifier.VOLATILE); }
|
|
|
|
| "strictfp" { modifiers.add(JModifier.STRICTFP); }
|
|
|
|
| "default" { modifiers.add(JModifier.DEFAULT); }
|
2020-08-22 21:39:14 +02:00
|
|
|
| LOOKAHEAD({isKeyword("sealed")}) <IDENTIFIER> { modifiers.add(JModifier.SEALED); }
|
|
|
|
| LOOKAHEAD({isNonSealedModifier()}) <IDENTIFIER> <MINUS> <IDENTIFIER> { modifiers.add(JModifier.NON_SEALED); }
|
2019-07-01 15:55:14 +02:00
|
|
|
| Annotation()
|
2014-09-30 19:51:42 +02:00
|
|
|
)
|
|
|
|
)*
|
2019-07-01 15:55:14 +02:00
|
|
|
{ jjtThis.setDeclaredModifiers(modifiers); }
|
|
|
|
{ jjtree.injectRight(1); } // inject the modifier node in the follower
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Declaration syntax follows.
|
|
|
|
*/
|
2020-02-14 04:14:15 +01:00
|
|
|
void TypeDeclaration() #void:
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
ModifierList()
|
2014-09-30 19:51:42 +02:00
|
|
|
(
|
2019-07-01 15:55:14 +02:00
|
|
|
ClassOrInterfaceDeclaration()
|
2020-03-02 21:05:21 +01:00
|
|
|
| AnnotationTypeDeclaration()
|
|
|
|
| LOOKAHEAD({isKeyword("enum")}) EnumDeclaration()
|
|
|
|
| LOOKAHEAD({isKeyword("record")}) RecordDeclaration()
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-12-12 19:57:57 +01:00
|
|
|
void ClassOrInterfaceDeclaration() #ClassDeclaration:
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-09-25 06:30:17 +02:00
|
|
|
( "class" | "interface" { jjtThis.setInterface(); } )
|
2024-02-08 17:50:37 +01:00
|
|
|
<IDENTIFIER> { jjtThis.setSimpleName(getToken(0).getImage()); }
|
2014-09-30 19:51:42 +02:00
|
|
|
[ TypeParameters() ]
|
|
|
|
[ ExtendsList() ]
|
|
|
|
[ ImplementsList() ]
|
2020-08-14 22:16:41 +02:00
|
|
|
[ LOOKAHEAD({isKeyword("permits")}) PermittedSubclasses() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
ClassOrInterfaceBody()
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExtendsList():
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-03-21 13:58:03 +01:00
|
|
|
"extends" AnnotatedClassOrInterfaceType()
|
2019-07-01 15:55:14 +02:00
|
|
|
( "," AnnotatedClassOrInterfaceType() )*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ImplementsList():
|
|
|
|
{}
|
|
|
|
{
|
2019-03-21 13:58:03 +01:00
|
|
|
"implements" AnnotatedClassOrInterfaceType()
|
|
|
|
( "," AnnotatedClassOrInterfaceType() )*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-08-22 19:30:38 +02:00
|
|
|
void PermittedSubclasses() #PermitsList:
|
2023-03-19 22:49:45 +01:00
|
|
|
{}
|
2020-08-14 22:16:41 +02:00
|
|
|
{
|
2023-03-19 22:49:45 +01:00
|
|
|
softKeyword("permits")
|
2021-11-26 10:13:05 +01:00
|
|
|
ClassOrInterfaceType()
|
|
|
|
( "," ClassOrInterfaceType() )*
|
2020-08-14 22:16:41 +02:00
|
|
|
}
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void EnumDeclaration():
|
2023-03-19 22:49:45 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2023-03-19 22:49:45 +01:00
|
|
|
softKeyword("enum")
|
2024-02-08 17:50:37 +01:00
|
|
|
<IDENTIFIER> { jjtThis.setSimpleName(getToken(0).getImage()); }
|
2014-09-30 19:51:42 +02:00
|
|
|
[ ImplementsList() ]
|
|
|
|
EnumBody()
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnumBody():
|
2019-09-25 06:30:17 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2020-02-07 18:23:42 +01:00
|
|
|
[ EnumConstant() ( LOOKAHEAD(2) "," EnumConstant() )* ]
|
|
|
|
[ "," { jjtThis.setTrailingComma(); } ]
|
|
|
|
[ ";" { jjtThis.setSeparatorSemi(); } ( ClassOrInterfaceBodyDeclaration() )* ]
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void EnumConstant():
|
2019-04-25 18:17:01 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
ModAnnotationList() VariableDeclaratorId() [ ArgumentList() ] [ AnonymousClassDeclaration() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-03-02 21:05:21 +01:00
|
|
|
void RecordDeclaration():
|
2023-03-19 22:49:45 +01:00
|
|
|
{}
|
2020-02-28 14:58:52 +01:00
|
|
|
{
|
2023-03-19 22:49:45 +01:00
|
|
|
softKeyword("record")
|
2024-02-08 17:50:37 +01:00
|
|
|
<IDENTIFIER> { jjtThis.setSimpleName(getToken(0).getImage()); }
|
2020-02-28 14:58:52 +01:00
|
|
|
[ TypeParameters() ]
|
2021-02-14 19:42:59 +01:00
|
|
|
RecordHeader()
|
2020-02-28 14:58:52 +01:00
|
|
|
[ ImplementsList() ]
|
|
|
|
RecordBody()
|
|
|
|
}
|
|
|
|
|
2021-02-14 19:42:59 +01:00
|
|
|
void RecordHeader() #void:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
"(" RecordComponentList() ")"
|
|
|
|
}
|
|
|
|
|
2020-02-28 16:56:43 +01:00
|
|
|
void RecordComponentList() :
|
2020-02-28 14:58:52 +01:00
|
|
|
{}
|
|
|
|
{
|
2021-02-14 19:42:59 +01:00
|
|
|
[ RecordComponent() ("," RecordComponent())* ]
|
2020-02-28 14:58:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void RecordComponent():
|
|
|
|
{}
|
|
|
|
{
|
2020-03-02 21:05:21 +01:00
|
|
|
ModAnnotationList()
|
|
|
|
FormalParamType()
|
2020-02-28 17:35:44 +01:00
|
|
|
VariableDeclaratorId()
|
2020-02-28 14:58:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void RecordBody():
|
|
|
|
{}
|
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2020-02-28 14:58:52 +01:00
|
|
|
( RecordBodyDeclaration() )*
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2020-02-28 14:58:52 +01:00
|
|
|
}
|
|
|
|
|
2020-02-28 18:16:19 +01:00
|
|
|
void RecordBodyDeclaration() #void :
|
2020-02-28 14:58:52 +01:00
|
|
|
{}
|
|
|
|
{
|
2021-02-18 10:44:23 +01:00
|
|
|
LOOKAHEAD(CompactConstructorDeclarationLookahead()) ModifierList() CompactConstructorDeclaration()
|
2020-02-28 14:58:52 +01:00
|
|
|
|
|
2020-03-02 19:00:59 +01:00
|
|
|
ClassOrInterfaceBodyDeclaration()
|
|
|
|
}
|
|
|
|
|
2021-02-14 19:42:59 +01:00
|
|
|
private void CompactConstructorDeclarationLookahead() #void:
|
2020-03-02 19:00:59 +01:00
|
|
|
{}
|
|
|
|
{
|
2020-03-28 15:28:34 +01:00
|
|
|
ModifierList() <IDENTIFIER> "{"
|
2020-02-28 14:58:52 +01:00
|
|
|
}
|
|
|
|
|
2021-02-14 19:42:59 +01:00
|
|
|
void CompactConstructorDeclaration():
|
2020-03-02 21:05:21 +01:00
|
|
|
{}
|
2020-02-28 14:58:52 +01:00
|
|
|
{
|
2020-02-28 17:01:57 +01:00
|
|
|
<IDENTIFIER> { jjtThis.setImage(token.image); }
|
2020-03-02 21:05:21 +01:00
|
|
|
Block()
|
2020-02-28 14:58:52 +01:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
void TypeParameters():
|
|
|
|
{}
|
|
|
|
{
|
2019-09-25 06:30:17 +02:00
|
|
|
"<" TypeParameter() ( "," TypeParameter() )* ">"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void TypeParameter():
|
2020-02-07 23:43:26 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-03-26 17:17:22 +01:00
|
|
|
AnnotationList()
|
2020-02-07 23:43:26 +01:00
|
|
|
<IDENTIFIER> {setLastTokenImage(jjtThis);} [ "extends" IntersectionType() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2023-12-13 10:49:13 +01:00
|
|
|
void ClassOrInterfaceBody() #ClassBody:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2023-08-10 11:27:53 +02:00
|
|
|
( ClassOrInterfaceBodyDeclaration() )*
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-02-14 04:02:12 +01:00
|
|
|
void ClassOrInterfaceBodyDeclaration() #void:
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{ LOOKAHEAD(["static"] "{" ) Initializer()
|
2019-07-01 15:55:14 +02:00
|
|
|
| ModifierList()
|
|
|
|
( LOOKAHEAD(3) ClassOrInterfaceDeclaration()
|
|
|
|
| LOOKAHEAD({isKeyword("enum")}) EnumDeclaration()
|
2020-03-02 21:05:21 +01:00
|
|
|
| LOOKAHEAD({isKeyword("record")}) RecordDeclaration()
|
2019-07-01 15:55:14 +02:00
|
|
|
| LOOKAHEAD( [ TypeParameters() ] <IDENTIFIER> "(" ) ConstructorDeclaration()
|
|
|
|
| LOOKAHEAD( Type() <IDENTIFIER> (AnnotationList() "[" "]")* ( "," | "=" | ";" ) ) FieldDeclaration()
|
|
|
|
| LOOKAHEAD(2) MethodDeclaration()
|
|
|
|
| LOOKAHEAD(2) AnnotationTypeDeclaration()
|
2014-09-30 19:51:42 +02:00
|
|
|
)
|
|
|
|
|
|
2019-05-28 19:16:04 +02:00
|
|
|
";" #EmptyDeclaration
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2017-09-22 12:16:51 +02:00
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void FieldDeclaration() :
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
|
|
|
Type() VariableDeclarator() ( "," VariableDeclarator() )* ";"
|
|
|
|
}
|
|
|
|
|
|
|
|
void VariableDeclarator() :
|
|
|
|
{}
|
|
|
|
{
|
2019-12-15 03:53:10 +01:00
|
|
|
VariableIdWithDims() [ "=" VariableInitializer() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2023-12-13 10:30:39 +01:00
|
|
|
void VariableDeclaratorId() #VariableId:
|
2019-10-07 19:35:20 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2024-02-08 17:50:37 +01:00
|
|
|
<IDENTIFIER> { jjtThis.setName(getToken(0).getImage()); }
|
2019-12-15 03:53:10 +01:00
|
|
|
}
|
|
|
|
|
2023-12-13 10:30:39 +01:00
|
|
|
void VariableIdWithDims() #VariableId :
|
2019-12-15 03:53:10 +01:00
|
|
|
{}
|
|
|
|
{
|
2024-02-08 17:50:37 +01:00
|
|
|
<IDENTIFIER> { jjtThis.setName(getToken(0).getImage()); }
|
2019-12-15 03:53:10 +01:00
|
|
|
[ Dims() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-07-22 06:03:04 +02:00
|
|
|
void ReceiverParameter():
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
AnnotatedClassOrInterfaceType() [ <IDENTIFIER> "." ] "this"
|
|
|
|
}
|
|
|
|
|
2019-02-18 23:39:10 +01:00
|
|
|
void VariableInitializer() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
|
|
|
ArrayInitializer()
|
|
|
|
| Expression()
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArrayInitializer() :
|
|
|
|
{}
|
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2023-08-10 11:27:53 +02:00
|
|
|
[ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ]
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void MethodDeclaration() :
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
|
|
|
[ TypeParameters() ]
|
2019-07-22 09:43:52 +02:00
|
|
|
ResultType()
|
2024-02-08 17:50:37 +01:00
|
|
|
<IDENTIFIER> { jjtThis.setName(getToken(0).getImage()); }
|
2019-07-22 09:43:52 +02:00
|
|
|
FormalParameters()
|
2019-12-15 03:53:10 +01:00
|
|
|
[ Dims() ]
|
2019-09-27 06:21:08 +02:00
|
|
|
[ ThrowsList() ]
|
2019-07-22 09:43:52 +02:00
|
|
|
( Block() | ";" )
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FormalParameters() :
|
|
|
|
{}
|
|
|
|
{
|
2019-07-22 06:03:04 +02:00
|
|
|
"(" [ ( LOOKAHEAD(ReceiverParameter()) ReceiverParameter() | FormalParameter() ) ( "," FormalParameter() )* ] ")"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FormalParameter() :
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
LocalVarModifierList()
|
2020-01-07 22:05:28 +01:00
|
|
|
FormalParamType() ("|" FormalParamType())* // remove this stuff when #2202 is merged
|
2019-12-15 03:53:10 +01:00
|
|
|
VariableIdWithDims()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
2019-12-15 03:53:10 +01:00
|
|
|
|
|
|
|
void FormalParamType() #void:
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-12-15 03:53:10 +01:00
|
|
|
PrimitiveType() [ LOOKAHEAD(2) VarargsDimensions() #ArrayType(2) ]
|
|
|
|
| ClassOrInterfaceType() [ LOOKAHEAD(2) VarargsDimensions() #ArrayType(2) ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-12-15 03:53:10 +01:00
|
|
|
void VarargsDimensions() #ArrayDimensions:
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-12-15 03:53:10 +01:00
|
|
|
// like ArrayDimensions but allows for a varargs ellipsis at the end ("...")
|
|
|
|
LOOKAHEAD(AnnotationList() "[") (LOOKAHEAD(AnnotationList() "[") ArrayTypeDim())+ [ VarargsDim() ]
|
|
|
|
| VarargsDim()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-12-15 03:53:10 +01:00
|
|
|
void VarargsDim() #ArrayTypeDim:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
TypeAnnotListNoInject() "..." {jjtThis.setVarargs();}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void ConstructorDeclaration() :
|
2020-02-07 23:23:54 +01:00
|
|
|
{}
|
|
|
|
{
|
|
|
|
[ TypeParameters() ]
|
|
|
|
<IDENTIFIER> {setLastTokenImage(jjtThis);}
|
|
|
|
FormalParameters()
|
|
|
|
[ ThrowsList() ]
|
|
|
|
ConstructorBlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ConstructorBlock() #Block:
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2024-02-15 15:07:50 +01:00
|
|
|
(
|
|
|
|
LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation()
|
|
|
|
|
|
|
|
|
( LOOKAHEAD(2) BlockStatement() )*
|
|
|
|
[ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ]
|
|
|
|
)
|
2020-02-07 23:23:54 +01:00
|
|
|
( BlockStatement() )*
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ExplicitConstructorInvocation() :
|
2022-11-16 13:56:01 +01:00
|
|
|
{boolean prev = inExplicitConstructorInvoc; inExplicitConstructorInvoc = true;}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-05-22 23:51:03 +02:00
|
|
|
// We may only lookahead one token here, because:
|
|
|
|
// * "this" or "super" can't appear in the primary expression in case of
|
|
|
|
// qualified super call (last branch), or else compile error, so if we
|
|
|
|
// see one of them, then the rest is necessarily the arguments
|
2019-05-25 03:21:42 +02:00
|
|
|
// But: "this" may appear if it's qualified!
|
2019-05-22 23:51:03 +02:00
|
|
|
// * No primary expression may start with "<", meaning we can use it to
|
|
|
|
// know we're looking forward to type arguments
|
|
|
|
( LOOKAHEAD("<") TypeArguments() ( "this" | "super" {jjtThis.setIsSuper();} )
|
|
|
|
| LOOKAHEAD("this") "this"
|
|
|
|
| LOOKAHEAD("super") "super" {jjtThis.setIsSuper();}
|
|
|
|
| PrimaryExpression() "." [ TypeArguments() ] "super" {jjtThis.setIsSuper();}
|
|
|
|
)
|
2019-05-24 19:47:29 +02:00
|
|
|
// reset this before parsing the arguments list
|
2022-11-16 13:56:01 +01:00
|
|
|
{inExplicitConstructorInvoc = prev;}
|
2019-05-24 19:47:29 +02:00
|
|
|
ArgumentList() ";"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Initializer() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
[ "static" {jjtThis.setStatic();} ] Block()
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:20:43 +01:00
|
|
|
/* JLS: https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.3
|
|
|
|
|
|
|
|
ReferenceType:
|
|
|
|
ClassOrInterfaceType
|
|
|
|
TypeVariable
|
|
|
|
ArrayType
|
|
|
|
ClassOrInterfaceType:
|
|
|
|
ClassType
|
|
|
|
InterfaceType
|
|
|
|
ClassType:
|
|
|
|
{Annotation} Identifier [TypeArguments]
|
|
|
|
ClassOrInterfaceType . {Annotation} Identifier [TypeArguments]
|
|
|
|
InterfaceType:
|
|
|
|
ClassType
|
|
|
|
TypeVariable:
|
|
|
|
{Annotation} Identifier
|
|
|
|
ArrayType:
|
|
|
|
PrimitiveType Dims
|
|
|
|
ClassOrInterfaceType Dims
|
|
|
|
TypeVariable Dims
|
|
|
|
Dims:
|
|
|
|
{Annotation} [ ] {{Annotation} [ ]}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2019-09-25 06:30:17 +02:00
|
|
|
void IntersectionType() #IntersectionType(isIntersection):
|
2019-03-26 17:17:22 +01:00
|
|
|
{boolean isIntersection=false;}
|
2019-03-21 13:58:03 +01:00
|
|
|
{
|
2019-09-25 06:30:17 +02:00
|
|
|
AnnotatedType() ( "&" {isIntersection=true;} AnnotatedClassOrInterfaceType() )*
|
2019-03-21 13:58:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnnotationList() #void:
|
2019-03-22 22:09:06 +01:00
|
|
|
{}
|
2019-03-21 13:58:03 +01:00
|
|
|
{
|
2019-03-22 22:09:06 +01:00
|
|
|
(Annotation())*
|
2019-03-21 13:58:03 +01:00
|
|
|
}
|
2019-05-29 12:56:34 +02:00
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void ModAnnotationList() #ModifierList:
|
|
|
|
{jjtThis.setDeclaredModifiers(Collections.emptySet());}
|
|
|
|
{
|
|
|
|
(Annotation())*
|
|
|
|
}
|
|
|
|
|
2019-05-29 13:39:52 +02:00
|
|
|
int TypeAnnotListNoInject() #void:
|
|
|
|
{int num = 0;}
|
2019-05-29 12:56:34 +02:00
|
|
|
{
|
2019-05-29 13:39:52 +02:00
|
|
|
( TypeAnnotation() {num++;} )*
|
|
|
|
{
|
|
|
|
return num;
|
|
|
|
}
|
2019-05-29 12:56:34 +02:00
|
|
|
}
|
2019-05-29 13:39:52 +02:00
|
|
|
|
|
|
|
// Type annotation lists are by default injected in the
|
|
|
|
// next node to be opened (most likely a type).
|
|
|
|
// Sometimes (array dims), this need not be and TypeAnnotListNoInject
|
|
|
|
// should be used.
|
2019-03-22 22:09:06 +01:00
|
|
|
void TypeAnnotationList() #void:
|
2019-05-29 13:39:52 +02:00
|
|
|
{int size=0;}
|
2019-03-21 13:58:03 +01:00
|
|
|
{
|
2019-05-29 13:39:52 +02:00
|
|
|
size=TypeAnnotListNoInject() { jjtree.injectRight(size); }
|
2019-03-21 13:58:03 +01:00
|
|
|
}
|
|
|
|
|
2019-03-26 17:17:22 +01:00
|
|
|
void AnnotatedType() #void:
|
2019-03-22 22:09:06 +01:00
|
|
|
{}
|
2019-03-21 13:58:03 +01:00
|
|
|
{
|
2019-03-22 22:09:06 +01:00
|
|
|
TypeAnnotationList() Type()
|
2019-03-21 13:58:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-26 17:17:22 +01:00
|
|
|
void AnnotatedRefType() #void:
|
2019-03-22 22:09:06 +01:00
|
|
|
{}
|
2019-03-21 13:58:03 +01:00
|
|
|
{
|
2019-03-22 22:09:06 +01:00
|
|
|
TypeAnnotationList() ReferenceType()
|
2019-03-21 13:58:03 +01:00
|
|
|
}
|
|
|
|
|
2019-03-26 17:17:22 +01:00
|
|
|
void AnnotatedClassOrInterfaceType() #void:
|
2019-03-22 22:09:06 +01:00
|
|
|
{}
|
2019-03-21 13:58:03 +01:00
|
|
|
{
|
2019-03-22 22:09:06 +01:00
|
|
|
TypeAnnotationList() ClassOrInterfaceType()
|
2019-03-21 13:58:03 +01:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
/*
|
|
|
|
* Type, name and expression syntax follows.
|
2018-05-28 21:13:11 +02:00
|
|
|
* Type is the same as "UnannType" in JLS
|
|
|
|
*
|
|
|
|
* See https://docs.oracle.com/javase/specs/jls/se10/html/jls-8.html#jls-UnannType
|
2014-09-30 19:51:42 +02:00
|
|
|
*/
|
2018-11-05 21:20:43 +01:00
|
|
|
void Type() #void:
|
2020-01-07 22:24:32 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-01-07 22:24:32 +01:00
|
|
|
PrimitiveType() [ LOOKAHEAD(2) Dims() #ArrayType(2) ]
|
|
|
|
| ClassOrInterfaceType() [ LOOKAHEAD(2) Dims() #ArrayType(2) ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-08-15 17:39:44 +02:00
|
|
|
void Dims() #ArrayDimensions:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-02-16 16:47:42 +01:00
|
|
|
// the list of dimensions is flat, but annotations are
|
|
|
|
// preserved within each specific dim.
|
2019-02-16 11:44:34 +01:00
|
|
|
(ArrayTypeDim())+
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-02-16 11:44:34 +01:00
|
|
|
void ArrayTypeDim():
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-05-29 12:56:34 +02:00
|
|
|
TypeAnnotListNoInject() "[" "]"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
2018-11-05 21:20:43 +01:00
|
|
|
|
2018-11-05 21:20:43 +01:00
|
|
|
void ReferenceType() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-05-28 19:16:04 +02:00
|
|
|
// We parse it that way because the right injection considers node openings,
|
|
|
|
// which means if we want the annotations to belong to the element type, then
|
|
|
|
// the ArrayType node needs to be opened after eg the PrimitiveType
|
|
|
|
PrimitiveType() Dims() #ArrayType(2)
|
|
|
|
| ClassOrInterfaceType() [ LOOKAHEAD(2) Dims() #ArrayType(2) ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2018-11-07 08:52:19 +01:00
|
|
|
|
|
|
|
/**
|
2019-02-16 11:15:52 +01:00
|
|
|
* Parses a ClassOrInterfaceType. The production itself is #void,
|
2019-02-16 11:44:34 +01:00
|
|
|
* but the node exists (declared inline within the production).
|
2018-11-07 08:52:19 +01:00
|
|
|
*/
|
2018-11-06 04:22:31 +01:00
|
|
|
void ClassOrInterfaceType() #void:
|
2019-02-18 17:55:41 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-02-18 17:55:41 +01:00
|
|
|
|
2019-05-28 19:16:04 +02:00
|
|
|
(LOOKAHEAD({jjtree.isInjectionPending()})
|
2019-05-29 13:39:52 +02:00
|
|
|
// Perhaps surprisingly a type annotation binds to the closest segment
|
|
|
|
// So in "@B Map.Entry", "@B" binds to "Map", and Map is required to be a type name.
|
|
|
|
// If the annotation is not applicable to TYPE_USE then it doesn't compile
|
|
|
|
|
|
|
|
// So if there are annotations pending injection here, then they're necessarily
|
|
|
|
// type annotations, since otherwise they would have been consumed in the
|
|
|
|
// annotation list of a declaration.
|
|
|
|
|
|
|
|
// Eg in "public abstract @F int foo();", "@F" is part of the modifier list of the method.
|
|
|
|
// but in "public abstract <T> @F T foo();", "@F" is necessarily a type annotation, and indeed
|
|
|
|
// is in a separate AnnotationList (it follows the type parameters so is not a modifier).
|
|
|
|
|
|
|
|
// To sum it up, if we have annotations pending, then the first segment is necessarily
|
|
|
|
// a type name, otherwise it wouldn't have compiled. So it's not ambiguous and we can
|
|
|
|
// start fresh: "@B Map.Entry" will be unambiguously [[@B Map].Entry]
|
2019-05-28 19:16:04 +02:00
|
|
|
|
2024-02-08 17:50:37 +01:00
|
|
|
(<IDENTIFIER> { jjtThis.setSimpleName(getToken(0).getImage()); } [ TypeArguments() ]) #ClassType
|
2019-05-28 19:16:04 +02:00
|
|
|
|
|
2018-11-06 04:22:31 +01:00
|
|
|
|
2019-05-29 13:39:52 +02:00
|
|
|
|
|
|
|
// Otherwise, for now we have no clue until the first type arguments
|
|
|
|
// or annotation is found. The name is ambiguous between package or
|
|
|
|
// type name unless type arguments are present, in which case we can
|
|
|
|
// be sure that the last segment is a type name.
|
2019-05-28 19:16:04 +02:00
|
|
|
|
|
|
|
AmbiguousName()
|
2023-12-12 15:55:04 +01:00
|
|
|
[ TypeArguments() #ClassType(2) ]
|
2019-05-28 19:16:04 +02:00
|
|
|
{
|
2024-02-08 17:50:37 +01:00
|
|
|
// At this point the first ClassType may be on top of the stack,
|
2019-05-28 19:16:04 +02:00
|
|
|
// but its image is not set. If it is on the stack we need to shrink the bounds
|
|
|
|
// of the ambiguous name, or delete it.
|
|
|
|
Node first = jjtree.peekNode();
|
2023-12-12 15:55:04 +01:00
|
|
|
if (first instanceof ASTClassType) {
|
2019-05-28 19:16:04 +02:00
|
|
|
// then we saw type arguments, so the last segment is definitely a type name
|
2023-12-14 09:40:26 +01:00
|
|
|
ASTAmbiguousName name = first.firstChild(ASTAmbiguousName.class);
|
2019-05-28 19:16:04 +02:00
|
|
|
name.shrinkOrDeleteInParentSetImage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
2018-11-06 04:22:31 +01:00
|
|
|
|
2019-02-16 11:44:34 +01:00
|
|
|
/*
|
2019-03-24 19:27:59 +01:00
|
|
|
Now if there are other segments, either the previous segment specified type
|
2019-04-03 14:48:48 +02:00
|
|
|
arguments, or the next has an annotation. Either way we know that all the
|
|
|
|
following segments is a type name. Each segment is parsed as its own ClassOrInterfaceType
|
|
|
|
which encloses the previous one. The resulting structure appears left-recursive, but the parser just
|
2019-02-16 12:02:21 +01:00
|
|
|
executes a loop. That scheme preserves the position of type arguments and annotations.
|
2019-02-16 11:44:34 +01:00
|
|
|
See #1150.
|
|
|
|
*/
|
2019-05-29 13:39:52 +02:00
|
|
|
( LOOKAHEAD(2) "." ClassTypeSegment() )*
|
2019-04-03 14:48:48 +02:00
|
|
|
{ forceTypeContext(); }
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2023-12-12 15:55:04 +01:00
|
|
|
private void ClassTypeSegment() #ClassType(jjtree.nodeArity() + 1):
|
2019-05-24 16:33:48 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-05-29 12:56:34 +02:00
|
|
|
TypeAnnotListNoInject()
|
2019-05-24 16:33:48 +02:00
|
|
|
<IDENTIFIER>
|
|
|
|
// We'll enclose the previous segment
|
2024-02-08 17:50:37 +01:00
|
|
|
{ jjtThis.setSimpleName(getToken(0).getImage()); }
|
2019-05-24 16:33:48 +02:00
|
|
|
[ TypeArguments() ]
|
|
|
|
}
|
2018-11-06 04:22:31 +01:00
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
void TypeArguments():
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
LOOKAHEAD(2)
|
2019-09-25 06:30:17 +02:00
|
|
|
"<" TypeArgument() ( "," TypeArgument() )* ">"
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
2019-09-25 06:30:17 +02:00
|
|
|
"<" ">"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-31 06:59:49 +02:00
|
|
|
void TypeArgument() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-03-22 22:09:06 +01:00
|
|
|
TypeAnnotationList() (ReferenceType() | WildcardType())
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-21 13:58:03 +01:00
|
|
|
void WildcardType():
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2022-12-07 22:51:02 +01:00
|
|
|
"?" [ ("extends" | "super" {jjtThis.setLowerBound(true);}) AnnotatedRefType() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-05 21:20:43 +01:00
|
|
|
/* JLS https://docs.oracle.com/javase/specs/jls/se10/html/jls-4.html#jls-PrimitiveType
|
|
|
|
|
|
|
|
PrimitiveType:
|
|
|
|
{Annotation} NumericType
|
|
|
|
{Annotation} boolean
|
|
|
|
NumericType:
|
|
|
|
IntegralType
|
|
|
|
FloatingPointType
|
|
|
|
IntegralType:
|
|
|
|
(one of)
|
|
|
|
byte short int long char
|
|
|
|
FloatingPointType:
|
|
|
|
(one of)
|
|
|
|
float double
|
|
|
|
*/
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
void PrimitiveType() :
|
|
|
|
{}
|
|
|
|
{
|
2020-07-26 17:48:42 +02:00
|
|
|
"boolean" {jjtThis.setKind(PrimitiveTypeKind.BOOLEAN);}
|
New typeres framework
Ceci est la combinaison de 338+ commits.
Make set of classes to mirror types
Implement capture conversion
Document
Doc
Implement contains for targs
Implement toString
Fully implement subtyping
Check for reifiability
Implement unchecked, fix array subtyping
Test rec typevar building
Test primitive subtyping
Test array subtyping
Test wildcards subtyping
Doc
Rename primitiveType
Reify conversions
Test boxing
Make constants for common types
Test type param mutual recursion
More defensive validation
Implement numeric promotion
Checkstyle
Implement supertype set
Implement lub
Fix infinite recursion
Fix lub bugs
Use linkedhashset for stable ordering
Add primitives to common types
Move common types into type factory
Try a lazy class resolver, needs a symbol table
Improve lazy resolver
Implement conditional expr typing
remove poly impl
Represent primitive wrappers differently
Better compromise for primitive wrappers
Extract wildcard interface
Extract array type interface
Refactor to extract interfaces
Don't depend on initialization of jprimitiveType
Finish pretty printer
Remove dependency on reflection
Fix class initialization trouble
Move to type constants
Use regular impl for OBJECT
Encapsulate ops into TypeOps
Add inference var to model
Impl some ops
Add some type inference algos
Invocation context compatibility
Add incorporation
Generify bound set with ExprOps
Add applicability tests
Fix compil
Add incorporation actions
Implement incorporation
Add inference steps
Implement brute force walk strategy
Remove some type params
Wire in everything
Implement methodtype
Access methods from JClassType
Represent enclosing types
Work on overriding
Implement expr ops
Catch easy cases
Diamond inference
Fix pretty printer
Fix concurrent mod
Test
Add reflect info to JModifier
Add symbolic type declaration
Most specific check
Test with nested invocation
Test lub
Add constraints for lambdas and all subexpressions
Resolve full call chain with lambdas
Set partial results on nodes
Test chain
Doc
Generalise expr mirrors
Fix context
Add invocation mirror
Add support for method references
make infer static
Cleanup interface
Fix constructor access
Test method reference
Cleanup method ref types
Test constructor reference
Test overload resolution, fix TODO
Fix ctdecl of mref on non-ground target type
Add graph walk strategy
Document
Use toposort
Make enum constant implement ctor invoc mirror
Work on context
Test conditional expr type
Handle switch exprs uniformly
Fix bugs
Add type inference performance test case
Add overload resolution tests
Cache result of overload selection, only recompute invocation
Optimise common case in graph building
Optimise propagation by merging variables
Fix some tests, cleanup
Preserve applicability phase
Improve jsinglechildnode
Add way to get a field's type
Make more complex stress test
Cache bound check results
Type projection for inference
Simplify lazy type inference of var ids
Improve memory usage
- reuse constant enum sets (by far the biggest leak, given the number of PropagateBounds created)
- implement substitution without a visitor
Optimise imports
Cache hash of classes
Cleanup
Add overloads test
Fix context fetching
Fix lub bug
Test switch expr
Fix rebase
Remove useless type
Factorise poly check
Remove base poly expr
Fix array initializer
Remove duplicated numeric literal typing
Fix inferred iterable type
Move method resolution phase to upper level
Delete useless var
Commit pr plan
Remove useless method
Fix enclosing type comb rule
REVERT ME Remove partial enclosing type support
Add package info
Put task list in branch description
Fix old rebases
Fix rebase
Simplify for left recursive ops
Fix comments
Fix rebase
Revert "REVERT ME Remove partial enclosing type support"
This reverts commit 8080ff1585b3a760fafc957282771baf716f3c7f.
WIP base type mirrors on symbols
Make JMethodType not a JTypeMirror
Figure out getSymbol & type vars
make type factory non-static
Add a parameter to visitors
Fix compilation
Use symbol table in lazy type resolver
Move package
Fix most tests
Move internal api around
Specify some stuff
Split reflect impl from API
Make AST impl
Equality routines
Fix tests
Move internal symtable doc
Improve symtableResolver ergonomics
Poly res tests
Make AST type factory
Update
Make lambda expressions not a MethodlikeNode
Build local var sym
Update for switches
Make Infer not static, fix logging
Don't expose visitor nature of SymbolResolver
Cleanup
Improve type error handling
Don't throw away CTdecls for an arg mismatch
Fix more tests
Local symbol tables
Symbol table looks in interfaces
Incompatible changes that should stay on this branch and not be squashed
ResolveResult
Explicitly typed lambdas
Fix some static bugs
Fix a lot of bugs
Use FQCN symtable
Move parsing contexts to upper level
Cleanup
DSL to test types
test subst
Dont create an exception for each failure
Stack trace creation takes a significant amount of time
Remove laziness for fetching method streams
Streams obfuscate performance analysis by
delaying the computation until the last
moment.
Fix some bugs with unresolved classes
Also measure performance: full typeres
is around same time as parsing. This is
great. At this point 80% of all types
are resolved (though some type inference
results are probably incorrect). Mostly
this comes from the fact that there are
still AmbiguousNames in the tree.
Fix problem with varargs
Handle enclosing types
Enclosing types
Fix compil
Add another stress test
Refactor primitive subtyping
Fix rebase
Fix rebase: tests
Figure out type factories WIP
Move type ops into TypeOps
Move AsSuper
Figure out type factories WIP
Make TypeSystem object
wip
WIP
WIP
Make typeops static
Fix grounding routine
Fix bug with return type
Start fixing tests
Cleanup primitive types
Fix some tests
Add todo
Remove JDK test dependency
Test cases lubbing String and
StringBuilder produce different
outputs on JDK [8, 11[ and 11+, because
StringBuilder was made a Comparable<StringBuilder>
in JDK 11
Implement most specific method selection
Drop JVariableSig from symbol table
Use asOuterSuper instead
Fix local var type inference with foreach.
Fix a lot of stuff based on jdk 12 run
Make type system own symbol factories
Fix intersection with bound
Fix standalone ternary types
Capture field access type
Eg class Foo<T> { T[] field; }
Foo<? extends T>.field : capture(T)[]
Add tests
Delete lexical substs
Fix reflected owner type
Add graph viz
Fix bug with graph reduction
Optimise ivar dependency reduction
by a lot. The previous 60s stress
test now takes 600ms.
Btw at this point type res for the
whole JDK 12 codebase takes 25 secs,
down from 175 on 6.20.0 (7x speedup).
Implement inherited field/class lookup
Fix scoping inside switch statements
Fix a few bugs
Handle inherited methods
Interfaces should inherit Object methods
Move lub into TypeSystem
Handle class types induced by intersections
Fix lambda congruence
Test lambda with intersection type
Fix inference
Fix same type check using equals
Simplify intersection type induction
Remove type sys extension
Simplify sym factories
Finish symbol factory streamlining
Document
Cache non-erased symbols separately
Doc
Revert, erased types are only raw
Get rid of generic constants in TypeSystem
Remove some dead code
Fix exact method reference
Improve unchecked conversion handling
Fix dependency of delegated ivars
Improve logging, fix a few bugs
Test enclosing types
Improve loggin
Print file location
Fix subtyping for wildcards
Fix standalone method types
Fix boxing conversion
Fix promotion on unary exprs
Implement special treatment of getClass()
Add tests for anon classes
Make symbol tables use lists for methods
Fix method reference with void target type
Move graphUtils
Make unresolved types bottom
(instead of top)
It's more likely to be useful. Eg.
Unresolved var = ...;
knownMethod(var);
Here, var must conform to the parameter,
if it is unresolved, we assume that's the
case. Otherwise we would fail resolution
of knownMethod for this call site.
The reverse situation is rarer.
Fix conversions in loose phase
Make JInferenceVar a class
Hide TypePair
Remove special string type
Fix toString of anon classes
Implement overload specificity for generic methdos
Fix anon class ctors
Fix Object methods not in scope in interfaces
Fixing anon class ctors WIP
Fix rebase
Cleanup
Print type var bounds
Fix tests, improve pretty printing
Hide ast sym factory
Fix array method erasure
Fix superclass, uncover bug with substitution
Substitute type param bounds
Make Array have Object methods
Fix duplicated logging categories
Make root symbolFactory thread safe
Fix overload ambiguity with hiding
Fix exact method when they shadow each other
Make PMultimap type
Make shadowGroup
Make a few utilities to replace import tables
Replace other tables
Cleanup
Compat with old impl
Fix rebase
Port to using sigs
Make base class for shadow groups
Fix method group
Test shadowing of inherited members
Fix bugs with tparams
Specialize to StringMultimap
Big optimizations
Simplify a lot of things, remove caching
of getAllMethods
Factorize group implementations
Add resolveFirst
Fix bug with ctor invocation
Fix type parsing for union types
Generify multimap
Implement nextShadowGroup
Remove unused API of pmultimap
Use interface where possible
Fix tests
Use singleton resolvers more frequently
Remove commons collections dependency
Tries don't make a significant difference
in execution time. Mostly because tries
used in symbol tables are very small.
Remove some api of jtypemirror
Fix shadow barriers
Fix accessibility check for protected member
Qualified ctor invocations have access to inner class name
Make strict stream for profiling
LOOK AT ME strict streams
Strict streams are actually *much* more
efficient for our use case
Extract some stuff into CollectionUtil
Make methods shadow each other
doc
Simplify OptionalBool
Improve strict stream
Eventually I'll remove it
Doc newer symtable
Make PMultimap type
Make shadowGroup
Make a few utilities to replace import tables
Cleanup
Checkout newer sym table from typeres branch
Port
Checkout tests
Port tests, remove old impl
Extract augment function
Move classes back into internal package
Abstract stuff away for pmd-core
Optimise singular map case even more
Fix nextShadowGroup WIP
Make ShadowIterator to replace getNextGroup
Use chain iterator
Add tests
Finish impl
Add tests for supertype enumerator
Add tests for method shadowing in imports
Port to using types etc
Fix tests
Fix outdated tests
Fix anon class ctors
Fix more outdated tests
Object methods should be in scope in interfaces
Fix compil
Make simple signature parser
Make stubs
Figure out loading logic
Progress on type param parsing
Do away with nested classes
Class signatures
It works!
Parse tvar bounds lazily
Fix a lot of stuff
No errors on pmd-core
JDK 13 under 80s
Implement toString everywhere
Try to make the whole thing thread safe
Still a spurious NPE, access flags are weird.
For j.l.invoke.DelegatingMethodHandle
(declared as `final class Holder {}`) the
access flags from the class file are 0x32, and
the enclosing type is null, while when accessed
through reflection, the access flags are correctly
0x10. The class is engineered through VM magic
so idk what happens
Remove shared caching of TypeSystem
The sub caches are not useful anymore
and creating them all the time is wasteful
Add some tests
Fix improper locking
Reorganise typeSystem initialization
Change the name
Doc
Opts
Optimise away some expensive lookaheads in the parser
Doc
Fix modifiers
Optimise big switches in parser
Placing token decls that are frequently used together closer
increases the chance that the compiler generate a TABLESWITCH
instruction instead of a LOOKUPSWITCH. Table switches take
constant lookup time, while lookupswitch is linear. Selection
of table switch is now done for the biggest switches of the
parser: the one in types, in modifiers, in statements, and
at the start of expressions. Other lookup switches are unimportant
because they have very few labels (typically 2).
Optimise variable initializer lookahead
make test rule noop
PARSER Optimise common branches in expressions
PARSER opt blocks & statements
doc
Don't accept void by default
Split signature parsers
Simplify type param parsing
Simplify type params parsing
Some optimisations
Tests
Simplify synchronization
Factorize synchronization logic
Move ConsList into pmd-core
Prune more empty nodes
Use single map for asm resolver
Remove changes to parser
Add option to suppress type inference log entry creation
Use soft references to allow class stubs to be GCed
Fix rebase
2020-02-11 04:43:54 +01:00
|
|
|
| "char" {jjtThis.setKind(PrimitiveTypeKind.CHAR);}
|
|
|
|
| "byte" {jjtThis.setKind(PrimitiveTypeKind.BYTE);}
|
|
|
|
| "short" {jjtThis.setKind(PrimitiveTypeKind.SHORT);}
|
|
|
|
| "int" {jjtThis.setKind(PrimitiveTypeKind.INT);}
|
|
|
|
| "long" {jjtThis.setKind(PrimitiveTypeKind.LONG);}
|
|
|
|
| "float" {jjtThis.setKind(PrimitiveTypeKind.FLOAT);}
|
|
|
|
| "double" {jjtThis.setKind(PrimitiveTypeKind.DOUBLE);}
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-14 07:10:15 +02:00
|
|
|
void ResultType() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2020-08-14 07:10:15 +02:00
|
|
|
"void" #VoidType
|
|
|
|
| AnnotatedType()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-27 06:21:08 +02:00
|
|
|
void ThrowsList() :
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-09-27 06:21:08 +02:00
|
|
|
"throws" AnnotatedClassOrInterfaceType() ( "," AnnotatedClassOrInterfaceType())*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Expression syntax follows.
|
|
|
|
*/
|
|
|
|
|
2019-02-18 10:53:17 +01:00
|
|
|
void Expression() #AssignmentExpression(>1):
|
2014-09-30 19:51:42 +02:00
|
|
|
/*
|
|
|
|
* This expansion has been written this way instead of:
|
|
|
|
* Assignment() | ConditionalExpression()
|
|
|
|
* for performance reasons.
|
|
|
|
* However, it is a weakening of the grammar for it allows the LHS of
|
|
|
|
* assignments to be any conditional expression whereas it can only be
|
|
|
|
* a primary expression. Consider adding a semantic predicate to work
|
|
|
|
* around this.
|
|
|
|
*/
|
2019-02-19 00:15:26 +01:00
|
|
|
{AssignmentOp op = null;}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
|
|
|
ConditionalExpression()
|
|
|
|
[
|
2019-08-15 13:54:52 +02:00
|
|
|
LOOKAHEAD(1) op=AssignmentOperator() {jjtThis.setOp(op);} Expression()
|
2014-09-30 19:51:42 +02:00
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2019-02-19 02:30:43 +01:00
|
|
|
AssignmentOp AssignmentOperator() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-09-30 15:40:38 +02:00
|
|
|
"=" { return AssignmentOp.ASSIGN; }
|
|
|
|
| "*=" { return AssignmentOp.MUL_ASSIGN; }
|
|
|
|
| "/=" { return AssignmentOp.DIV_ASSIGN; }
|
|
|
|
| "%=" { return AssignmentOp.MOD_ASSIGN; }
|
|
|
|
| "+=" { return AssignmentOp.ADD_ASSIGN; }
|
|
|
|
| "-=" { return AssignmentOp.SUB_ASSIGN; }
|
|
|
|
| "<<=" { return AssignmentOp.LEFT_SHIFT_ASSIGN; }
|
|
|
|
| ">>=" { return AssignmentOp.RIGHT_SHIFT_ASSIGN; }
|
|
|
|
| ">>>=" { return AssignmentOp.UNSIGNED_RIGHT_SHIFT_ASSIGN; }
|
|
|
|
| "&=" { return AssignmentOp.AND_ASSIGN; }
|
|
|
|
| "^=" { return AssignmentOp.XOR_ASSIGN; }
|
|
|
|
| "|=" { return AssignmentOp.OR_ASSIGN; }
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConditionalExpression() #ConditionalExpression(>1) :
|
|
|
|
{}
|
|
|
|
{
|
2019-08-15 13:54:52 +02:00
|
|
|
ConditionalOrExpression() [LOOKAHEAD(1) "?" Expression() ":" ConditionalExpression() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-08-14 21:32:40 +02:00
|
|
|
void ConditionalOrExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-08-15 13:54:52 +02:00
|
|
|
ConditionalAndExpression() (LOOKAHEAD(1) ("||" {jjtThis.setOp(BinaryOp.CONDITIONAL_OR);} ConditionalAndExpression()) #InfixExpression(2))*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-08-14 21:32:40 +02:00
|
|
|
void ConditionalAndExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-08-15 13:54:52 +02:00
|
|
|
InclusiveOrExpression() (LOOKAHEAD(1) ("&&" {jjtThis.setOp(BinaryOp.CONDITIONAL_AND);} InclusiveOrExpression()) #InfixExpression(2))*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-08-14 21:32:40 +02:00
|
|
|
void InclusiveOrExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-08-15 13:54:52 +02:00
|
|
|
ExclusiveOrExpression() (LOOKAHEAD(1) ("|" {jjtThis.setOp(BinaryOp.OR);} ExclusiveOrExpression()) #InfixExpression(2))*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-08-14 21:32:40 +02:00
|
|
|
void ExclusiveOrExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-08-15 13:54:52 +02:00
|
|
|
AndExpression() (LOOKAHEAD(1) ("^" {jjtThis.setOp(BinaryOp.XOR);} AndExpression()) #InfixExpression(2))*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-08-14 21:32:40 +02:00
|
|
|
void AndExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-08-15 13:54:52 +02:00
|
|
|
EqualityExpression() (LOOKAHEAD(1) ("&" {jjtThis.setOp(BinaryOp.AND);} EqualityExpression()) #InfixExpression(2))*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-29 19:15:13 +01:00
|
|
|
void EqualityExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-08-14 21:32:40 +02:00
|
|
|
InstanceOfExpression()
|
2019-08-15 13:54:52 +02:00
|
|
|
(LOOKAHEAD(1)
|
2019-08-14 21:32:40 +02:00
|
|
|
(
|
|
|
|
( "==" {jjtThis.setOp(BinaryOp.EQ);}
|
|
|
|
| "!=" {jjtThis.setOp(BinaryOp.NE);}
|
|
|
|
)
|
|
|
|
InstanceOfExpression()
|
|
|
|
) #InfixExpression(2)
|
|
|
|
)*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2021-07-01 17:01:48 +02:00
|
|
|
void Pattern() #void:
|
|
|
|
{}
|
|
|
|
{
|
2022-11-06 22:14:09 +01:00
|
|
|
LOOKAHEAD((Annotation())* ReferenceType() "(") RecordPattern()
|
2023-02-03 15:49:19 +01:00
|
|
|
| TypePattern()
|
2021-07-01 17:01:48 +02:00
|
|
|
}
|
|
|
|
|
2021-02-12 12:54:06 +01:00
|
|
|
void TypePattern():
|
2021-02-12 12:44:08 +01:00
|
|
|
{}
|
|
|
|
{
|
2024-06-03 16:24:41 +02:00
|
|
|
LocalVarModifierList() LocalVariableType() VariableDeclaratorId()
|
2021-02-12 12:44:08 +01:00
|
|
|
}
|
|
|
|
|
2022-07-07 15:06:52 +02:00
|
|
|
void RecordPattern():
|
2022-07-10 15:31:29 +02:00
|
|
|
{}
|
2022-07-07 15:06:52 +02:00
|
|
|
{
|
2023-02-03 19:54:19 +01:00
|
|
|
(Annotation())* ReferenceType() RecordStructurePattern()
|
2022-07-07 15:06:52 +02:00
|
|
|
}
|
|
|
|
|
2024-10-07 16:40:37 +02:00
|
|
|
void RecordStructurePattern() #PatternList:
|
2022-07-07 15:06:52 +02:00
|
|
|
{}
|
|
|
|
{
|
2023-08-05 15:13:49 +02:00
|
|
|
"(" [ ComponentPatternList() ] ")"
|
2022-07-07 15:06:52 +02:00
|
|
|
}
|
|
|
|
|
2024-10-07 16:40:37 +02:00
|
|
|
void ComponentPatternList() #void :
|
2022-07-07 15:06:52 +02:00
|
|
|
{}
|
|
|
|
{
|
2023-08-05 15:13:49 +02:00
|
|
|
ComponentPattern() ( "," ComponentPattern() )*
|
|
|
|
}
|
|
|
|
|
|
|
|
void ComponentPattern() #void:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
LOOKAHEAD({isKeyword("_")}) UnnamedPattern()
|
|
|
|
| Pattern()
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnnamedPattern():
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
softKeyword("_")
|
2021-02-12 12:44:08 +01:00
|
|
|
}
|
|
|
|
|
2019-09-26 00:49:26 +02:00
|
|
|
void InstanceOfExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-09-30 12:08:15 +02:00
|
|
|
RelationalExpression() [
|
|
|
|
("instanceof"
|
2021-02-18 10:44:23 +01:00
|
|
|
(
|
2022-07-10 17:12:30 +02:00
|
|
|
LOOKAHEAD(ReferenceType() "(") RecordPattern()
|
2024-07-26 18:50:04 +02:00
|
|
|
| AnnotatedType() [
|
2022-11-16 13:56:01 +01:00
|
|
|
VariableDeclaratorId() #TypePattern(2)
|
|
|
|
| RecordStructurePattern() #RecordPattern(2)
|
|
|
|
]
|
2022-07-10 15:05:35 +02:00
|
|
|
| Pattern()
|
2021-02-18 10:44:23 +01:00
|
|
|
)
|
2020-03-02 21:05:21 +01:00
|
|
|
{
|
|
|
|
jjtThis.setOp(BinaryOp.INSTANCEOF);
|
|
|
|
AbstractJavaNode top = jjtree.popNode();
|
|
|
|
if (top instanceof ASTPattern) {
|
2022-01-29 19:04:32 +01:00
|
|
|
if (top instanceof ASTTypePattern && !(top.getChild(0) instanceof ASTModifierList)) {
|
2021-02-18 12:58:13 +01:00
|
|
|
insertEmptyModifierListWithAnnotations(top, (AbstractJavaNode) top.getChild(0));
|
|
|
|
}
|
2020-03-02 21:05:21 +01:00
|
|
|
top = new ASTPatternExpression((ASTPattern) top);
|
|
|
|
} else {
|
|
|
|
top = new ASTTypeExpression((ASTType) top);
|
|
|
|
}
|
|
|
|
jjtree.pushNode(top);
|
|
|
|
}
|
2022-11-16 13:56:01 +01:00
|
|
|
{} // manipulate node before it is closed.
|
2018-12-22 09:01:20 +01:00
|
|
|
) #InfixExpression(2)
|
2019-09-30 12:08:15 +02:00
|
|
|
]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-07-28 15:19:52 +02:00
|
|
|
void RelationalExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-07-28 15:19:52 +02:00
|
|
|
// There technically cannot be more than one, because it wouldn't compile
|
|
|
|
// But we give it some leeway to not make the parser too knowledgeable
|
2019-03-29 19:15:13 +01:00
|
|
|
// From the JLS:
|
|
|
|
// For example, a<b<c parses as (a<b)<c, which is always a compile-time
|
|
|
|
// error, because the type of a<b is always boolean and < is not an operator
|
|
|
|
// on boolean values.
|
2019-08-14 21:32:40 +02:00
|
|
|
ShiftExpression()
|
2019-08-15 13:54:52 +02:00
|
|
|
(LOOKAHEAD(1)
|
2019-08-14 21:32:40 +02:00
|
|
|
(
|
|
|
|
(
|
|
|
|
"<" {jjtThis.setOp(BinaryOp.LT);}
|
|
|
|
| ">" {jjtThis.setOp(BinaryOp.GT);}
|
|
|
|
| "<=" {jjtThis.setOp(BinaryOp.LE);}
|
|
|
|
| ">=" {jjtThis.setOp(BinaryOp.GE);}
|
|
|
|
)
|
|
|
|
ShiftExpression()
|
|
|
|
) #InfixExpression(2)
|
|
|
|
)*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-29 18:50:43 +01:00
|
|
|
void ShiftExpression() #void:
|
|
|
|
{}
|
|
|
|
{
|
2019-08-14 21:32:40 +02:00
|
|
|
AdditiveExpression()
|
2019-08-15 13:54:52 +02:00
|
|
|
(LOOKAHEAD(1)
|
2019-08-14 21:32:40 +02:00
|
|
|
(
|
|
|
|
( "<<" {jjtThis.setOp(BinaryOp.LEFT_SHIFT);}
|
|
|
|
| RSIGNEDSHIFT() {jjtThis.setOp(BinaryOp.RIGHT_SHIFT);}
|
|
|
|
| RUNSIGNEDSHIFT() {jjtThis.setOp(BinaryOp.UNSIGNED_RIGHT_SHIFT);}
|
|
|
|
)
|
|
|
|
AdditiveExpression()
|
|
|
|
) #InfixExpression(2)
|
|
|
|
)*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-28 07:53:08 +01:00
|
|
|
void AdditiveExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-08-14 21:32:40 +02:00
|
|
|
MultiplicativeExpression()
|
2019-08-15 13:54:52 +02:00
|
|
|
(LOOKAHEAD(1)
|
2019-08-14 21:32:40 +02:00
|
|
|
(
|
|
|
|
( "+" {jjtThis.setOp(BinaryOp.ADD);}
|
|
|
|
| "-" {jjtThis.setOp(BinaryOp.SUB);}
|
|
|
|
)
|
|
|
|
MultiplicativeExpression()
|
|
|
|
) #InfixExpression(2)
|
|
|
|
)*
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-28 09:01:55 +01:00
|
|
|
void MultiplicativeExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-03-28 09:01:55 +01:00
|
|
|
UnaryExpression()
|
2019-08-15 13:54:52 +02:00
|
|
|
(LOOKAHEAD(1)
|
2019-08-14 21:32:40 +02:00
|
|
|
(
|
|
|
|
( "*" {jjtThis.setOp(BinaryOp.MUL);}
|
|
|
|
| "/" {jjtThis.setOp(BinaryOp.DIV);}
|
|
|
|
| "%" {jjtThis.setOp(BinaryOp.MOD);}
|
|
|
|
)
|
|
|
|
UnaryExpression()
|
|
|
|
) #InfixExpression(2)
|
|
|
|
)*
|
2019-03-28 09:01:55 +01:00
|
|
|
}
|
2019-07-28 15:19:52 +02:00
|
|
|
|
2019-08-14 21:32:40 +02:00
|
|
|
// TODO update operator setting for those expressions
|
|
|
|
|
2019-05-28 16:33:59 +02:00
|
|
|
void UnaryExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-12-09 14:54:05 +01:00
|
|
|
(("+" {jjtThis.setOp(UnaryOp.UNARY_PLUS);} | "-" {jjtThis.setOp(UnaryOp.UNARY_MINUS);}) UnaryExpression()) #UnaryExpression
|
2019-06-26 23:52:31 +02:00
|
|
|
| PrefixIncrementExpression()
|
2014-09-30 19:51:42 +02:00
|
|
|
| UnaryExpressionNotPlusMinus()
|
|
|
|
}
|
|
|
|
|
2019-12-09 14:54:05 +01:00
|
|
|
void PrefixIncrementExpression() #UnaryExpression:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-12-09 14:54:05 +01:00
|
|
|
("++" {jjtThis.setOp(UnaryOp.PRE_INCREMENT);}
|
|
|
|
| "--" {jjtThis.setOp(UnaryOp.PRE_DECREMENT);}
|
Split UnaryExpr into Prefix and Postfix
Among the different possible categorisations
of unary expressions, this is probably the
most logical and easiest to document.
Here's a comparison of different possible
categorisations. Note: `_++` is the postfix
increment operator, while `++_` is the prefix
one - idem for decrement. The last one is the
one implemented by this commit.
\## 6.0.x
```
Unary = { -, + }
UnaryNotPlusMinus { !, ~ }
PreIncrement = { ++_ }
PreDecrement { --_ }
Postfix { _++, _++ }
```
* Very assymmetric, splits operators based on parsing
concerns
\## Before #1890:
```
Unary = { -, + , !, ~ }
PreIncrement = { ++_ }
PreDecrement { --_ }
Postfix { _++, _++ }
```
* Minor simplification
\## #1890:
```
Unary = Prefix \ { ++_, --_ })
Increment ( { ++ , -- } x (postfix, prefix) )
```
* Names are weird (IncrementExpr may be decrement, Unary != Increment
even though semantically, Increment \subset Unary)
* No possibility to introduce a supertype (what would it be?)
* But easy to match all increment/decrement expressions
\## JLS (also, Eclipse):
```
Prefix = { !, ~, -, +, ++_, --_ }
Postfix = { _++, _-- }
```
* Both can have super interface UnaryExpr
* This allows matching all increment/decrement expressions easily too
* Easiest to document, JLS like, AST like
* Fits well with `InfixExpr`
2019-08-15 01:43:13 +02:00
|
|
|
)
|
2019-06-26 23:52:31 +02:00
|
|
|
PrimaryExpression()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-05-28 16:33:59 +02:00
|
|
|
void UnaryExpressionNotPlusMinus() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-12-09 14:54:05 +01:00
|
|
|
(( "~" {jjtThis.setOp(UnaryOp.COMPLEMENT);} | "!" {jjtThis.setOp(UnaryOp.NEGATION);}) UnaryExpression()) #UnaryExpression
|
2019-03-30 18:39:11 +01:00
|
|
|
// There's no separate production for CastExpression, because that would force
|
|
|
|
// us to repeat the lookahead
|
2019-04-28 20:03:15 +02:00
|
|
|
// Those lookaheads are quite expensive, they're run to disambiguate between
|
2019-03-31 06:49:39 +02:00
|
|
|
// ParenthesizedExpression and CastExpression.
|
2019-03-30 18:39:11 +01:00
|
|
|
| LOOKAHEAD("(" TypeAnnotationList() PrimitiveType() ")")
|
|
|
|
("(" AnnotatedType() ")" UnaryExpression()) #CastExpression
|
2019-04-28 20:03:15 +02:00
|
|
|
// here we avoid looking ahead for a whole unary expression, instead just testing the token after ")"
|
2019-09-25 06:30:17 +02:00
|
|
|
| LOOKAHEAD("(" IntersectionType() ")" UnaryExprNotPmStart() )
|
|
|
|
("(" IntersectionType() ")" UnaryExpressionNotPlusMinus()) #CastExpression
|
2014-09-30 19:51:42 +02:00
|
|
|
| PostfixExpression()
|
2019-03-15 15:29:16 +01:00
|
|
|
| SwitchExpression()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-05-22 03:58:15 +02:00
|
|
|
private void UnaryExprNotPmStart() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-05-22 03:58:15 +02:00
|
|
|
// Condensed FIRST set of UnaryExpressionNotPlusMinus
|
|
|
|
// Avoid looking ahead for a whole UnaryExpressionNotPlusMinus, but just for a token
|
|
|
|
|
2019-07-12 02:53:50 +02:00
|
|
|
"~" | "!" | "(" | "switch" | "new" | "this" | "super" | Literal() | "@"
|
2019-05-22 03:58:15 +02:00
|
|
|
| <IDENTIFIER>
|
|
|
|
| "void" | PrimitiveType()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-06-26 23:52:31 +02:00
|
|
|
void PostfixExpression() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-06-26 23:52:31 +02:00
|
|
|
|
Split UnaryExpr into Prefix and Postfix
Among the different possible categorisations
of unary expressions, this is probably the
most logical and easiest to document.
Here's a comparison of different possible
categorisations. Note: `_++` is the postfix
increment operator, while `++_` is the prefix
one - idem for decrement. The last one is the
one implemented by this commit.
\## 6.0.x
```
Unary = { -, + }
UnaryNotPlusMinus { !, ~ }
PreIncrement = { ++_ }
PreDecrement { --_ }
Postfix { _++, _++ }
```
* Very assymmetric, splits operators based on parsing
concerns
\## Before #1890:
```
Unary = { -, + , !, ~ }
PreIncrement = { ++_ }
PreDecrement { --_ }
Postfix { _++, _++ }
```
* Minor simplification
\## #1890:
```
Unary = Prefix \ { ++_, --_ })
Increment ( { ++ , -- } x (postfix, prefix) )
```
* Names are weird (IncrementExpr may be decrement, Unary != Increment
even though semantically, Increment \subset Unary)
* No possibility to introduce a supertype (what would it be?)
* But easy to match all increment/decrement expressions
\## JLS (also, Eclipse):
```
Prefix = { !, ~, -, +, ++_, --_ }
Postfix = { _++, _-- }
```
* Both can have super interface UnaryExpr
* This allows matching all increment/decrement expressions easily too
* Easiest to document, JLS like, AST like
* Fits well with `InfixExpr`
2019-08-15 01:43:13 +02:00
|
|
|
PrimaryExpression()
|
|
|
|
[
|
|
|
|
LOOKAHEAD(1)
|
2019-12-09 14:54:05 +01:00
|
|
|
("++" {jjtThis.setOp(UnaryOp.POST_INCREMENT);}
|
|
|
|
| "--" {jjtThis.setOp(UnaryOp.POST_DECREMENT);}
|
|
|
|
) #UnaryExpression(1)
|
Split UnaryExpr into Prefix and Postfix
Among the different possible categorisations
of unary expressions, this is probably the
most logical and easiest to document.
Here's a comparison of different possible
categorisations. Note: `_++` is the postfix
increment operator, while `++_` is the prefix
one - idem for decrement. The last one is the
one implemented by this commit.
\## 6.0.x
```
Unary = { -, + }
UnaryNotPlusMinus { !, ~ }
PreIncrement = { ++_ }
PreDecrement { --_ }
Postfix { _++, _++ }
```
* Very assymmetric, splits operators based on parsing
concerns
\## Before #1890:
```
Unary = { -, + , !, ~ }
PreIncrement = { ++_ }
PreDecrement { --_ }
Postfix { _++, _++ }
```
* Minor simplification
\## #1890:
```
Unary = Prefix \ { ++_, --_ })
Increment ( { ++ , -- } x (postfix, prefix) )
```
* Names are weird (IncrementExpr may be decrement, Unary != Increment
even though semantically, Increment \subset Unary)
* No possibility to introduce a supertype (what would it be?)
* But easy to match all increment/decrement expressions
\## JLS (also, Eclipse):
```
Prefix = { !, ~, -, +, ++_, --_ }
Postfix = { _++, _-- }
```
* Both can have super interface UnaryExpr
* This allows matching all increment/decrement expressions easily too
* Easiest to document, JLS like, AST like
* Fits well with `InfixExpr`
2019-08-15 01:43:13 +02:00
|
|
|
]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-02-17 06:33:30 +01:00
|
|
|
|
2019-03-15 15:29:16 +01:00
|
|
|
void SwitchExpression() :
|
2020-03-17 21:36:15 +01:00
|
|
|
{boolean prevInSwitchBlock = inSwitchExprBlock;}
|
2019-03-15 15:29:16 +01:00
|
|
|
{
|
2020-03-17 21:36:15 +01:00
|
|
|
"switch" "(" Expression() ")"
|
|
|
|
{inSwitchExprBlock = true;}
|
|
|
|
SwitchBlock()
|
|
|
|
{inSwitchExprBlock = prevInSwitchBlock;}
|
2019-03-15 15:29:16 +01:00
|
|
|
}
|
|
|
|
|
2019-02-17 14:25:07 +01:00
|
|
|
/**
|
|
|
|
* A primary expression. This includes call chains, etc.
|
|
|
|
*
|
|
|
|
* A PrimaryPrefix corresponds to an unqualified primary expression,
|
|
|
|
* e.g "new Foo()". Then, if any, suffixes of the form e.g. ".method()",
|
|
|
|
* ".field" or "::ref" are added, each time enclosing the previous node.
|
2019-05-25 02:32:23 +02:00
|
|
|
* Iteration stops after the first method reference, or we can't continue.
|
2019-02-17 14:25:07 +01:00
|
|
|
*
|
|
|
|
* The resulting subtree looks left-recursive, but the parsing is iterative.
|
|
|
|
*/
|
2019-02-17 06:33:30 +01:00
|
|
|
void PrimaryExpression() #void :
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-05-25 02:32:23 +02:00
|
|
|
// the lookahead here stops iteration after the first method reference,
|
|
|
|
// because nothing can be chained after a method reference.
|
|
|
|
PrimaryPrefix() ( LOOKAHEAD(SuffixLAhead(), {!(jjtree.peekNode() instanceof ASTMethodReference)}) PrimarySuffix() )* {forceExprContext();}
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-02-18 16:59:23 +01:00
|
|
|
/*
|
|
|
|
Expressions that may be present at the start of a primary expression.
|
|
|
|
*/
|
2019-02-17 06:33:30 +01:00
|
|
|
void PrimaryPrefix() #void :
|
2019-08-06 10:35:14 +02:00
|
|
|
{JavaccToken savedStart;}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
|
|
|
Literal()
|
2019-02-18 16:59:23 +01:00
|
|
|
| "this" #ThisExpression
|
2019-05-25 01:53:13 +02:00
|
|
|
| "super" #SuperExpression(true)
|
|
|
|
("." MemberSelector() | MethodReference())
|
2019-05-24 16:33:48 +02:00
|
|
|
| UnqualifiedAllocationExpr()
|
2020-08-14 07:10:15 +02:00
|
|
|
| ("void" #VoidType "." "class") #ClassLiteral
|
2020-01-25 02:40:35 +01:00
|
|
|
| LOOKAHEAD(1) // suppress the warning here.
|
|
|
|
(PrimitiveType() [ Dims() ] ) #ArrayType(>1)
|
2019-05-24 16:33:48 +02:00
|
|
|
(
|
|
|
|
MethodReference()
|
|
|
|
| "." "class" #ClassLiteral(1)
|
|
|
|
)
|
|
|
|
|
2019-06-26 04:55:43 +02:00
|
|
|
// If annotations start the expression, it's necessarily a method or ctor reference
|
|
|
|
// This is because types in class literals or in qualified super/this may not be annotated
|
2020-01-25 02:40:35 +01:00
|
|
|
| LOOKAHEAD("@") AnnotatedRefType() MethodReference()
|
2019-06-26 04:55:43 +02:00
|
|
|
|
2019-05-26 16:47:22 +02:00
|
|
|
| LOOKAHEAD(LambdaLahead()) LambdaExpression()
|
|
|
|
|
2019-07-22 12:31:59 +02:00
|
|
|
// Parenthesized expr, we need to adjust start/end tokens
|
|
|
|
| "(" {savedStart = getToken(0);} Expression() ")"
|
|
|
|
{
|
|
|
|
AstImplUtil.bumpParenDepth((ASTExpression) jjtree.peekNode());
|
|
|
|
AbstractJavaNode top = (AbstractJavaNode) jjtree.peekNode();
|
2020-05-02 20:54:41 +02:00
|
|
|
top.setFirstToken(savedStart);
|
|
|
|
top.setLastToken(getToken(0));
|
2019-07-22 12:31:59 +02:00
|
|
|
}
|
2019-05-25 02:05:42 +02:00
|
|
|
// If it is an ambiguous name, then we may go on
|
|
|
|
// into the next step, which is less restricted
|
|
|
|
// than PrimarySuffix
|
2019-05-24 17:29:36 +02:00
|
|
|
| AmbiguousName() [ LOOKAHEAD(Step2Lahead()) PrimaryStep2() ]
|
|
|
|
}
|
|
|
|
|
2019-05-25 02:05:42 +02:00
|
|
|
// This describes the cases where the PrimaryPrefix may fall
|
2019-05-28 16:33:59 +02:00
|
|
|
// into PrimaryStep2, after seeing an AmbiguousName. Notice
|
|
|
|
// that type arguments is still possible, as well as annotations
|
|
|
|
// ("@") before an annotated array type, or qualified "this".
|
2019-05-25 03:09:23 +02:00
|
|
|
// If we are in an explicit constructor invocation, then super is disallowed.
|
2019-05-24 17:29:36 +02:00
|
|
|
private void Step2Lahead() #void:
|
|
|
|
{}
|
|
|
|
{
|
2019-05-25 03:21:42 +02:00
|
|
|
"::" | "(" | "@" | "["
|
|
|
|
// the type arguments must be followed by what may complete a class type + method ref
|
|
|
|
// otherwise we choke on eg `i < w >> 1`, because `< w >` matches type arguments
|
|
|
|
| TypeArguments() ("[" | "." | "@" | "::")
|
2019-05-24 17:29:36 +02:00
|
|
|
| LOOKAHEAD({!inExplicitConstructorInvoc}) "."
|
2019-05-25 03:09:23 +02:00
|
|
|
| LOOKAHEAD({inExplicitConstructorInvoc}) "." ("class" | <IDENTIFIER> | TypeArguments() <IDENTIFIER> | "new" | "this") // not super in this case
|
2019-05-24 17:29:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void SuffixLAhead() #void:
|
|
|
|
{}
|
|
|
|
{
|
2019-05-25 02:15:35 +02:00
|
|
|
// this is simpler than the step 2 lookahead
|
2019-05-24 17:29:36 +02:00
|
|
|
"::" | "["
|
|
|
|
| LOOKAHEAD({!inExplicitConstructorInvoc}) "."
|
|
|
|
| LOOKAHEAD({inExplicitConstructorInvoc}) "." (<IDENTIFIER> | TypeArguments() <IDENTIFIER> | "new") // not super or this in this case
|
2019-05-24 16:33:48 +02:00
|
|
|
}
|
|
|
|
|
2019-05-24 17:29:36 +02:00
|
|
|
|
2019-05-24 19:47:42 +02:00
|
|
|
// Step right after the *first* ambiguous name if any.
|
|
|
|
// Then we have more options than a primary suffix,
|
|
|
|
// we can still expect to have some class type and a
|
|
|
|
// class literal, or some type arguments and a method reference
|
2019-05-24 16:33:48 +02:00
|
|
|
void PrimaryStep2() #void:
|
|
|
|
{}
|
|
|
|
{
|
2019-05-25 03:21:42 +02:00
|
|
|
// If we find type parameters, then we can only expect a method reference
|
|
|
|
// class literals or qualifiers to static member access/call may not be parameterised
|
2019-05-25 03:09:23 +02:00
|
|
|
{forceTypeContext();} TypeArguments() {injectTop();} ( "." ClassTypeSegment() )* [ Dims() #ArrayType(2) ] MethodReference()
|
2019-05-24 16:33:48 +02:00
|
|
|
| MethodReference()
|
|
|
|
| ArgumentList() #MethodCall(2)
|
|
|
|
| "." (
|
|
|
|
{forceTypeContext();} "class" #ClassLiteral(1)
|
2019-05-25 02:05:42 +02:00
|
|
|
// qualified this or super
|
|
|
|
| {forceTypeContext();} "this" #ThisExpression(1)
|
|
|
|
| {forceTypeContext();} "super" #SuperExpression(1)
|
|
|
|
// here we force the super to be followed by something,
|
|
|
|
// "super" alone is not a valid expression
|
|
|
|
("." MemberSelector() | MethodReference())
|
2019-05-24 16:33:48 +02:00
|
|
|
| MemberSelector()
|
2024-04-12 17:59:10 +02:00
|
|
|
| {forceExprContext();} Template() #TemplateExpression(2)
|
2019-05-24 16:33:48 +02:00
|
|
|
)
|
2019-05-28 16:33:59 +02:00
|
|
|
// catches the case where the ambig name is the start of an array type
|
2019-05-24 16:33:48 +02:00
|
|
|
| LOOKAHEAD("@" | "[" "]") {forceTypeContext();} Dims() #ArrayType(2) (MethodReference() | "." "class" #ClassLiteral(1))
|
2019-05-28 16:33:59 +02:00
|
|
|
// and here, the array expr in an array access
|
2019-05-25 02:15:35 +02:00
|
|
|
| {forceExprContext();} "[" Expression() "]" #ArrayAccess(2)
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-29 19:15:13 +01:00
|
|
|
/**
|
2019-05-28 16:33:59 +02:00
|
|
|
* Productions that may be present after a PrimaryPrefix. Basically
|
|
|
|
* allows for call chains. We loop on this production in PrimaryExpression.
|
2019-02-18 16:59:23 +01:00
|
|
|
*/
|
2019-02-17 10:28:12 +01:00
|
|
|
void PrimarySuffix() #void :
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-03-24 19:27:59 +01:00
|
|
|
MethodReference()
|
2019-05-25 02:15:35 +02:00
|
|
|
| {forceExprContext();} "[" Expression() "]" #ArrayAccess(2)
|
2019-05-24 16:33:48 +02:00
|
|
|
| "." MemberSelector()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-05-24 19:47:42 +02:00
|
|
|
/**
|
2019-05-25 02:32:23 +02:00
|
|
|
* Part of a primary suffix that immediately follows a dot. Also
|
|
|
|
* part of step 2.
|
2019-05-24 19:47:42 +02:00
|
|
|
*/
|
2019-03-24 19:27:59 +01:00
|
|
|
void MemberSelector() #void :
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-05-25 02:13:28 +02:00
|
|
|
/* JLS §6.5.1:
|
|
|
|
* A name is syntactically classified as an ExpressionName [...] as the
|
|
|
|
* qualifying expression in a qualified class instance creation expression (§15.9)*
|
|
|
|
*/
|
2019-05-25 02:15:35 +02:00
|
|
|
{forceExprContext();} QualifiedAllocationExpr()
|
2019-03-24 19:27:59 +01:00
|
|
|
// if there are type arguments, this is a method call
|
2019-05-25 02:15:35 +02:00
|
|
|
| (TypeArguments() <IDENTIFIER> {setLastTokenImage(jjtThis);} ArgumentList()) #MethodCall(3)
|
|
|
|
| LOOKAHEAD(2) (<IDENTIFIER> {setLastTokenImage(jjtThis);} ArgumentList()) #MethodCall(2)
|
|
|
|
| (<IDENTIFIER> {setLastTokenImage(jjtThis);}) #FieldAccess(1)
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-01-25 02:40:35 +01:00
|
|
|
void MethodReference() #MethodReference(jjtree.nodeArity() + 1): // LHS is injected
|
2019-09-25 06:30:17 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-01-25 02:40:35 +01:00
|
|
|
"::"
|
2019-05-24 16:33:48 +02:00
|
|
|
[TypeArguments()]
|
2024-02-08 17:50:37 +01:00
|
|
|
( "new" | <IDENTIFIER> ) { jjtThis.setMethodName(getToken(0).getImage()); }
|
2019-05-25 01:49:38 +02:00
|
|
|
{/* empty, to set the image before jjtClose */}
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-05-24 19:47:42 +02:00
|
|
|
// This factorises the lookahead for a lambda expression
|
|
|
|
// It's necessary because in all contexts a lambda may appear in,
|
|
|
|
// the arguments could be interpreted as a variable reference,
|
|
|
|
// or the start of a parenthesized expression
|
|
|
|
private void LambdaLahead() #void :
|
|
|
|
{}
|
|
|
|
{
|
2019-07-22 06:03:04 +02:00
|
|
|
LOOKAHEAD({!inSwitchLabel}) LambdaParameterList() "->"
|
2019-05-24 19:47:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Lambda expressions are not a PrimaryExpression in the JLS, instead they're
|
|
|
|
// separated from the AssignmentExpression production. Their use is restricted
|
|
|
|
// to method and constructor call argument, cast operand, the RHS of assignments,
|
|
|
|
// and the tail of a ternary expression
|
|
|
|
// https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.27
|
|
|
|
//
|
|
|
|
// To prevent LambdaExpressions in switch labels, the field #inSwitchLabel is used
|
|
|
|
// as a workaround.
|
2019-03-31 06:49:39 +02:00
|
|
|
void LambdaExpression():
|
2019-09-25 06:30:17 +02:00
|
|
|
{ }
|
2018-07-19 22:00:34 +02:00
|
|
|
{
|
2019-03-31 06:49:39 +02:00
|
|
|
LambdaParameterList() "->" ( Expression() | Block() )
|
2018-07-19 22:00:34 +02:00
|
|
|
}
|
|
|
|
|
2019-03-31 06:49:39 +02:00
|
|
|
void LambdaParameterList():
|
2018-07-19 22:00:34 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
SimpleLambdaParam()
|
2019-03-31 06:49:39 +02:00
|
|
|
| LOOKAHEAD("(" <IDENTIFIER> ("," | ")"))
|
2019-07-01 15:55:14 +02:00
|
|
|
"(" [ SimpleLambdaParam() ( "," SimpleLambdaParam())* ] ")"
|
2019-03-31 06:49:39 +02:00
|
|
|
| "(" [ LambdaParameter() ( "," LambdaParameter() )* ] ")"
|
2018-07-19 22:00:34 +02:00
|
|
|
}
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void SimpleLambdaParam() #LambdaParameter:
|
|
|
|
{pushEmptyModifierList();}
|
2019-05-28 19:16:04 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
VariableDeclaratorId()
|
2019-05-28 19:16:04 +02:00
|
|
|
}
|
2019-07-01 15:55:14 +02:00
|
|
|
|
|
|
|
void LambdaParameter():
|
|
|
|
{}
|
2018-07-19 22:00:34 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
LocalVarModifierList() // this weakens the grammar a bit
|
2019-03-31 06:49:39 +02:00
|
|
|
[
|
2019-07-01 15:55:14 +02:00
|
|
|
LambdaParameterType()
|
2019-03-31 06:49:39 +02:00
|
|
|
]
|
2019-12-15 03:53:10 +01:00
|
|
|
VariableIdWithDims()
|
2018-07-19 22:00:34 +02:00
|
|
|
}
|
|
|
|
|
2019-03-31 06:49:39 +02:00
|
|
|
/** Returns true if this is "var". */
|
|
|
|
boolean LambdaParameterType() #void :
|
2018-07-19 22:00:34 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-03-31 06:49:39 +02:00
|
|
|
LOOKAHEAD( { jdkVersion >= 11 && isKeyword("var") } )
|
2019-12-15 03:53:10 +01:00
|
|
|
<IDENTIFIER> { return true; }
|
|
|
|
| FormalParamType() { return false; }
|
2018-07-19 22:00:34 +02:00
|
|
|
}
|
|
|
|
|
2023-08-04 17:13:48 +02:00
|
|
|
void Template() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
StringTemplate()
|
|
|
|
| TextBlockTemplate()
|
2024-04-12 17:59:10 +02:00
|
|
|
| <STRING_LITERAL> #TemplateFragment
|
|
|
|
| <TEXT_BLOCK_LITERAL> #TemplateFragment
|
2023-08-04 17:13:48 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void StringTemplate() #void :
|
|
|
|
{}
|
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
<STRING_TEMPLATE_BEGIN> #TemplateFragment
|
2023-08-04 17:13:48 +02:00
|
|
|
EmbeddedExpression()
|
2024-04-12 17:59:10 +02:00
|
|
|
(LOOKAHEAD(2) (<RBRACE> <STRING_TEMPLATE_MID> ) #TemplateFragment EmbeddedExpression() )*
|
|
|
|
(<RBRACE> <STRING_TEMPLATE_END>) #TemplateFragment
|
2023-08-04 17:13:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void TextBlockTemplate() #void :
|
|
|
|
{}
|
|
|
|
{
|
2023-08-10 11:27:53 +02:00
|
|
|
|
2024-04-12 17:59:10 +02:00
|
|
|
<TEXT_BLOCK_TEMPLATE_MID> #TemplateFragment
|
2023-08-04 17:13:48 +02:00
|
|
|
EmbeddedExpression()
|
2024-04-12 17:59:10 +02:00
|
|
|
(LOOKAHEAD(2) ( <RBRACE> <TEXT_BLOCK_TEMPLATE_MID> ) #TemplateFragment EmbeddedExpression() )*
|
|
|
|
(<RBRACE> <TEXT_BLOCK_LITERAL>) #TemplateFragment
|
2023-08-04 17:13:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void EmbeddedExpression() #void :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
[ Expression() ]
|
|
|
|
}
|
|
|
|
|
2019-02-17 05:41:33 +01:00
|
|
|
void Literal() #void :
|
2020-04-08 21:06:19 +02:00
|
|
|
{}
|
2016-10-12 16:58:33 -03:00
|
|
|
{
|
2019-02-17 05:41:33 +01:00
|
|
|
NumericLiteral()
|
|
|
|
| StringLiteral()
|
|
|
|
| CharLiteral()
|
|
|
|
| ("true" { jjtThis.setTrue(); } | "false") #BooleanLiteral
|
|
|
|
| "null" #NullLiteral
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-02-17 05:41:33 +01:00
|
|
|
|
|
|
|
void NumericLiteral():
|
2020-02-07 23:43:26 +01:00
|
|
|
{}
|
2016-10-12 16:58:33 -03:00
|
|
|
{
|
2020-02-07 23:43:26 +01:00
|
|
|
( <INTEGER_LITERAL> { jjtThis.setIntLiteral(); }
|
|
|
|
| <FLOATING_POINT_LITERAL> { jjtThis.setFloatLiteral(); }
|
2019-02-17 05:41:33 +01:00
|
|
|
)
|
2020-02-07 23:43:26 +01:00
|
|
|
{ setLastTokenImage(jjtThis); }
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-02-17 05:41:33 +01:00
|
|
|
void CharLiteral():
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2020-02-07 23:43:26 +01:00
|
|
|
<CHARACTER_LITERAL> { setLastTokenImage(jjtThis); }
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-02-17 05:41:33 +01:00
|
|
|
void StringLiteral():
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
2019-02-17 05:41:33 +01:00
|
|
|
{
|
2019-09-14 15:31:03 +02:00
|
|
|
( <STRING_LITERAL>
|
2020-02-07 23:43:26 +01:00
|
|
|
| <TEXT_BLOCK_LITERAL> { jjtThis.setTextBlock(); }
|
|
|
|
)
|
|
|
|
{ setLastTokenImage(jjtThis); }
|
2019-02-17 05:41:33 +01:00
|
|
|
}
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
|
|
void ArgumentList() :
|
|
|
|
{}
|
|
|
|
{
|
2019-02-17 06:33:30 +01:00
|
|
|
"(" [ Expression() ( "," Expression() )* ] ")"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-17 14:25:07 +01:00
|
|
|
// more straightforward because can't be an array creation expr
|
2020-01-25 02:40:35 +01:00
|
|
|
void QualifiedAllocationExpr() #ConstructorCall(jjtree.nodeArity() + 1):
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-02-17 14:25:07 +01:00
|
|
|
"new"
|
|
|
|
[ TypeArguments() ]
|
2019-05-28 19:16:04 +02:00
|
|
|
AnnotatedClassOrInterfaceType()
|
2019-04-26 00:27:23 +02:00
|
|
|
ArgumentList()
|
2019-07-01 15:55:14 +02:00
|
|
|
[ AnonymousClassDeclaration() ]
|
2019-02-17 14:25:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void AnonymousClassDeclaration():
|
|
|
|
{
|
|
|
|
pushEmptyModifierList();
|
|
|
|
}
|
|
|
|
{
|
|
|
|
ClassOrInterfaceBody()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-17 14:25:07 +01:00
|
|
|
// this is much weaker than the JLS but since we parse compilable code
|
|
|
|
// the actual terms we get respect the JLS.
|
|
|
|
|
|
|
|
// only used in PrimaryPrefix
|
|
|
|
void UnqualifiedAllocationExpr() #void :
|
2019-03-26 18:09:47 +01:00
|
|
|
{
|
|
|
|
boolean isArrayInit=false;
|
|
|
|
}
|
2019-02-17 14:25:07 +01:00
|
|
|
{
|
|
|
|
(
|
2014-09-30 19:51:42 +02:00
|
|
|
(
|
2019-05-29 12:56:34 +02:00
|
|
|
"new" [ TypeArguments() ] TypeAnnotationList()
|
2019-02-17 14:25:07 +01:00
|
|
|
(
|
2019-03-26 18:09:47 +01:00
|
|
|
PrimitiveType() ArrayDimsAndInits(){isArrayInit=true;}
|
2019-02-17 14:25:07 +01:00
|
|
|
|
|
|
|
|
ClassOrInterfaceType()
|
|
|
|
(
|
2019-03-26 18:09:47 +01:00
|
|
|
ArrayDimsAndInits() {isArrayInit=true;}
|
2019-02-17 14:25:07 +01:00
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
ArgumentList() [ AnonymousClassDeclaration() ]
|
2019-02-17 14:25:07 +01:00
|
|
|
)
|
|
|
|
)
|
2019-03-26 18:09:47 +01:00
|
|
|
{/*Empty unit, important*/}
|
2014-09-30 19:51:42 +02:00
|
|
|
)
|
2019-03-26 18:09:47 +01:00
|
|
|
#ArrayAllocation(isArrayInit)
|
2019-02-17 14:25:07 +01:00
|
|
|
)
|
2019-03-26 18:09:47 +01:00
|
|
|
#ConstructorCall(!isArrayInit)
|
2019-02-17 14:25:07 +01:00
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-02-17 14:25:07 +01:00
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
/*
|
2019-08-15 17:14:49 +02:00
|
|
|
* The array dimensions are appended to the array type and they're both
|
|
|
|
* enclosed into an ArrayType node.
|
2014-09-30 19:51:42 +02:00
|
|
|
*/
|
2019-03-26 18:09:47 +01:00
|
|
|
void ArrayDimsAndInits() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-08-15 17:39:44 +02:00
|
|
|
LOOKAHEAD(TypeAnnotationList() "[" "]" ) (((ArrayTypeDim())+) #ArrayDimensions) #ArrayType(2) [ ArrayInitializer() ]
|
|
|
|
| ( (ArrayDimExpr())+ #ArrayDimensions ) #ArrayType(2)
|
2019-03-26 18:09:47 +01:00
|
|
|
}
|
2017-05-30 15:15:44 +02:00
|
|
|
|
2019-08-15 17:14:49 +02:00
|
|
|
// may push either an ArrayDimExpr or ArrayTypeDim
|
2019-03-26 18:09:47 +01:00
|
|
|
void ArrayDimExpr() #void:
|
|
|
|
{boolean hasExpr=false;}
|
|
|
|
{
|
2019-05-29 12:56:34 +02:00
|
|
|
((TypeAnnotListNoInject() "[" [ Expression() {hasExpr=true;} ] "]") #ArrayDimExpr(hasExpr) ) #ArrayTypeDim(!hasExpr)
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Statement syntax follows.
|
|
|
|
*/
|
|
|
|
|
2019-12-14 03:32:17 +01:00
|
|
|
void Statement() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2020-08-23 15:38:21 +02:00
|
|
|
StatementNoIdent()
|
|
|
|
// testing the hard cases last optimises the code gen
|
|
|
|
// all the previous cases are trivial for the parser
|
|
|
|
// because they start with a different token
|
2020-03-17 21:36:15 +01:00
|
|
|
| LOOKAHEAD( { isYieldStart() } ) YieldStatement()
|
2020-08-23 15:38:21 +02:00
|
|
|
| LOOKAHEAD( { isAssertStart() } ) AssertStatement()
|
|
|
|
| LOOKAHEAD(2) LabeledStatement()
|
|
|
|
| ( StatementExpression() ";" ) #ExpressionStatement
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatementNoIdent() #void:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
Block()
|
2014-09-30 19:51:42 +02:00
|
|
|
| EmptyStatement()
|
|
|
|
| SwitchStatement()
|
|
|
|
| IfStatement()
|
|
|
|
| WhileStatement()
|
|
|
|
| DoStatement()
|
|
|
|
| ForStatement()
|
|
|
|
| BreakStatement()
|
|
|
|
| ContinueStatement()
|
|
|
|
| ReturnStatement()
|
|
|
|
| ThrowStatement()
|
|
|
|
| SynchronizedStatement()
|
|
|
|
| TryStatement()
|
|
|
|
}
|
|
|
|
|
|
|
|
void LabeledStatement() :
|
2020-02-07 23:43:26 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-02-07 23:43:26 +01:00
|
|
|
<IDENTIFIER> { setLastTokenImage(jjtThis); } ":" Statement()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Block() :
|
2020-02-07 23:23:54 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2023-08-10 11:27:53 +02:00
|
|
|
( BlockStatement() )*
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-12-14 03:32:17 +01:00
|
|
|
void BlockStatement() #void:
|
2020-08-23 15:38:21 +02:00
|
|
|
{} // Note: this has been written this way to minimize lookaheads
|
|
|
|
// This generates a table switch with very few lookaheads
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-08-23 15:38:21 +02:00
|
|
|
LOOKAHEAD(1, "@" | "final" )
|
2020-08-16 21:37:39 +02:00
|
|
|
// this eagerly parses all modifiers and annotations. After that, either a local type declaration
|
|
|
|
// or a local variable declaration follows.
|
|
|
|
// This allows more modifiers for local variables than actually allowed
|
2020-08-23 15:38:21 +02:00
|
|
|
|
2020-08-23 22:00:09 +02:00
|
|
|
// The ModifierList is adopted by the next node to open
|
2020-08-23 15:38:21 +02:00
|
|
|
ModifierList() (
|
|
|
|
LOOKAHEAD({localTypeDeclAfterModifiers()}) LocalTypeDecl()
|
2020-08-23 22:00:09 +02:00
|
|
|
| LOOKAHEAD({true}) LocalVariableDeclarationPendingModifiers() ";" { fixLastToken(); }
|
2020-08-16 21:37:39 +02:00
|
|
|
)
|
2020-08-23 15:38:21 +02:00
|
|
|
| LOOKAHEAD(1, <IDENTIFIER>)
|
|
|
|
(
|
|
|
|
LOOKAHEAD({ localTypeDeclGivenNextIsIdent() }) ModifierList() LocalTypeDecl()
|
|
|
|
| LOOKAHEAD({ isAssertStart() }) AssertStatement()
|
|
|
|
| LOOKAHEAD({ isYieldStart() }) YieldStatement()
|
|
|
|
| LOOKAHEAD({ getToken(2).kind == COLON }) LabeledStatement()
|
2020-08-23 15:53:58 +02:00
|
|
|
| LOOKAHEAD(ReferenceType() <IDENTIFIER>) LocalVariableDeclaration() ";" { fixLastToken(); }
|
2020-08-23 15:38:21 +02:00
|
|
|
| LOOKAHEAD({true}) ExpressionStatement()
|
|
|
|
)
|
|
|
|
| LOOKAHEAD(1, LocalTypeStartNoIdent()) ModifierList() LocalTypeDecl()
|
|
|
|
| LOOKAHEAD(1) StatementNoIdent()
|
|
|
|
| LOOKAHEAD(Type() <IDENTIFIER>) LocalVariableDeclaration() ";" { fixLastToken(); }
|
|
|
|
| LOOKAHEAD({true}) ExpressionStatement()
|
2019-05-30 14:53:16 +02:00
|
|
|
}
|
|
|
|
|
2020-08-23 15:38:21 +02:00
|
|
|
private void LocalTypeStartNoIdent() #void: // A lookahead
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2020-08-23 21:31:32 +02:00
|
|
|
{ // notice: not default, not synchronized, not final
|
|
|
|
"public" | "static" | "protected" | "private"
|
|
|
|
| "abstract" | "native" | "transient"
|
2020-08-23 15:38:21 +02:00
|
|
|
| "volatile" | "strictfp"
|
|
|
|
|
|
|
|
| "class" | "interface"
|
|
|
|
}
|
|
|
|
|
|
|
|
void LocalTypeDecl() #void:
|
|
|
|
{} // At the point this is called, a ModifierList is on the top of the stack,
|
|
|
|
{ // waiting for the next node to open. We want that node to be the type declaration,
|
|
|
|
// not the wrapper statement node.
|
|
|
|
( ClassOrInterfaceDeclaration()
|
2020-08-22 21:39:14 +02:00
|
|
|
| LOOKAHEAD({isKeyword("record")}) RecordDeclaration()
|
|
|
|
| LOOKAHEAD({isKeyword("enum")}) EnumDeclaration()
|
2020-08-23 15:38:21 +02:00
|
|
|
) {
|
|
|
|
// Wrap the type decl into a statement
|
|
|
|
// This can't be done with regular jjtree constructs, as the ModifierList
|
|
|
|
// is adopted by the first node to be opened.
|
2023-12-13 08:39:09 +01:00
|
|
|
ASTTypeDeclaration type = (ASTTypeDeclaration) jjtree.popNode();
|
2020-08-23 15:38:21 +02:00
|
|
|
ASTLocalClassStatement stmt = new ASTLocalClassStatement(type);
|
|
|
|
jjtree.pushNode(stmt);
|
|
|
|
}
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2018-05-28 21:13:11 +02:00
|
|
|
/*
|
|
|
|
* See https://docs.oracle.com/javase/specs/jls/se10/html/jls-14.html#jls-14.4
|
|
|
|
*/
|
2014-09-30 19:51:42 +02:00
|
|
|
void LocalVariableDeclaration() :
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
LocalVarModifierList()
|
2018-05-28 21:13:11 +02:00
|
|
|
LocalVariableType()
|
2014-09-30 19:51:42 +02:00
|
|
|
VariableDeclarator()
|
|
|
|
( "," VariableDeclarator() )*
|
|
|
|
}
|
|
|
|
|
2020-08-23 22:00:09 +02:00
|
|
|
void LocalVariableDeclarationPendingModifiers() #LocalVariableDeclaration:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
// no ModifierList, it's pending at this time
|
|
|
|
LocalVariableType()
|
|
|
|
VariableDeclarator()
|
|
|
|
( "," VariableDeclarator() )*
|
|
|
|
}
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
private void LocalVarModifierList() #ModifierList:
|
|
|
|
{Set<JModifier> set = Collections.emptySet(); }
|
2019-05-28 19:16:04 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
( "final" { set = ASTModifierList.JUST_FINAL; } | Annotation() )*
|
|
|
|
{jjtThis.setDeclaredModifiers(set);}
|
2019-05-28 19:16:04 +02:00
|
|
|
}
|
|
|
|
|
2019-05-29 13:39:52 +02:00
|
|
|
void LocalVariableType() #void:
|
2018-05-28 21:13:11 +02:00
|
|
|
{}
|
|
|
|
{
|
|
|
|
LOOKAHEAD( { jdkVersion >= 10 && isKeyword("var") } ) <IDENTIFIER>
|
|
|
|
| Type()
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
void EmptyStatement() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
";"
|
|
|
|
}
|
|
|
|
|
2019-12-14 03:32:17 +01:00
|
|
|
void EmptyDeclaration() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
";"
|
|
|
|
}
|
|
|
|
|
2020-08-23 15:38:21 +02:00
|
|
|
void ExpressionStatement():
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
StatementExpression() ";"
|
|
|
|
}
|
|
|
|
|
2019-12-14 03:32:17 +01:00
|
|
|
void StatementExpression() #void:
|
2019-02-19 00:15:26 +01:00
|
|
|
{AssignmentOp op = null;}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-06-26 23:52:31 +02:00
|
|
|
PrefixIncrementExpression()
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
2019-03-31 06:49:39 +02:00
|
|
|
// using PostfixExpression here allows us to skip the part of the production tree
|
2019-02-18 10:53:17 +01:00
|
|
|
// between Expression() and PostfixExpression()
|
|
|
|
(PostfixExpression() [ op=AssignmentOperator() {jjtThis.setOp(op);} Expression() ]) #AssignmentExpression(>1)
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-15 15:29:16 +01:00
|
|
|
void SwitchStatement():
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2019-03-15 20:51:53 +01:00
|
|
|
"switch" "(" Expression() ")" SwitchBlock()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-12-14 18:02:49 +01:00
|
|
|
void SwitchBlock() #void:
|
2019-03-15 15:29:16 +01:00
|
|
|
{}
|
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2019-03-31 00:21:34 +01:00
|
|
|
(
|
2019-12-14 18:02:49 +01:00
|
|
|
LOOKAHEAD(SwitchLabel() ":") (SwitchFallthroughBranch())+
|
|
|
|
| (SwitchArrowBranch())*
|
|
|
|
)
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2019-03-15 15:29:16 +01:00
|
|
|
}
|
|
|
|
|
2019-12-14 18:02:49 +01:00
|
|
|
void SwitchArrowBranch():
|
2019-09-25 06:30:17 +02:00
|
|
|
{}
|
2019-03-31 10:33:02 +02:00
|
|
|
{
|
2019-12-14 18:02:49 +01:00
|
|
|
SwitchLabel() "->" (Expression() ";" | Block() | ThrowStatement())
|
2019-03-31 00:21:34 +01:00
|
|
|
}
|
|
|
|
|
2019-12-14 18:02:49 +01:00
|
|
|
void SwitchFallthroughBranch():
|
2019-03-31 00:21:34 +01:00
|
|
|
{}
|
|
|
|
{
|
2019-12-14 18:02:49 +01:00
|
|
|
SwitchLabel() ":"
|
|
|
|
// the lookahead is to prevent choosing BlockStatement when the token is "default",
|
|
|
|
// which could happen as local class declarations accept the "default" modifier.
|
|
|
|
(LOOKAHEAD({shouldStartStatementInSwitch()}) BlockStatement() )*
|
2019-03-31 00:21:34 +01:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
void SwitchLabel() :
|
|
|
|
{}
|
|
|
|
{
|
2019-03-15 20:51:53 +01:00
|
|
|
{ inSwitchLabel = true; }
|
|
|
|
(
|
2021-07-22 12:03:58 +02:00
|
|
|
"case" CaseLabelElement(jjtThis) ( "," CaseLabelElement(jjtThis) )*
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
2019-03-15 15:29:16 +01:00
|
|
|
"default" {jjtThis.setDefault();}
|
2019-03-15 20:51:53 +01:00
|
|
|
)
|
|
|
|
{ inSwitchLabel = false; }
|
2019-03-15 15:29:16 +01:00
|
|
|
}
|
|
|
|
|
2021-07-01 20:29:07 +02:00
|
|
|
void CaseLabelElement(ASTSwitchLabel label) #void:
|
2021-07-01 11:51:30 +02:00
|
|
|
{}
|
|
|
|
{
|
2023-08-04 11:47:45 +02:00
|
|
|
"null" #NullLiteral [ "," "default" {label.setDefault();} ]
|
2021-07-01 11:51:30 +02:00
|
|
|
|
|
2023-08-05 15:13:49 +02:00
|
|
|
LOOKAHEAD(Pattern()) CasePattern() [ LOOKAHEAD({isKeyword("when")}) Guard() ]
|
2021-07-01 11:51:30 +02:00
|
|
|
|
|
2023-08-05 15:13:49 +02:00
|
|
|
CaseConstant()
|
|
|
|
}
|
|
|
|
|
|
|
|
void CaseConstant() #void:
|
|
|
|
{}
|
|
|
|
{
|
2021-07-22 19:31:45 +02:00
|
|
|
ConditionalExpression()
|
2021-07-01 11:51:30 +02:00
|
|
|
}
|
|
|
|
|
2023-08-05 15:13:49 +02:00
|
|
|
void CasePattern() #void:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
Pattern()
|
|
|
|
}
|
|
|
|
|
2023-08-04 11:47:45 +02:00
|
|
|
void Guard() :
|
2023-03-19 22:49:45 +01:00
|
|
|
{}
|
2022-07-07 14:07:49 +02:00
|
|
|
{
|
2023-03-19 22:49:45 +01:00
|
|
|
softKeyword("when")
|
2022-07-07 14:07:49 +02:00
|
|
|
Expression()
|
|
|
|
}
|
|
|
|
|
2019-08-13 18:33:53 +02:00
|
|
|
void YieldStatement() :
|
2019-09-25 06:30:17 +02:00
|
|
|
{ }
|
2019-08-13 18:33:53 +02:00
|
|
|
{
|
|
|
|
<IDENTIFIER> Expression() ";"
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
void IfStatement() :
|
|
|
|
/*
|
|
|
|
* The disambiguating algorithm of JavaCC automatically binds dangling
|
|
|
|
* else's to the innermost if statement. The LOOKAHEAD specification
|
|
|
|
* is to tell JavaCC that we know what we are doing.
|
|
|
|
*/
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
"if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" {jjtThis.setHasElse();} Statement() ]
|
|
|
|
}
|
|
|
|
|
|
|
|
void WhileStatement() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
"while" "(" Expression() ")" Statement()
|
|
|
|
}
|
|
|
|
|
|
|
|
void DoStatement() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
"do" Statement() "while" "(" Expression() ")" ";"
|
|
|
|
}
|
|
|
|
|
2019-12-14 03:32:17 +01:00
|
|
|
void ForStatement() #void:
|
2020-04-08 21:06:19 +02:00
|
|
|
{JavaccToken t;}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-12-14 03:32:17 +01:00
|
|
|
t="for" "("
|
2014-09-30 19:51:42 +02:00
|
|
|
(
|
2023-02-03 19:37:28 +01:00
|
|
|
LOOKAHEAD(EnhancedForDeclaration() ":")
|
2023-02-04 19:10:37 +01:00
|
|
|
(EnhancedForDeclaration() ":" Expression() ")" Statement() { jjtThis.setFirstToken(t); }) #ForeachStatement
|
2019-12-14 03:32:17 +01:00
|
|
|
| (
|
2014-09-30 19:51:42 +02:00
|
|
|
[ ForInit() ] ";"
|
|
|
|
[ Expression() ] ";"
|
|
|
|
[ ForUpdate() ]
|
|
|
|
")" Statement()
|
2020-05-02 20:54:41 +02:00
|
|
|
{ jjtThis.setFirstToken(t); }
|
2019-12-14 03:32:17 +01:00
|
|
|
) #ForStatement
|
|
|
|
)
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2023-02-03 19:37:28 +01:00
|
|
|
void EnhancedForDeclaration() #void:
|
2023-02-04 19:10:37 +01:00
|
|
|
{}
|
2023-02-03 19:37:28 +01:00
|
|
|
{
|
2024-02-15 10:03:37 +01:00
|
|
|
LocalVariableDeclaration()
|
2023-02-03 19:37:28 +01:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
void ForInit() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
LOOKAHEAD( LocalVariableDeclaration() )
|
|
|
|
LocalVariableDeclaration()
|
|
|
|
|
|
|
|
|
StatementExpressionList()
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatementExpressionList() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
StatementExpression() ( "," StatementExpression() )*
|
|
|
|
}
|
|
|
|
|
|
|
|
void ForUpdate() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
StatementExpressionList()
|
|
|
|
}
|
|
|
|
|
|
|
|
void BreakStatement() :
|
2020-02-07 23:43:26 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-03-02 21:05:21 +01:00
|
|
|
"break" [ <IDENTIFIER> { setLastTokenImage(jjtThis); } ] ";"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ContinueStatement() :
|
2020-02-07 23:43:26 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-03-02 21:05:21 +01:00
|
|
|
"continue" [ <IDENTIFIER> { setLastTokenImage(jjtThis); } ] ";"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ReturnStatement() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
"return" [ Expression() ] ";"
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThrowStatement() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
"throw" Expression() ";"
|
|
|
|
}
|
|
|
|
|
|
|
|
void SynchronizedStatement() :
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
"synchronized" "(" Expression() ")" Block()
|
|
|
|
}
|
|
|
|
|
|
|
|
void TryStatement() :
|
|
|
|
/*
|
|
|
|
* Semantic check required here to make sure that at least one
|
|
|
|
* resource/finally/catch is present.
|
|
|
|
*/
|
|
|
|
{}
|
|
|
|
{
|
2019-12-14 03:32:17 +01:00
|
|
|
"try" (ResourceList())?
|
|
|
|
Block()
|
|
|
|
( CatchClause() )*
|
|
|
|
[ FinallyClause() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-08-06 02:04:41 +02:00
|
|
|
void ResourceList():
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
|
|
|
"("
|
|
|
|
Resource() (LOOKAHEAD(2) ";" Resource())*
|
2019-08-06 02:04:41 +02:00
|
|
|
(";" {jjtThis.setTrailingSemi();})?
|
|
|
|
")"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Resource() :
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-03-21 20:47:23 +01:00
|
|
|
LOOKAHEAD(("final" | Annotation())* LocalVariableType() VariableDeclaratorId() "=" )
|
2019-07-16 14:05:11 +02:00
|
|
|
(
|
2019-07-01 15:55:14 +02:00
|
|
|
LocalVarModifierList()
|
2019-07-16 14:05:11 +02:00
|
|
|
LocalVariableType() VariableDeclarator()
|
|
|
|
) #LocalVariableDeclaration
|
2017-09-23 00:15:08 +02:00
|
|
|
|
|
2019-09-25 06:30:17 +02:00
|
|
|
PrimaryExpression()
|
2019-09-25 07:37:31 +02:00
|
|
|
{
|
|
|
|
Node top = jjtree.peekNode();
|
2024-04-05 10:19:58 +02:00
|
|
|
if (!(top instanceof ASTVariableAccess || top instanceof ASTFieldAccess || top instanceof ASTThisExpression))
|
|
|
|
throwParseException("Expected a variable or field access, but was a " + top.getXPathNodeName());
|
2019-09-25 07:37:31 +02:00
|
|
|
}
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-12-14 03:32:17 +01:00
|
|
|
void CatchClause() :
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
|
|
|
"catch"
|
2019-07-20 13:08:49 +02:00
|
|
|
"(" CatchParameter() ")"
|
2014-09-30 19:51:42 +02:00
|
|
|
Block()
|
|
|
|
}
|
|
|
|
|
2019-07-20 13:08:49 +02:00
|
|
|
|
2020-01-07 22:24:32 +01:00
|
|
|
void CatchParameter():
|
2019-07-01 15:55:14 +02:00
|
|
|
{boolean multi=false;}
|
2019-07-20 13:08:49 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
LocalVarModifierList()
|
2020-01-07 22:24:32 +01:00
|
|
|
( AnnotatedClassOrInterfaceType() ( "|" AnnotatedClassOrInterfaceType() {multi=true;} )* ) #UnionType(multi)
|
|
|
|
VariableDeclaratorId()
|
2019-07-20 13:08:49 +02:00
|
|
|
}
|
|
|
|
|
2019-12-14 03:32:17 +01:00
|
|
|
void FinallyClause() :
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
|
|
|
"finally" Block()
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssertStatement() :
|
2019-09-25 06:57:09 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
|
|
|
<IDENTIFIER> Expression() [ ":" Expression() ] ";"
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We use productions to match >>>, >> and > so that we can keep the
|
|
|
|
* type declaration syntax with generics clean
|
|
|
|
*/
|
|
|
|
|
2019-03-26 20:43:31 +01:00
|
|
|
void RUNSIGNEDSHIFT() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2022-03-07 22:00:14 +01:00
|
|
|
LOOKAHEAD({ JavaTokenDocumentBehavior.getRealKind(getToken(1)) == RUNSIGNEDSHIFT})
|
2014-09-30 19:51:42 +02:00
|
|
|
">" ">" ">"
|
|
|
|
}
|
|
|
|
|
2019-03-26 20:43:31 +01:00
|
|
|
void RSIGNEDSHIFT() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2022-03-07 22:00:14 +01:00
|
|
|
LOOKAHEAD({ JavaTokenDocumentBehavior.getRealKind(getToken(1)) == RSIGNEDSHIFT})
|
2014-09-30 19:51:42 +02:00
|
|
|
">" ">"
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Annotation syntax follows. */
|
|
|
|
|
2020-01-25 01:30:26 +01:00
|
|
|
void Annotation():
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2020-07-24 22:23:33 +02:00
|
|
|
"@" ClassName() [ AnnotationMemberList() ]
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-01-25 01:30:26 +01:00
|
|
|
void AnnotationMemberList():
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
2020-01-25 01:30:26 +01:00
|
|
|
"("
|
|
|
|
( LOOKAHEAD(<IDENTIFIER> "=")
|
|
|
|
MemberValuePair() ( "," MemberValuePair() )*
|
|
|
|
| [ ShorthandAnnotationValue() ]
|
|
|
|
)
|
|
|
|
")"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-01-25 01:30:26 +01:00
|
|
|
void ShorthandAnnotationValue() #MemberValuePair:
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-01-25 01:30:26 +01:00
|
|
|
jjtThis.setImage("value");
|
|
|
|
jjtThis.setShorthand();
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
{
|
2020-01-25 01:30:26 +01:00
|
|
|
MemberValue()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MemberValuePair():
|
2020-02-07 23:43:26 +01:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-02-07 23:43:26 +01:00
|
|
|
<IDENTIFIER> { setLastTokenImage(jjtThis); } "=" MemberValue()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-21 15:07:55 +01:00
|
|
|
void MemberValue() #void:
|
2014-09-30 19:51:42 +02:00
|
|
|
{}
|
|
|
|
{
|
|
|
|
Annotation()
|
2020-01-25 01:30:26 +01:00
|
|
|
| MemberValueArrayInitializer()
|
|
|
|
| ConditionalExpression() // Constant expression
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemberValueArrayInitializer():
|
|
|
|
{}
|
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2023-08-10 11:27:53 +02:00
|
|
|
(MemberValue() ( LOOKAHEAD(2) "," MemberValue() )*)? [ "," ]
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2018-02-16 23:48:16 +01:00
|
|
|
/*
|
|
|
|
* We use that ghost production to factorise the check for JDK >= 1.8.
|
|
|
|
*/
|
|
|
|
void TypeAnnotation() #void:
|
|
|
|
{}
|
|
|
|
{
|
2019-09-25 06:30:17 +02:00
|
|
|
Annotation()
|
2018-02-16 23:48:16 +01:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
|
|
/* Annotation Types. */
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void AnnotationTypeDeclaration():
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2024-02-08 17:50:37 +01:00
|
|
|
"@" "interface" <IDENTIFIER> { jjtThis.setSimpleName(getToken(0).getImage()); }
|
2018-05-28 20:02:10 +02:00
|
|
|
AnnotationTypeBody()
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnnotationTypeBody():
|
|
|
|
{}
|
|
|
|
{
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2023-08-10 11:27:53 +02:00
|
|
|
( AnnotationTypeMemberDeclaration() )*
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2020-02-14 04:02:12 +01:00
|
|
|
void AnnotationTypeMemberDeclaration() #void:
|
2019-07-01 15:55:14 +02:00
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2019-07-01 15:55:14 +02:00
|
|
|
ModifierList()
|
2014-09-30 19:51:42 +02:00
|
|
|
(
|
2019-07-01 15:55:14 +02:00
|
|
|
LOOKAHEAD(Type() <IDENTIFIER> "(") AnnotationMethodDeclaration()
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
ClassOrInterfaceDeclaration()
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
LOOKAHEAD(3) EnumDeclaration()
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
AnnotationTypeDeclaration()
|
2014-09-30 19:51:42 +02:00
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
FieldDeclaration()
|
2014-09-30 19:51:42 +02:00
|
|
|
)
|
|
|
|
|
|
2019-05-28 19:16:04 +02:00
|
|
|
";" #EmptyDeclaration
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
2019-07-01 15:55:14 +02:00
|
|
|
void AnnotationMethodDeclaration() #MethodDeclaration:
|
|
|
|
{}
|
2014-09-30 19:51:42 +02:00
|
|
|
{
|
2020-08-14 07:10:15 +02:00
|
|
|
Type()
|
2024-02-08 17:50:37 +01:00
|
|
|
<IDENTIFIER> { jjtThis.setName(getToken(0).getImage()); }
|
2020-04-08 21:06:19 +02:00
|
|
|
("(" ")") #FormalParameters
|
2020-01-16 03:21:09 +01:00
|
|
|
[ Dims() ]
|
2019-07-26 18:00:03 +02:00
|
|
|
[ DefaultValue() ] ";"
|
2014-09-30 19:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DefaultValue():
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
"default" MemberValue()
|
|
|
|
}
|
2017-09-22 21:35:24 +02:00
|
|
|
|
|
|
|
void ModuleDeclaration():
|
2022-04-01 18:56:16 +02:00
|
|
|
{}
|
2017-09-22 21:35:24 +02:00
|
|
|
{
|
2022-04-01 18:56:16 +02:00
|
|
|
AnnotationList()
|
|
|
|
[LOOKAHEAD({isKeyword("open")}) <IDENTIFIER> {jjtThis.setOpen(true);}]
|
|
|
|
LOOKAHEAD({isKeyword("module")}) <IDENTIFIER>
|
|
|
|
ModuleName()
|
2024-04-12 17:59:10 +02:00
|
|
|
"{"
|
2023-08-10 11:27:53 +02:00
|
|
|
(ModuleDirective())*
|
2024-04-12 17:59:10 +02:00
|
|
|
"}"
|
2017-09-22 21:35:24 +02:00
|
|
|
}
|
|
|
|
|
2022-04-01 18:56:16 +02:00
|
|
|
void ModuleDirective() #void:
|
|
|
|
{String packageName;}
|
2017-09-22 21:35:24 +02:00
|
|
|
{
|
2022-04-01 18:56:16 +02:00
|
|
|
( LOOKAHEAD({isKeyword("requires")}) <IDENTIFIER>
|
|
|
|
[
|
|
|
|
LOOKAHEAD({isKeyword("transitive")}) <IDENTIFIER> { jjtThis.setTransitive(); }
|
|
|
|
| "static" { jjtThis.setStatic(); }
|
|
|
|
]
|
|
|
|
ModuleName() ";" ) #ModuleRequiresDirective
|
|
|
|
| ( LOOKAHEAD({isKeyword("exports")}) <IDENTIFIER> packageName=VoidNameNoLookahead() {jjtThis.setPackageName(packageName);} [ LOOKAHEAD({isKeyword("to")}) <IDENTIFIER> ModuleName() ("," ModuleName())* ] ";" ) #ModuleExportsDirective
|
|
|
|
| ( LOOKAHEAD({isKeyword("opens")}) <IDENTIFIER> packageName=VoidNameNoLookahead() {jjtThis.setPackageName(packageName);} [ LOOKAHEAD({isKeyword("to")}) <IDENTIFIER> ModuleName() ("," ModuleName())* ] ";" ) #ModuleOpensDirective
|
2022-04-14 19:49:48 +02:00
|
|
|
| ( LOOKAHEAD({isKeyword("uses")}) <IDENTIFIER> ClassName() ";" ) #ModuleUsesDirective
|
2022-04-01 18:56:16 +02:00
|
|
|
| ( LOOKAHEAD({isKeyword("provides")}) <IDENTIFIER> ClassName() LOOKAHEAD({isKeyword("with")}) <IDENTIFIER> ClassName() ("," ClassName() )* ";" ) #ModuleProvidesDirective
|
2017-09-22 21:35:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ModuleName():
|
2020-04-08 21:06:19 +02:00
|
|
|
{ String name; }
|
2017-09-22 21:35:24 +02:00
|
|
|
{
|
2024-02-08 17:50:37 +01:00
|
|
|
name=VoidNameNoLookahead() { jjtThis.setName(name); }
|
2019-02-17 10:28:12 +01:00
|
|
|
}
|
|
|
|
|
2019-02-18 17:55:41 +01:00
|
|
|
void AmbiguousName():
|
2020-04-08 21:06:19 +02:00
|
|
|
{ String name; }
|
2019-02-18 17:55:41 +01:00
|
|
|
{
|
2020-04-08 21:06:19 +02:00
|
|
|
name=VoidName() { jjtThis.setImage(name); }
|
2019-02-18 17:55:41 +01:00
|
|
|
}
|
|
|
|
|
2019-02-17 10:28:12 +01:00
|
|
|
String VoidName() #void:
|
|
|
|
/*
|
|
|
|
* A lookahead of 2 is required below since "Name" can be followed
|
2019-06-26 18:28:58 +02:00
|
|
|
* by a ".*" when used in the context of an "ImportDeclaration",
|
2020-04-08 21:06:19 +02:00
|
|
|
* or with "this" or "super" in PrimaryPrefix (AmbiguousName).
|
2019-02-17 10:28:12 +01:00
|
|
|
*/
|
|
|
|
{
|
|
|
|
StringBuilder s = new StringBuilder();
|
2019-08-06 10:35:14 +02:00
|
|
|
JavaccToken t;
|
2019-02-17 10:28:12 +01:00
|
|
|
}
|
|
|
|
{
|
2020-01-25 01:30:26 +01:00
|
|
|
t=<IDENTIFIER> { s.append(t.getImage()); }
|
2020-04-08 21:06:19 +02:00
|
|
|
( LOOKAHEAD(2) "." t=<IDENTIFIER> { s.append('.').append(t.getImage()); }
|
2019-02-17 10:28:12 +01:00
|
|
|
)*
|
|
|
|
{return s.toString();}
|
|
|
|
}
|
2019-02-18 16:59:23 +01:00
|
|
|
|
2022-04-01 18:56:16 +02:00
|
|
|
|
|
|
|
String VoidNameNoLookahead() #void:
|
|
|
|
{
|
|
|
|
StringBuilder s = new StringBuilder();
|
|
|
|
JavaccToken t;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
t=<IDENTIFIER> { s.append(t.getImage()); }
|
|
|
|
( "." t=<IDENTIFIER> { s.append('.').append(t.getImage()); } )*
|
|
|
|
{return s.toString();}
|
|
|
|
}
|
|
|
|
|
2020-07-24 22:23:33 +02:00
|
|
|
// Produces a ClassOrInterfaceType, possibly with an ambiguous LHS
|
|
|
|
void ClassName() #void:
|
|
|
|
{}
|
|
|
|
{
|
|
|
|
AmbiguousName() { forceTypeContext(); }
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:59:23 +01:00
|
|
|
// This is used to get JJTree to generate a node.
|
2019-04-03 14:48:48 +02:00
|
|
|
// Variable references are always ambiguous
|
|
|
|
// when they're parsed, so they're not created
|
|
|
|
// normally by jjtree, but rather by the disambiguation
|
|
|
|
// hooks spread across the parser
|
2019-07-28 15:47:20 +02:00
|
|
|
//noinspection UnusedProduction
|
2020-03-02 21:05:21 +01:00
|
|
|
void VariableAccess(): {} { <IDENTIFIER> }
|
|
|
|
// those are created manually
|
|
|
|
void TypeExpression(): {} { <IDENTIFIER> }
|
|
|
|
void PatternExpression(): {} { <IDENTIFIER> }
|
2020-08-23 15:38:21 +02:00
|
|
|
void LocalClassStatement(): {} { TypeDeclaration() }
|
2023-03-19 22:49:45 +01:00
|
|
|
|
|
|
|
void softKeyword(String name) #void: {} {
|
|
|
|
<IDENTIFIER> {
|
|
|
|
if (!getToken(0).getImageCs().contentEquals(name))
|
|
|
|
throwParseException("Expecting keyword '" + name + "'");
|
|
|
|
}
|
|
|
|
}
|