1 /*
   2  * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.parser;
  27 
  28 import java.util.*;
  29 import java.util.function.Function;
  30 import java.util.function.Predicate;
  31 import java.util.stream.Collectors;
  32 
  33 import javax.lang.model.SourceVersion;
  34 
  35 import com.sun.source.tree.CaseTree;
  36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  37 import com.sun.source.tree.ModuleTree.ModuleKind;
  38 
  39 import com.sun.tools.javac.code.*;
  40 import com.sun.tools.javac.code.Flags.Flag;
  41 import com.sun.tools.javac.code.Source.Feature;
  42 import com.sun.tools.javac.file.PathFileObject;
  43 import com.sun.tools.javac.parser.Tokens.*;
  44 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
  45 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  46 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  47 import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
  48 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  49 import com.sun.tools.javac.tree.*;
  50 import com.sun.tools.javac.tree.JCTree.*;
  51 import com.sun.tools.javac.util.*;
  52 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  53 import com.sun.tools.javac.util.JCDiagnostic.Error;
  54 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  55 import com.sun.tools.javac.util.List;
  56 
  57 import static com.sun.tools.javac.code.Flags.asFlagSet;
  58 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  59 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  60 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  61 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  62 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  63 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  64 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  65 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  66 import static com.sun.tools.javac.parser.Tokens.TokenKind.SYNCHRONIZED;
  67 import com.sun.tools.javac.parser.VirtualParser.VirtualScanner;
  68 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  70 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  71 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
  72 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
  73 
  74 /**
  75  * The parser maps a token sequence into an abstract syntax tree.
  76  * The parser is a hand-written recursive-descent parser that
  77  * implements the grammar described in the Java Language Specification.
  78  * For efficiency reasons, an operator precedence scheme is used
  79  * for parsing binary operation expressions.
  80  *
  81  *  <p><b>This is NOT part of any supported API.
  82  *  If you write code that depends on this, you do so at your own risk.
  83  *  This code and its internal interfaces are subject to change or
  84  *  deletion without notice.</b>
  85  */
  86 public class JavacParser implements Parser {
  87 
  88     /** The number of precedence levels of infix operators.
  89      */
  90     private static final int infixPrecedenceLevels = 10;
  91 
  92     /** Is the parser instantiated to parse a module-info file ?
  93      */
  94     private final boolean parseModuleInfo;
  95 
  96     /** The scanner used for lexical analysis.
  97      */
  98     protected Lexer S;
  99 
 100     /** The factory to be used for abstract syntax tree construction.
 101      */
 102     protected TreeMaker F;
 103 
 104     /** The log to be used for error diagnostics.
 105      */
 106     private Log log;
 107 
 108     /** The Source language setting. */
 109     private Source source;
 110 
 111     /** The Preview language setting. */
 112     private Preview preview;
 113 
 114     /** The name table. */
 115     private Names names;
 116 
 117     /** End position mappings container */
 118     protected final AbstractEndPosTable endPosTable;
 119 
 120     /** A map associating "other nearby documentation comments"
 121      *  with the preferred documentation comment for a declaration. */
 122     protected Map<Comment, List<Comment>> danglingComments = new HashMap<>();
 123     /** Handler for deferred diagnostics. */
 124     protected final DeferredLintHandler deferredLintHandler;
 125 
 126     // Because of javac's limited lookahead, some contexts are ambiguous in
 127     // the presence of type annotations even though they are not ambiguous
 128     // in the absence of type annotations.  Consider this code:
 129     //   void m(String [] m) { }
 130     //   void m(String ... m) { }
 131     // After parsing "String", javac calls bracketsOpt which immediately
 132     // returns if the next character is not '['.  Similarly, javac can see
 133     // if the next token is ... and in that case parse an ellipsis.  But in
 134     // the presence of type annotations:
 135     //   void m(String @A [] m) { }
 136     //   void m(String @A ... m) { }
 137     // no finite lookahead is enough to determine whether to read array
 138     // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
 139     // bracketsOpt first reads all the leading annotations and only then
 140     // discovers that it needs to fail.  bracketsOpt needs a way to push
 141     // back the extra annotations that it read.  (But, bracketsOpt should
 142     // not *always* be allowed to push back extra annotations that it finds
 143     // -- in most contexts, any such extra annotation is an error.
 144     //
 145     // The following two variables permit type annotations that have
 146     // already been read to be stored for later use.  Alternate
 147     // implementations are possible but would cause much larger changes to
 148     // the parser.
 149 
 150     /** Type annotations that have already been read but have not yet been used. **/
 151     private List<JCAnnotation> typeAnnotationsPushedBack = List.nil();
 152 
 153     /**
 154      * If the parser notices extra annotations, then it either immediately
 155      * issues an error (if this variable is false) or places the extra
 156      * annotations in variable typeAnnotationsPushedBack (if this variable
 157      * is true).
 158      */
 159     private boolean permitTypeAnnotationsPushBack = false;
 160     private JCDiagnostic.Error unexpectedTopLevelDefinitionStartError;
 161 
 162     interface ErrorRecoveryAction {
 163         JCTree doRecover(JavacParser parser);
 164     }
 165 
 166     enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
 167         BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
 168         CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
 169     }
 170 
 171     /** Construct a parser from a given scanner, tree factory and log.
 172      */
 173     protected JavacParser(ParserFactory fac,
 174                           Lexer S,
 175                           boolean keepDocComments,
 176                           boolean keepLineMap,
 177                           boolean keepEndPositions) {
 178         this(fac, S, keepDocComments, keepLineMap, keepEndPositions, false);
 179 
 180     }
 181     /** Construct a parser from a given scanner, tree factory and log.
 182      */
 183     @SuppressWarnings("this-escape")
 184     protected JavacParser(ParserFactory fac,
 185                      Lexer S,
 186                      boolean keepDocComments,
 187                      boolean keepLineMap,
 188                      boolean keepEndPositions,
 189                      boolean parseModuleInfo) {
 190         this.S = S;
 191         nextToken(); // prime the pump
 192         this.F = fac.F;
 193         this.log = fac.log;
 194         this.names = fac.names;
 195         this.source = fac.source;
 196         this.preview = fac.preview;
 197         this.deferredLintHandler = fac.deferredLintHandler;
 198         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
 199         this.keepDocComments = keepDocComments;
 200         this.parseModuleInfo = parseModuleInfo;
 201         this.docComments = newDocCommentTable(keepDocComments, fac);
 202         this.keepLineMap = keepLineMap;
 203         this.errorTree = F.Erroneous();
 204         this.endPosTable = newEndPosTable(keepEndPositions);
 205         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 206         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 207         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 208         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 209                 Feature.VALUE_CLASSES.allowedInSource(source);
 210         updateUnexpectedTopLevelDefinitionStartError(false);
 211     }
 212 
 213     /** Construct a parser from an existing parser, with minimal overhead.
 214      */
 215     @SuppressWarnings("this-escape")
 216     protected JavacParser(JavacParser parser,
 217                           Lexer S) {
 218         this.S = S;
 219         this.token = parser.token;
 220         this.F = parser.F;
 221         this.log = parser.log;
 222         this.names = parser.names;
 223         this.source = parser.source;
 224         this.preview = parser.preview;
 225         this.deferredLintHandler = parser.deferredLintHandler;
 226         this.allowStringFolding = parser.allowStringFolding;
 227         this.keepDocComments = parser.keepDocComments;
 228         this.parseModuleInfo = false;
 229         this.docComments = parser.docComments;
 230         this.errorTree = F.Erroneous();
 231         this.endPosTable = newEndPosTable(false);
 232         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 233         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 234         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 235         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 236                 Feature.VALUE_CLASSES.allowedInSource(source);
 237         updateUnexpectedTopLevelDefinitionStartError(false);
 238     }
 239 
 240     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
 241         return  keepEndPositions
 242                 ? new SimpleEndPosTable()
 243                 : new MinimalEndPosTable();
 244     }
 245 
 246     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
 247         return keepDocComments ? new LazyDocCommentTable(fac) : null;
 248     }
 249 
 250     /** Switch: should we fold strings?
 251      */
 252     boolean allowStringFolding;
 253 
 254     /** Switch: should we keep docComments?
 255      */
 256     boolean keepDocComments;
 257 
 258     /** Switch: should we keep line table?
 259      */
 260     boolean keepLineMap;
 261 
 262     /** Switch: is "this" allowed as an identifier?
 263      * This is needed to parse receiver types.
 264      */
 265     boolean allowThisIdent;
 266 
 267     /** Switch: is yield statement allowed in this source level?
 268      */
 269     boolean allowYieldStatement;
 270 
 271     /** Switch: are records allowed in this source level?
 272      */
 273     boolean allowRecords;
 274 
 275     /** Switch: are value classes allowed in this source level?
 276      */
 277     boolean allowValueClasses;
 278 
 279     /** Switch: are sealed types allowed in this source level?
 280      */
 281     boolean allowSealedTypes;
 282 
 283     /** The type of the method receiver, as specified by a first "this" parameter.
 284      */
 285     JCVariableDecl receiverParam;
 286 
 287     /** When terms are parsed, the mode determines which is expected:
 288      *     mode = EXPR        : an expression
 289      *     mode = TYPE        : a type
 290      *     mode = NOPARAMS    : no parameters allowed for type
 291      *     mode = TYPEARG     : type argument
 292      *     mode |= NOLAMBDA   : lambdas are not allowed
 293      */
 294     protected static final int EXPR          = 1 << 0;
 295     protected static final int TYPE          = 1 << 1;
 296     protected static final int NOPARAMS      = 1 << 2;
 297     protected static final int TYPEARG       = 1 << 3;
 298     protected static final int DIAMOND       = 1 << 4;
 299     protected static final int NOLAMBDA      = 1 << 5;
 300 
 301     protected void setMode(int mode) {
 302         this.mode = mode;
 303     }
 304 
 305     protected void setLastMode(int mode) {
 306         lastmode = mode;
 307     }
 308 
 309     protected boolean isMode(int mode) {
 310         return (this.mode & mode) != 0;
 311     }
 312 
 313     protected boolean wasTypeMode() {
 314         return (lastmode & TYPE) != 0;
 315     }
 316 
 317     protected void selectExprMode() {
 318         setMode((mode & NOLAMBDA) | EXPR);
 319     }
 320 
 321     protected void selectTypeMode() {
 322         setMode((mode & NOLAMBDA) | TYPE);
 323     }
 324 
 325     /** The current mode.
 326      */
 327     protected int mode = 0;
 328 
 329     /** The mode of the term that was parsed last.
 330      */
 331     protected int lastmode = 0;
 332 
 333     /* ---------- token management -------------- */
 334 
 335     protected Token token;
 336 
 337     public Token token() {
 338         return token;
 339     }
 340 
 341     public void nextToken() {
 342         S.nextToken();
 343         token = S.token();
 344     }
 345 
 346     protected boolean peekToken(Predicate<TokenKind> tk) {
 347         return peekToken(0, tk);
 348     }
 349 
 350     protected boolean peekToken(int lookahead, Predicate<TokenKind> tk) {
 351         return tk.test(S.token(lookahead + 1).kind);
 352     }
 353 
 354     protected boolean peekToken(Predicate<TokenKind> tk1, Predicate<TokenKind> tk2) {
 355         return peekToken(0, tk1, tk2);
 356     }
 357 
 358     protected boolean peekToken(int lookahead, Predicate<TokenKind> tk1, Predicate<TokenKind> tk2) {
 359         return tk1.test(S.token(lookahead + 1).kind) &&
 360                 tk2.test(S.token(lookahead + 2).kind);
 361     }
 362 
 363     protected boolean peekToken(Predicate<TokenKind> tk1, Predicate<TokenKind> tk2, Predicate<TokenKind> tk3) {
 364         return peekToken(0, tk1, tk2, tk3);
 365     }
 366 
 367     protected boolean peekToken(int lookahead, Predicate<TokenKind> tk1, Predicate<TokenKind> tk2, Predicate<TokenKind> tk3) {
 368         return tk1.test(S.token(lookahead + 1).kind) &&
 369                 tk2.test(S.token(lookahead + 2).kind) &&
 370                 tk3.test(S.token(lookahead + 3).kind);
 371     }
 372 
 373     @SuppressWarnings("unchecked")
 374     protected boolean peekToken(Predicate<TokenKind>... kinds) {
 375         return peekToken(0, kinds);
 376     }
 377 
 378     @SuppressWarnings("unchecked")
 379     protected boolean peekToken(int lookahead, Predicate<TokenKind>... kinds) {
 380         for (Predicate<TokenKind> kind : kinds) {
 381             if (!kind.test(S.token(++lookahead).kind)) {
 382                 return false;
 383             }
 384         }
 385         return true;
 386     }
 387 
 388     /* ---------- error recovery -------------- */
 389 
 390     private JCErroneous errorTree;
 391 
 392     /** Skip forward until a suitable stop token is found.
 393      */
 394     protected void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
 395          while (true) {
 396              switch (token.kind) {
 397                 case SEMI:
 398                     nextToken();
 399                     return;
 400                 case PUBLIC:
 401                 case FINAL:
 402                 case ABSTRACT:
 403                 case MONKEYS_AT:
 404                 case EOF:
 405                 case CLASS:
 406                 case INTERFACE:
 407                 case ENUM:
 408                     return;
 409                 case IMPORT:
 410                     if (stopAtImport)
 411                         return;
 412                     break;
 413                 case LBRACE:
 414                 case RBRACE:
 415                 case PRIVATE:
 416                 case PROTECTED:
 417                 case STATIC:
 418                 case TRANSIENT:
 419                 case NATIVE:
 420                 case VOLATILE:
 421                 case SYNCHRONIZED:
 422                 case STRICTFP:
 423                 case LT:
 424                 case BYTE:
 425                 case SHORT:
 426                 case CHAR:
 427                 case INT:
 428                 case LONG:
 429                 case FLOAT:
 430                 case DOUBLE:
 431                 case BOOLEAN:
 432                 case VOID:
 433                     if (stopAtMemberDecl)
 434                         return;
 435                     break;
 436                 case UNDERSCORE:
 437                 case IDENTIFIER:
 438                    if (stopAtIdentifier)
 439                         return;
 440                     break;
 441                 case CASE:
 442                 case DEFAULT:
 443                 case IF:
 444                 case FOR:
 445                 case WHILE:
 446                 case DO:
 447                 case TRY:
 448                 case SWITCH:
 449                 case RETURN:
 450                 case THROW:
 451                 case BREAK:
 452                 case CONTINUE:
 453                 case ELSE:
 454                 case FINALLY:
 455                 case CATCH:
 456                 case THIS:
 457                 case SUPER:
 458                 case NEW:
 459                     if (stopAtStatement)
 460                         return;
 461                     break;
 462                 case ASSERT:
 463                     if (stopAtStatement)
 464                         return;
 465                     break;
 466             }
 467             nextToken();
 468         }
 469     }
 470 
 471     protected JCErroneous syntaxError(int pos, Error errorKey) {
 472         return syntaxError(pos, List.nil(), errorKey);
 473     }
 474 
 475     protected JCErroneous syntaxError(int pos, List<? extends JCTree> errs, Error errorKey) {
 476         return syntaxError(pos, errs, errorKey, false);
 477     }
 478 
 479     private JCErroneous syntaxError(int pos, List<? extends JCTree> errs, Error errorKey, boolean noEofError) {
 480         setErrorEndPos(pos);
 481         JCErroneous err = F.at(pos).Erroneous(errs);
 482         reportSyntaxError(err, errorKey, noEofError);
 483         if (errs != null) {
 484             JCTree last = errs.last();
 485             if (last != null)
 486                 storeEnd(last, pos);
 487         }
 488         return toP(err);
 489     }
 490 
 491     private static final int RECOVERY_THRESHOLD = 50;
 492     private int errorPos = Position.NOPOS;
 493     private int count = 0;
 494 
 495     /**
 496      * Report a syntax using the given the position parameter and arguments,
 497      * unless one was already reported at the same position.
 498      */
 499     protected void reportSyntaxError(int pos, Error errorKey) {
 500         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
 501         reportSyntaxError(diag, errorKey);
 502     }
 503 
 504     /**
 505      * Report a syntax error using the given DiagnosticPosition object and
 506      * arguments, unless one was already reported at the same position.
 507      */
 508     protected void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, Error errorKey) {
 509         reportSyntaxError(diagPos, errorKey, false);
 510     }
 511 
 512     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, Error errorKey, boolean noEofError) {
 513         int pos = diagPos.getPreferredPosition();
 514         if (pos > S.errPos() || pos == Position.NOPOS) {
 515             if (token.kind == EOF && !noEofError) {
 516                 log.error(DiagnosticFlag.SYNTAX, diagPos, Errors.PrematureEof);
 517             } else {
 518                 log.error(DiagnosticFlag.SYNTAX, diagPos, errorKey);
 519             }
 520         }
 521         S.errPos(pos);
 522         if (token.pos == errorPos && token.kind != EOF) {
 523             //check for a possible infinite loop in parsing:
 524             Assert.check(count++ < RECOVERY_THRESHOLD);
 525         } else {
 526             count = 0;
 527             errorPos = token.pos;
 528         }
 529     }
 530 
 531     /** If next input token matches given token, skip it, otherwise report
 532      *  an error.
 533      */
 534     public void accept(TokenKind tk) {
 535         accept(tk, Errors::Expected);
 536     }
 537 
 538     /** If next input token matches given token, skip it, otherwise report
 539      *  an error.
 540      */
 541     public void accept(TokenKind tk, Function<TokenKind, Error> errorProvider) {
 542         if (token.kind == tk) {
 543             nextToken();
 544         } else {
 545             setErrorEndPos(token.pos);
 546             reportSyntaxError(S.prevToken().endPos, errorProvider.apply(tk));
 547         }
 548     }
 549 
 550     /** Report an illegal start of expression/type error at given position.
 551      */
 552     JCExpression illegal(int pos) {
 553         setErrorEndPos(pos);
 554         if (isMode(EXPR))
 555             return syntaxError(pos, Errors.IllegalStartOfExpr);
 556         else
 557             return syntaxError(pos, Errors.IllegalStartOfType);
 558 
 559     }
 560 
 561     /** Report an illegal start of expression/type error at current position.
 562      */
 563     JCExpression illegal() {
 564         return illegal(token.pos);
 565     }
 566 
 567     /** Diagnose a modifier flag from the set, if any. */
 568     protected void checkNoMods(long mods) {
 569         checkNoMods(token.pos, mods);
 570     }
 571 
 572     protected void checkNoMods(int pos, long mods) {
 573         if (mods != 0) {
 574             long lowestMod = mods & -mods;
 575             log.error(DiagnosticFlag.SYNTAX, pos, Errors.ModNotAllowedHere(Flags.asFlagSet(lowestMod)));
 576         }
 577     }
 578 
 579 /* ---------- doc comments --------- */
 580 
 581     /** A table to store all documentation comments
 582      *  indexed by the tree nodes they refer to.
 583      *  defined only if option flag keepDocComment is set.
 584      */
 585     private final DocCommentTable docComments;
 586 
 587     /** Record nearby documentation comments against the
 588      *  primary documentation comment for a declaration.
 589      *
 590      *  Dangling documentation comments are handled as follows.
 591      *  1. {@code Scanner} adds all doc comments to a queue of
 592      *     recent doc comments. The queue is flushed whenever
 593      *     it is known that the recent doc comments should be
 594      *     ignored and should not cause any warnings.
 595      *  2. The primary documentation comment is the one obtained
 596      *     from the first token of any declaration.
 597      *     (using {@code token.getDocComment()}.
 598      *  3. At the end of the "signature" of the declaration
 599      *     (that is, before any initialization or body for the
 600      *     declaration) any other "recent" comments are saved
 601      *     in a map using the primary comment as a key,
 602      *     using this method, {@code saveDanglingComments}.
 603      *  4. When the tree node for the declaration is finally
 604      *     available, and the primary comment, if any,
 605      *     is "attached", (in {@link #attach}) any related
 606      *     dangling comments are also attached to the tree node
 607      *     by registering them using the {@link #deferredLintHandler}.
 608      *  5. (Later) Warnings may be generated for the dangling
 609      *     comments, subject to the {@code -Xlint} and
 610      *     {@code @SuppressWarnings}.
 611      *
 612      *  @param dc the primary documentation comment
 613      */
 614     private void saveDanglingDocComments(Comment dc) {
 615         var recentComments = S.getDocComments();
 616 
 617         switch (recentComments.size()) {
 618             case 0:
 619                 // no recent comments
 620                 return;
 621 
 622             case 1:
 623                 if (recentComments.peek() == dc) {
 624                     // no other recent comments
 625                     recentComments.remove();
 626                     return;
 627                 }
 628         }
 629 
 630         var lb = new ListBuffer<Comment>();
 631         while (!recentComments.isEmpty()) {
 632             var c = recentComments.remove();
 633             if (c != dc) {
 634                 lb.add(c);
 635             }
 636         }
 637         danglingComments.put(dc, lb.toList());
 638     }
 639 
 640     /** Make an entry into docComments hashtable,
 641      *  provided flag keepDocComments is set and given doc comment is non-null.
 642      *  If there are any related "dangling comments", register
 643      *  diagnostics to be handled later, when @SuppressWarnings
 644      *  can be taken into account.
 645      *
 646      *  @param tree   The tree to be used as index in the hashtable
 647      *  @param dc     The doc comment to associate with the tree, or null.
 648      *  @return {@code tree}
 649      */
 650     protected <T extends JCTree> T attach(T tree, Comment dc) {
 651         if (keepDocComments && dc != null) {
 652             docComments.putComment(tree, dc);
 653         }
 654         reportDanglingComments(tree, dc);
 655         return tree;
 656     }
 657 
 658     /** Reports all dangling comments associated with the
 659      *  primary comment for a declaration against the position
 660      *  of the tree node for a declaration.
 661      *
 662      * @param tree the tree node for the declaration
 663      * @param dc the primary comment for the declaration
 664      */
 665     void reportDanglingComments(JCTree tree, Comment dc) {
 666         var list = danglingComments.remove(dc);
 667         if (list != null) {
 668             deferredLintHandler.push(tree);
 669             try {
 670                 list.forEach(this::reportDanglingDocComment);
 671             } finally {
 672                 deferredLintHandler.pop();
 673             }
 674         }
 675     }
 676 
 677     /**
 678      * Reports an individual dangling comment using the {@link #deferredLintHandler}.
 679      * The comment may or not may generate an actual diagnostic, depending on
 680      * the settings for {@code -Xlint} and/or {@code @SuppressWarnings}.
 681      *
 682      * @param c the comment
 683      */
 684     void reportDanglingDocComment(Comment c) {
 685         var pos = c.getPos();
 686         if (pos != null) {
 687             deferredLintHandler.report(lint -> {
 688                 if (lint.isEnabled(Lint.LintCategory.DANGLING_DOC_COMMENTS) &&
 689                         !shebang(c, pos)) {
 690                     log.warning(
 691                             pos, LintWarnings.DanglingDocComment);
 692                 }
 693             });
 694         }
 695     }
 696 
 697     /** Returns true for a comment that acts similarly to shebang in UNIX */
 698     private boolean shebang(Comment c, JCDiagnostic.DiagnosticPosition pos) {
 699         var src = log.currentSource();
 700         return c.getStyle() == Comment.CommentStyle.JAVADOC_LINE &&
 701                 c.getPos().getStartPosition() == 0 &&
 702                 src.getLineNumber(pos.getEndPosition(src.getEndPosTable())) == 1;
 703     }
 704 
 705     /**
 706      * Ignores any recent documentation comments found by the scanner,
 707      * such as those that cannot be associated with a nearby declaration.
 708      */
 709     private void ignoreDanglingComments() {
 710         S.getDocComments().clear();
 711     }
 712 
 713 /* -------- source positions ------- */
 714 
 715     protected void setErrorEndPos(int errPos) {
 716         endPosTable.setErrorEndPos(errPos);
 717     }
 718 
 719     /**
 720      * Store ending position for a tree, the value of which is the greater of
 721      * last error position in {@link #endPosTable} and the given ending position.
 722      * @param tree tree node
 723      * @param endpos the ending position to associate with {@code tree}
 724      * @return {@code tree}
 725      */
 726     protected <T extends JCTree> T storeEnd(T tree, int endpos) {
 727         return endPosTable.storeEnd(tree, endpos);
 728     }
 729 
 730     /**
 731      * Store current token's ending position for a tree, the value of which
 732      * will be the greater of last error position in {@link #endPosTable}
 733      * and the ending position of the current token.
 734      * @param tree tree node
 735      */
 736     protected <T extends JCTree> T to(T tree) {
 737         return storeEnd(tree, token.endPos);
 738     }
 739 
 740     /**
 741      * Store current token's ending position for a tree, the value of which
 742      * will be the greater of last error position in {@link #endPosTable}
 743      * and the ending position of the previous token.
 744      * @param tree tree node
 745      */
 746     protected <T extends JCTree> T toP(T tree) {
 747         return storeEnd(tree, S.prevToken().endPos);
 748     }
 749 
 750     /** Get the start position for a tree node.  The start position is
 751      * defined to be the position of the first character of the first
 752      * token of the node's source text.
 753      * @param tree  The tree node
 754      */
 755     public int getStartPos(JCTree tree) {
 756         return TreeInfo.getStartPos(tree);
 757     }
 758 
 759     /**
 760      * Get the end position for a tree node.  The end position is
 761      * defined to be the position of the last character of the last
 762      * token of the node's source text.  Returns Position.NOPOS if end
 763      * positions are not generated or the position is otherwise not
 764      * found.
 765      * @param tree  The tree node
 766      */
 767     public int getEndPos(JCTree tree) {
 768         return endPosTable.getEndPos(tree);
 769     }
 770 
 771 
 772 
 773 /* ---------- parsing -------------- */
 774 
 775     /**
 776      * Ident = IDENTIFIER
 777      */
 778     public Name ident() {
 779         return ident(false);
 780     }
 781 
 782     protected Name ident(boolean allowClass) {
 783         return ident(allowClass, false);
 784     }
 785 
 786     public Name identOrUnderscore() {
 787         return ident(false, true);
 788     }
 789 
 790     protected Name ident(boolean allowClass, boolean asVariable) {
 791         if (token.kind == IDENTIFIER) {
 792             Name name = token.name();
 793             nextToken();
 794             return name;
 795         } else if (token.kind == ASSERT) {
 796             log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.AssertAsIdentifier);
 797             nextToken();
 798             return names.error;
 799         } else if (token.kind == ENUM) {
 800             log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.EnumAsIdentifier);
 801             nextToken();
 802             return names.error;
 803         } else if (token.kind == THIS) {
 804             if (allowThisIdent) {
 805                 Name name = token.name();
 806                 nextToken();
 807                 return name;
 808             } else {
 809                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ThisAsIdentifier);
 810                 nextToken();
 811                 return names.error;
 812             }
 813         } else if (token.kind == UNDERSCORE) {
 814             if (Feature.UNDERSCORE_IDENTIFIER.allowedInSource(source)) {
 815                 log.warning(token.pos, Warnings.UnderscoreAsIdentifier);
 816             } else if (asVariable) {
 817                 checkSourceLevel(Feature.UNNAMED_VARIABLES);
 818                 if (peekToken(LBRACKET)) {
 819                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UseOfUnderscoreNotAllowedWithBrackets);
 820                 }
 821             } else {
 822                 if (Feature.UNNAMED_VARIABLES.allowedInSource(source)) {
 823                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UseOfUnderscoreNotAllowedNonVariable);
 824                 } else {
 825                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UnderscoreAsIdentifier);
 826                 }
 827             }
 828             Name name = token.name();
 829             nextToken();
 830             return name;
 831         } else {
 832             accept(IDENTIFIER);
 833             if (allowClass && token.kind == CLASS) {
 834                 nextToken();
 835                 return names._class;
 836             }
 837             return names.error;
 838         }
 839     }
 840 
 841     /**
 842      * Qualident = Ident { DOT [Annotations] Ident }
 843      */
 844     public JCExpression qualident(boolean allowAnnos) {
 845         JCExpression t = toP(F.at(token.pos).Ident(ident()));
 846         while (token.kind == DOT) {
 847             int pos = token.pos;
 848             nextToken();
 849             List<JCAnnotation> tyannos = null;
 850             if (allowAnnos) {
 851                 tyannos = typeAnnotationsOpt();
 852             }
 853             t = toP(F.at(pos).Select(t, ident()));
 854             if (tyannos != null && tyannos.nonEmpty()) {
 855                 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
 856             }
 857         }
 858         return t;
 859     }
 860 
 861     JCExpression literal(Name prefix) {
 862         return literal(prefix, token.pos);
 863     }
 864 
 865     /**
 866      * Literal =
 867      *     INTLITERAL
 868      *   | LONGLITERAL
 869      *   | FLOATLITERAL
 870      *   | DOUBLELITERAL
 871      *   | CHARLITERAL
 872      *   | STRINGLITERAL
 873      *   | TRUE
 874      *   | FALSE
 875      *   | NULL
 876      */
 877     JCExpression literal(Name prefix, int pos) {
 878         JCExpression t = errorTree;
 879         switch (token.kind) {
 880         case INTLITERAL:
 881             try {
 882                 t = F.at(pos).Literal(
 883                     TypeTag.INT,
 884                     Convert.string2int(strval(prefix), token.radix()));
 885             } catch (NumberFormatException ex) {
 886                 reportIntegralLiteralError(prefix, pos);
 887             }
 888             break;
 889         case LONGLITERAL:
 890             try {
 891                 t = F.at(pos).Literal(
 892                     TypeTag.LONG,
 893                     Long.valueOf(Convert.string2long(strval(prefix), token.radix())));
 894             } catch (NumberFormatException ex) {
 895                 reportIntegralLiteralError(prefix, pos);
 896             }
 897             break;
 898         case FLOATLITERAL: {
 899             String proper = token.radix() == 16 ?
 900                     ("0x"+ token.stringVal()) :
 901                     token.stringVal();
 902             Float n;
 903             try {
 904                 n = Float.valueOf(proper);
 905             } catch (NumberFormatException ex) {
 906                 // error already reported in scanner
 907                 n = Float.NaN;
 908             }
 909             if (n.floatValue() == 0.0f && !isZero(proper))
 910                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooSmall);
 911             else if (n.floatValue() == Float.POSITIVE_INFINITY)
 912                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooLarge);
 913             else
 914                 t = F.at(pos).Literal(TypeTag.FLOAT, n);
 915             break;
 916         }
 917         case DOUBLELITERAL: {
 918             String proper = token.radix() == 16 ?
 919                     ("0x"+ token.stringVal()) :
 920                     token.stringVal();
 921             Double n;
 922             try {
 923                 n = Double.valueOf(proper);
 924             } catch (NumberFormatException ex) {
 925                 // error already reported in scanner
 926                 n = Double.NaN;
 927             }
 928             if (n.doubleValue() == 0.0d && !isZero(proper))
 929                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooSmall);
 930             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
 931                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooLarge);
 932             else
 933                 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
 934             break;
 935         }
 936         case CHARLITERAL:
 937             t = F.at(pos).Literal(
 938                 TypeTag.CHAR,
 939                 token.stringVal().charAt(0) + 0);
 940             break;
 941         case STRINGLITERAL:
 942             t = F.at(pos).Literal(
 943                 TypeTag.CLASS,
 944                 token.stringVal());
 945             break;
 946         case TRUE: case FALSE:
 947             t = F.at(pos).Literal(
 948                 TypeTag.BOOLEAN,
 949                 (token.kind == TRUE ? 1 : 0));
 950             break;
 951         case NULL:
 952             t = F.at(pos).Literal(
 953                 TypeTag.BOT,
 954                 null);
 955             break;
 956         default:
 957             Assert.error();
 958         }
 959         if (t == errorTree)
 960             t = F.at(pos).Erroneous();
 961         storeEnd(t, token.endPos);
 962         nextToken();
 963         return t;
 964     }
 965     //where
 966         boolean isZero(String s) {
 967             char[] cs = s.toCharArray();
 968             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
 969             int i = ((base==16) ? 2 : 0);
 970             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
 971             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
 972         }
 973 
 974         String strval(Name prefix) {
 975             String s = token.stringVal();
 976             return prefix.isEmpty() ? s : prefix + s;
 977         }
 978         void reportIntegralLiteralError(Name prefix, int pos) {
 979             int radix = token.radix();
 980             if (radix == 2 || radix == 8) {
 981                 //attempt to produce more user-friendly error message for
 982                 //binary and octal literals with wrong digits:
 983                 String value = strval(prefix);
 984                 char[] cs = value.toCharArray();
 985                 for (int i = 0; i < cs.length; i++) {
 986                     char c = cs[i];
 987                     int d = Character.digit(c, radix);
 988                     if (d == (-1)) {
 989                         Error err = radix == 2 ? Errors.IllegalDigitInBinaryLiteral
 990                                                : Errors.IllegalDigitInOctalLiteral;
 991                         log.error(DiagnosticFlag.SYNTAX,
 992                                   token.pos + i,
 993                                   err);
 994                         return ;
 995                     }
 996                 }
 997             }
 998             log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.IntNumberTooLarge(strval(prefix)));
 999         }
1000 
1001     /** terms can be either expressions or types.
1002      */
1003     public JCExpression parseExpression() {
1004         return term(EXPR);
1005     }
1006 
1007     /** parses patterns.
1008      */
1009     public JCPattern parsePattern(int pos, JCModifiers mods, JCExpression parsedType,
1010                                   boolean allowVar, boolean checkGuard) {
1011         JCPattern pattern;
1012         mods = mods != null ? mods : optFinal(0);
1013         JCExpression e;
1014         if (token.kind == UNDERSCORE && parsedType == null) {
1015             nextToken();
1016             checkSourceLevel(Feature.UNNAMED_VARIABLES);
1017             pattern = toP(F.at(token.pos).AnyPattern());
1018         }
1019         else {
1020             if (parsedType == null) {
1021                 boolean var = token.kind == IDENTIFIER && token.name() == names.var;
1022                 e = unannotatedType(allowVar, TYPE | NOLAMBDA);
1023                 if (var) {
1024                     e = null;
1025                 }
1026             } else {
1027                 e = parsedType;
1028             }
1029             if (token.kind == LPAREN) {
1030                 //deconstruction pattern:
1031                 checkSourceLevel(Feature.RECORD_PATTERNS);
1032                 ListBuffer<JCPattern> nested = new ListBuffer<>();
1033                 if (!peekToken(RPAREN)) {
1034                     do {
1035                         nextToken();
1036                         JCPattern nestedPattern = parsePattern(token.pos, null, null, true, false);
1037                         nested.append(nestedPattern);
1038                     } while (token.kind == COMMA);
1039                 } else {
1040                     nextToken();
1041                 }
1042                 accept(RPAREN);
1043                 pattern = toP(F.at(pos).RecordPattern(e, nested.toList()));
1044                 if (mods.annotations.nonEmpty()) {
1045                     log.error(mods.annotations.head.pos(), Errors.RecordPatternsAnnotationsNotAllowed);
1046                 }
1047                 checkNoMods(pos, mods.flags & Flags.FINAL);
1048                 new TreeScanner() {
1049                     @Override
1050                     public void visitAnnotatedType(JCAnnotatedType tree) {
1051                         log.error(tree.pos(), Errors.RecordPatternsAnnotationsNotAllowed);
1052                     }
1053                 }.scan(e);
1054             } else {
1055                 //type test pattern:
1056                 int varPos = token.pos;
1057                 Name name = identOrUnderscore();
1058                 if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
1059                     name = names.empty;
1060                 }
1061                 JCVariableDecl var = toP(F.at(varPos).VarDef(mods, name, e, null));
1062                 if (e == null) {
1063                     var.startPos = pos;
1064                     if (var.name == names.underscore && !allowVar) {
1065                         log.error(DiagnosticFlag.SYNTAX, varPos, Errors.UseOfUnderscoreNotAllowed);
1066                     }
1067                 }
1068                 pattern = toP(F.at(pos).BindingPattern(var));
1069             }
1070         }
1071         return pattern;
1072     }
1073 
1074     /**
1075      * parses (optional) type annotations followed by a type. If the
1076      * annotations are present before the type and are not consumed during array
1077      * parsing, this method returns a {@link JCAnnotatedType} consisting of
1078      * these annotations and the underlying type. Otherwise, it returns the
1079      * underlying type.
1080      *
1081      * <p>
1082      *
1083      * Note that this method sets {@code mode} to {@code TYPE} first, before
1084      * parsing annotations.
1085      */
1086     public JCExpression parseType() {
1087         return parseType(false);
1088     }
1089 
1090     public JCExpression parseType(boolean allowVar) {
1091         List<JCAnnotation> annotations = typeAnnotationsOpt();
1092         return parseType(allowVar, annotations);
1093     }
1094 
1095     public JCExpression parseType(boolean allowVar, List<JCAnnotation> annotations) {
1096         JCExpression result = unannotatedType(allowVar);
1097 
1098         if (annotations.nonEmpty()) {
1099             result = insertAnnotationsToMostInner(result, annotations, false);
1100         }
1101 
1102         return result;
1103     }
1104 
1105     protected JCExpression parseIntersectionType(int pos, JCExpression firstType) {
1106         JCExpression t = firstType;
1107         int pos1 = pos;
1108         List<JCExpression> targets = List.of(t);
1109         while (token.kind == AMP) {
1110             accept(AMP);
1111             targets = targets.prepend(parseType());
1112         }
1113         if (targets.length() > 1) {
1114             t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
1115         }
1116         return t;
1117     }
1118 
1119     public JCExpression unannotatedType(boolean allowVar) {
1120         return unannotatedType(allowVar, TYPE);
1121     }
1122 
1123     public JCExpression unannotatedType(boolean allowVar, int newmode) {
1124         JCExpression result = term(newmode);
1125         Name restrictedTypeName = restrictedTypeName(result, !allowVar);
1126 
1127         if (restrictedTypeName != null && (!allowVar || restrictedTypeName != names.var)) {
1128             syntaxError(result.pos, Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
1129         }
1130 
1131         return result;
1132     }
1133 
1134 
1135 
1136     protected JCExpression term(int newmode) {
1137         int prevmode = mode;
1138         setMode(newmode);
1139         JCExpression t = term();
1140         setLastMode(mode);
1141         setMode(prevmode);
1142         return t;
1143     }
1144 
1145     /**
1146      *  {@literal
1147      *  Expression = Expression1 [ExpressionRest]
1148      *  ExpressionRest = [AssignmentOperator Expression1]
1149      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
1150      *                       "&=" | "|=" | "^=" |
1151      *                       "%=" | "<<=" | ">>=" | ">>>="
1152      *  Type = Type1
1153      *  TypeNoParams = TypeNoParams1
1154      *  StatementExpression = Expression
1155      *  ConstantExpression = Expression
1156      *  }
1157      */
1158     JCExpression term() {
1159         JCExpression t = term1();
1160         if (isMode(EXPR) &&
1161             (token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0))
1162             return termRest(t);
1163         else
1164             return t;
1165     }
1166 
1167     JCExpression termRest(JCExpression t) {
1168         switch (token.kind) {
1169         case EQ: {
1170             int pos = token.pos;
1171             nextToken();
1172             selectExprMode();
1173             JCExpression t1 = term();
1174             return toP(F.at(pos).Assign(t, t1));
1175         }
1176         case PLUSEQ:
1177         case SUBEQ:
1178         case STAREQ:
1179         case SLASHEQ:
1180         case PERCENTEQ:
1181         case AMPEQ:
1182         case BAREQ:
1183         case CARETEQ:
1184         case LTLTEQ:
1185         case GTGTEQ:
1186         case GTGTGTEQ:
1187             int pos = token.pos;
1188             TokenKind tk = token.kind;
1189             nextToken();
1190             selectExprMode();
1191             JCExpression t1 = term();
1192             return F.at(pos).Assignop(optag(tk), t, t1);
1193         default:
1194             return t;
1195         }
1196     }
1197 
1198     /** Expression1   = Expression2 [Expression1Rest]
1199      *  Type1         = Type2
1200      *  TypeNoParams1 = TypeNoParams2
1201      */
1202     JCExpression term1() {
1203         JCExpression t = term2();
1204         if (isMode(EXPR) && token.kind == QUES) {
1205             selectExprMode();
1206             return term1Rest(t);
1207         } else {
1208             return t;
1209         }
1210     }
1211 
1212     /** Expression1Rest = ["?" Expression ":" Expression1]
1213      */
1214     JCExpression term1Rest(JCExpression t) {
1215         if (token.kind == QUES) {
1216             int pos = token.pos;
1217             nextToken();
1218             JCExpression t1 = term();
1219             accept(COLON);
1220             JCExpression t2 = term1();
1221             return F.at(pos).Conditional(t, t1, t2);
1222         } else {
1223             return t;
1224         }
1225     }
1226 
1227     /** Expression2   = Expression3 [Expression2Rest]
1228      *  Type2         = Type3
1229      *  TypeNoParams2 = TypeNoParams3
1230      */
1231     JCExpression term2() {
1232         JCExpression t = term3();
1233         if (isMode(EXPR) && prec(token.kind) >= TreeInfo.orPrec) {
1234             selectExprMode();
1235             return term2Rest(t, TreeInfo.orPrec);
1236         } else {
1237             return t;
1238         }
1239     }
1240 
1241     /*  Expression2Rest = {infixop Expression3}
1242      *                  | Expression3 instanceof Type
1243      *                  | Expression3 instanceof Pattern
1244      *  infixop         = "||"
1245      *                  | "&&"
1246      *                  | "|"
1247      *                  | "^"
1248      *                  | "&"
1249      *                  | "==" | "!="
1250      *                  | "<" | ">" | "<=" | ">="
1251      *                  | "<<" | ">>" | ">>>"
1252      *                  | "+" | "-"
1253      *                  | "*" | "/" | "%"
1254      */
1255     JCExpression term2Rest(JCExpression t, int minprec) {
1256         JCExpression[] odStack = newOdStack();
1257         Token[] opStack = newOpStack();
1258 
1259         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
1260         int top = 0;
1261         odStack[0] = t;
1262         int startPos = token.pos;
1263         Token topOp = Tokens.DUMMY;
1264         while (prec(token.kind) >= minprec) {
1265             opStack[top] = topOp;
1266 
1267             if (token.kind == INSTANCEOF) {
1268                 int pos = token.pos;
1269                 nextToken();
1270                 JCTree pattern;
1271                 if (token.kind == LPAREN) {
1272                     checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
1273                     pattern = parsePattern(token.pos, null, null, false, false);
1274                 } else {
1275                     int patternPos = token.pos;
1276                     JCModifiers mods = optFinal(0);
1277                     int typePos = token.pos;
1278                     JCExpression type = unannotatedType(false);
1279                     if (token.kind == IDENTIFIER) {
1280                         checkSourceLevel(token.pos, Feature.PATTERN_MATCHING_IN_INSTANCEOF);
1281                         pattern = parsePattern(patternPos, mods, type, false, false);
1282                     } else if (token.kind == LPAREN) {
1283                         pattern = parsePattern(patternPos, mods, type, false, false);
1284                     } else if (token.kind == UNDERSCORE) {
1285                         checkSourceLevel(token.pos, Feature.UNNAMED_VARIABLES);
1286                         pattern = parsePattern(patternPos, mods, type, false, false);
1287                     } else {
1288                         checkNoMods(typePos, mods.flags & ~Flags.DEPRECATED);
1289                         if (mods.annotations.nonEmpty()) {
1290                             List<JCAnnotation> typeAnnos =
1291                                     mods.annotations
1292                                         .map(decl -> {
1293                                             JCAnnotation typeAnno = F.at(decl.pos)
1294                                                                      .TypeAnnotation(decl.annotationType,
1295                                                                                       decl.args);
1296                                             endPosTable.replaceTree(decl, typeAnno);
1297                                             return typeAnno;
1298                                         });
1299                             type = insertAnnotationsToMostInner(type, typeAnnos, false);
1300                         }
1301                         pattern = type;
1302                     }
1303                 }
1304                 odStack[top] = F.at(pos).TypeTest(odStack[top], pattern);
1305             } else {
1306                 topOp = token;
1307                 nextToken();
1308                 top++;
1309                 odStack[top] = term3();
1310             }
1311             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
1312                 odStack[top - 1] = F.at(topOp.pos).Binary(optag(topOp.kind), odStack[top - 1], odStack[top]);
1313                 top--;
1314                 topOp = opStack[top];
1315             }
1316         }
1317         Assert.check(top == 0);
1318         t = odStack[0];
1319 
1320         if (t.hasTag(JCTree.Tag.PLUS)) {
1321             t = foldStrings(t);
1322         }
1323 
1324         odStackSupply.add(odStack);
1325         opStackSupply.add(opStack);
1326         return t;
1327     }
1328     //where
1329         /** If tree is a concatenation of string literals, replace it
1330          *  by a single literal representing the concatenated string.
1331          */
1332         protected JCExpression foldStrings(JCExpression tree) {
1333             if (!allowStringFolding)
1334                 return tree;
1335             ListBuffer<JCExpression> opStack = new ListBuffer<>();
1336             ListBuffer<JCLiteral> litBuf = new ListBuffer<>();
1337             boolean needsFolding = false;
1338             JCExpression curr = tree;
1339             while (true) {
1340                 if (curr.hasTag(JCTree.Tag.PLUS)) {
1341                     JCBinary op = (JCBinary)curr;
1342                     needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false);
1343                     curr = op.lhs;
1344                 } else {
1345                     needsFolding |= foldIfNeeded(curr, litBuf, opStack, true);
1346                     break; //last one!
1347                 }
1348             }
1349             if (needsFolding) {
1350                 List<JCExpression> ops = opStack.toList();
1351                 JCExpression res = ops.head;
1352                 for (JCExpression op : ops.tail) {
1353                     res = F.at(op.getStartPosition()).Binary(optag(TokenKind.PLUS), res, op);
1354                     storeEnd(res, getEndPos(op));
1355                 }
1356                 return res;
1357             } else {
1358                 return tree;
1359             }
1360         }
1361 
1362         private boolean foldIfNeeded(JCExpression tree, ListBuffer<JCLiteral> litBuf,
1363                                                 ListBuffer<JCExpression> opStack, boolean last) {
1364             JCLiteral str = stringLiteral(tree);
1365             if (str != null) {
1366                 litBuf.prepend(str);
1367                 return last && merge(litBuf, opStack);
1368             } else {
1369                 boolean res = merge(litBuf, opStack);
1370                 litBuf.clear();
1371                 opStack.prepend(tree);
1372                 return res;
1373             }
1374         }
1375 
1376         boolean merge(ListBuffer<JCLiteral> litBuf, ListBuffer<JCExpression> opStack) {
1377             if (litBuf.isEmpty()) {
1378                 return false;
1379             } else if (litBuf.size() == 1) {
1380                 opStack.prepend(litBuf.first());
1381                 return false;
1382             } else {
1383                 JCExpression t = F.at(litBuf.first().getStartPosition()).Literal(TypeTag.CLASS,
1384                         litBuf.stream().map(lit -> (String)lit.getValue()).collect(Collectors.joining()));
1385                 storeEnd(t, litBuf.last().getEndPosition(endPosTable));
1386                 opStack.prepend(t);
1387                 return true;
1388             }
1389         }
1390 
1391         private JCLiteral stringLiteral(JCTree tree) {
1392             if (tree.hasTag(LITERAL)) {
1393                 JCLiteral lit = (JCLiteral)tree;
1394                 if (lit.typetag == TypeTag.CLASS) {
1395                     return lit;
1396                 }
1397             }
1398             return null;
1399         }
1400 
1401 
1402         /** optimization: To save allocating a new operand/operator stack
1403          *  for every binary operation, we use supplys.
1404          */
1405         ArrayList<JCExpression[]> odStackSupply = new ArrayList<>();
1406         ArrayList<Token[]> opStackSupply = new ArrayList<>();
1407 
1408         private JCExpression[] newOdStack() {
1409             if (odStackSupply.isEmpty())
1410                 return new JCExpression[infixPrecedenceLevels + 1];
1411             return odStackSupply.remove(odStackSupply.size() - 1);
1412         }
1413 
1414         private Token[] newOpStack() {
1415             if (opStackSupply.isEmpty())
1416                 return new Token[infixPrecedenceLevels + 1];
1417             return opStackSupply.remove(opStackSupply.size() - 1);
1418         }
1419 
1420     /**
1421      *  Expression3    = PrefixOp Expression3
1422      *                 | "(" Expr | TypeNoParams ")" Expression3
1423      *                 | Primary {Selector} {PostfixOp}
1424      *
1425      *  {@literal
1426      *  Primary        = "(" Expression ")"
1427      *                 | Literal
1428      *                 | [TypeArguments] THIS [Arguments]
1429      *                 | [TypeArguments] SUPER SuperSuffix
1430      *                 | NEW [TypeArguments] Creator
1431      *                 | "(" Arguments ")" "->" ( Expression | Block )
1432      *                 | Ident "->" ( Expression | Block )
1433      *                 | [Annotations] Ident { "." [Annotations] Ident }
1434      *                 | Expression3 MemberReferenceSuffix
1435      *                   [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
1436      *                   | Arguments
1437      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
1438      *                   ]
1439      *                 | BasicType BracketsOpt "." CLASS
1440      *  }
1441      *
1442      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
1443      *  PostfixOp      = "++" | "--"
1444      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
1445      *                 | BasicType
1446      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
1447      *  Selector       = "." [TypeArguments] Ident [Arguments]
1448      *                 | "." THIS
1449      *                 | "." [TypeArguments] SUPER SuperSuffix
1450      *                 | "." NEW [TypeArguments] InnerCreator
1451      *                 | "[" Expression "]"
1452      *  TypeSelector   = "." Ident [TypeArguments]
1453      *  SuperSuffix    = Arguments | "." Ident [Arguments]
1454      */
1455     protected JCExpression term3() {
1456         int pos = token.pos;
1457         JCExpression t;
1458         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
1459         switch (token.kind) {
1460         case QUES:
1461             if (isMode(TYPE) && isMode(TYPEARG) && !isMode(NOPARAMS)) {
1462                 selectTypeMode();
1463                 return typeArgument();
1464             } else
1465                 return illegal();
1466         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
1467             if (typeArgs == null && isMode(EXPR)) {
1468                 TokenKind tk = token.kind;
1469                 nextToken();
1470                 selectExprMode();
1471                 if (tk == SUB &&
1472                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
1473                     token.radix() == 10) {
1474                     selectExprMode();
1475                     t = literal(names.hyphen, pos);
1476                 } else {
1477                     t = term3();
1478                     return F.at(pos).Unary(unoptag(tk), t);
1479                 }
1480             } else return illegal();
1481             break;
1482         case LPAREN:
1483             if (typeArgs == null && isMode(EXPR)) {
1484                 ParensResult pres = analyzeParens();
1485                 switch (pres) {
1486                     case CAST:
1487                        accept(LPAREN);
1488                        selectTypeMode();
1489                        t = parseIntersectionType(pos, parseType());
1490                        accept(RPAREN);
1491                        selectExprMode();
1492                        JCExpression t1 = term3();
1493                        return F.at(pos).TypeCast(t, t1);
1494                     case IMPLICIT_LAMBDA:
1495                     case EXPLICIT_LAMBDA:
1496                         t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
1497                         break;
1498                     default: //PARENS
1499                         accept(LPAREN);
1500                         selectExprMode();
1501                         t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
1502                         accept(RPAREN);
1503                         t = toP(F.at(pos).Parens(t));
1504                         break;
1505                 }
1506             } else {
1507                 return illegal();
1508             }
1509             break;
1510         case THIS:
1511             if (isMode(EXPR)) {
1512                 selectExprMode();
1513                 t = to(F.at(pos).Ident(names._this));
1514                 nextToken();
1515                 if (typeArgs == null)
1516                     t = argumentsOpt(null, t);
1517                 else
1518                     t = arguments(typeArgs, t);
1519                 typeArgs = null;
1520             } else return illegal();
1521             break;
1522         case SUPER:
1523             if (isMode(EXPR)) {
1524                 selectExprMode();
1525                 t = to(F.at(pos).Ident(names._super));
1526                 t = superSuffix(typeArgs, t);
1527                 typeArgs = null;
1528             } else return illegal();
1529             break;
1530         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
1531         case CHARLITERAL: case STRINGLITERAL:
1532         case TRUE: case FALSE: case NULL:
1533             if (typeArgs == null && isMode(EXPR)) {
1534                 selectExprMode();
1535                 t = literal(names.empty);
1536             } else return illegal();
1537             break;
1538         case NEW:
1539             if (typeArgs != null) return illegal();
1540             if (isMode(EXPR)) {
1541                 selectExprMode();
1542                 nextToken();
1543                 if (token.kind == LT) typeArgs = typeArguments(false);
1544                 t = creator(pos, typeArgs);
1545                 typeArgs = null;
1546             } else return illegal();
1547             break;
1548         case MONKEYS_AT:
1549             // Only annotated cast types and method references are valid
1550             List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
1551             if (typeAnnos.isEmpty()) {
1552                 // else there would be no '@'
1553                 throw new AssertionError("Expected type annotations, but found none!");
1554             }
1555 
1556             JCExpression expr = term3();
1557 
1558             if (!isMode(TYPE)) {
1559                 // Type annotations on class literals no longer legal
1560                 switch (expr.getTag()) {
1561                 case REFERENCE: {
1562                     JCMemberReference mref = (JCMemberReference) expr;
1563                     mref.expr = toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr));
1564                     t = mref;
1565                     break;
1566                 }
1567                 case SELECT: {
1568                     JCFieldAccess sel = (JCFieldAccess) expr;
1569 
1570                     if (sel.name != names._class) {
1571                         return illegal();
1572                     } else {
1573                         log.error(token.pos, Errors.NoAnnotationsOnDotClass);
1574                         return expr;
1575                     }
1576                 }
1577                 default:
1578                     return illegal(typeAnnos.head.pos);
1579                 }
1580 
1581             } else {
1582                 // Type annotations targeting a cast
1583                 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
1584             }
1585             break;
1586         case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
1587             if (typeArgs != null) return illegal();
1588             if (isMode(EXPR) && !isMode(NOLAMBDA) && peekToken(ARROW)) {
1589                 t = lambdaExpressionOrStatement(false, false, pos);
1590             } else {
1591                 t = toP(F.at(token.pos).Ident(ident()));
1592                 loop: while (true) {
1593                     pos = token.pos;
1594                     final List<JCAnnotation> annos = typeAnnotationsOpt();
1595 
1596                     // need to report an error later if LBRACKET is for array
1597                     // index access rather than array creation level
1598                     if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
1599                         return illegal(annos.head.pos);
1600 
1601                     switch (token.kind) {
1602                     case LBRACKET:
1603                         nextToken();
1604                         if (token.kind == RBRACKET) {
1605                             nextToken();
1606                             t = bracketsOpt(t);
1607                             t = toP(F.at(pos).TypeArray(t));
1608                             if (annos.nonEmpty()) {
1609                                 t = toP(F.at(pos).AnnotatedType(annos, t));
1610                             }
1611                             t = bracketsSuffix(t);
1612                         } else {
1613                             if (isMode(EXPR)) {
1614                                 selectExprMode();
1615                                 JCExpression t1 = term();
1616                                 if (!annos.isEmpty()) t = illegal(annos.head.pos);
1617                                 t = to(F.at(pos).Indexed(t, t1));
1618                             }
1619                             accept(RBRACKET);
1620                         }
1621                         break loop;
1622                     case LPAREN:
1623                         if (isMode(EXPR)) {
1624                             selectExprMode();
1625                             t = arguments(typeArgs, t);
1626                             if (!annos.isEmpty()) t = illegal(annos.head.pos);
1627                             typeArgs = null;
1628                         }
1629                         break loop;
1630                     case DOT:
1631                         nextToken();
1632                         if (token.kind == TokenKind.IDENTIFIER && typeArgs != null) {
1633                             return illegal();
1634                         }
1635                         int prevmode = mode;
1636                         setMode(mode & ~NOPARAMS);
1637                         typeArgs = typeArgumentsOpt(EXPR);
1638                         setMode(prevmode);
1639                         if (isMode(EXPR)) {
1640                             switch (token.kind) {
1641                             case CLASS:
1642                                 if (typeArgs != null) return illegal();
1643                                 selectExprMode();
1644                                 t = to(F.at(pos).Select(t, names._class));
1645                                 nextToken();
1646                                 break loop;
1647                             case THIS:
1648                                 if (typeArgs != null) return illegal();
1649                                 selectExprMode();
1650                                 t = to(F.at(pos).Select(t, names._this));
1651                                 nextToken();
1652                                 break loop;
1653                             case SUPER:
1654                                 selectExprMode();
1655                                 t = to(F.at(pos).Select(t, names._super));
1656                                 t = superSuffix(typeArgs, t);
1657                                 typeArgs = null;
1658                                 break loop;
1659                             case NEW:
1660                                 if (typeArgs != null) return illegal();
1661                                 selectExprMode();
1662                                 int pos1 = token.pos;
1663                                 nextToken();
1664                                 if (token.kind == LT) typeArgs = typeArguments(false);
1665                                 t = innerCreator(pos1, typeArgs, t);
1666                                 typeArgs = null;
1667                                 break loop;
1668                             }
1669                         }
1670 
1671                         List<JCAnnotation> tyannos = null;
1672                         if (isMode(TYPE) && token.kind == MONKEYS_AT) {
1673                             tyannos = typeAnnotationsOpt();
1674                         }
1675                         // typeArgs saved for next loop iteration.
1676                         t = toP(F.at(pos).Select(t, ident()));
1677                         if (token.pos <= endPosTable.errorEndPos &&
1678                             token.kind == MONKEYS_AT) {
1679                             //error recovery, case like:
1680                             //int i = expr.<missing-ident>
1681                             //@Deprecated
1682                             if (typeArgs != null) illegal();
1683                             return toP(t);
1684                         }
1685                         if (tyannos != null && tyannos.nonEmpty()) {
1686                             t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1687                         }
1688                         break;
1689                     case ELLIPSIS:
1690                         if (this.permitTypeAnnotationsPushBack) {
1691                             this.typeAnnotationsPushedBack = annos;
1692                         } else if (annos.nonEmpty()) {
1693                             // Don't return here -- error recovery attempt
1694                             illegal(annos.head.pos);
1695                         }
1696                         break loop;
1697                     case LT:
1698                         if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1699                             //this is either an unbound method reference whose qualifier
1700                             //is a generic type i.e. A<S>::m
1701                             int pos1 = token.pos;
1702                             accept(LT);
1703                             ListBuffer<JCExpression> args = new ListBuffer<>();
1704                             args.append(typeArgument());
1705                             while (token.kind == COMMA) {
1706                                 nextToken();
1707                                 args.append(typeArgument());
1708                             }
1709                             accept(GT);
1710                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
1711                             while (token.kind == DOT) {
1712                                 nextToken();
1713                                 selectTypeMode();
1714                                 t = toP(F.at(token.pos).Select(t, ident()));
1715                                 t = typeArgumentsOpt(t);
1716                             }
1717                             t = bracketsOpt(t);
1718                             if (token.kind != COLCOL) {
1719                                 //method reference expected here
1720                                 t = illegal();
1721                             }
1722                             selectExprMode();
1723                             return term3Rest(t, typeArgs);
1724                         }
1725                         break loop;
1726                     default:
1727                         break loop;
1728                     }
1729                 }
1730             }
1731             if (typeArgs != null) illegal();
1732             t = typeArgumentsOpt(t);
1733             break;
1734         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1735         case DOUBLE: case BOOLEAN:
1736             if (typeArgs != null) illegal();
1737             t = bracketsSuffix(bracketsOpt(basicType()));
1738             break;
1739         case VOID:
1740             if (typeArgs != null) illegal();
1741             if (isMode(EXPR)) {
1742                 nextToken();
1743                 if (token.kind == DOT) {
1744                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
1745                     t = bracketsSuffix(ti);
1746                 } else {
1747                     return illegal(pos);
1748                 }
1749             } else {
1750                 // Support the corner case of myMethodHandle.<void>invoke() by passing
1751                 // a void type (like other primitive types) to the next phase.
1752                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1753                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
1754                 nextToken();
1755                 return ti;
1756                 //return illegal();
1757             }
1758             break;
1759         case SWITCH:
1760             checkSourceLevel(Feature.SWITCH_EXPRESSION);
1761             allowYieldStatement = true;
1762             int switchPos = token.pos;
1763             nextToken();
1764             JCExpression selector = parExpression();
1765             accept(LBRACE);
1766             ListBuffer<JCCase> cases = new ListBuffer<>();
1767             while (true) {
1768                 pos = token.pos;
1769                 switch (token.kind) {
1770                 case CASE:
1771                 case DEFAULT:
1772                     cases.appendList(switchExpressionStatementGroup());
1773                     break;
1774                 case RBRACE: case EOF:
1775                     JCSwitchExpression e = to(F.at(switchPos).SwitchExpression(selector,
1776                                                                                cases.toList()));
1777                     e.bracePos = token.pos;
1778                     accept(RBRACE);
1779                     return e;
1780                 default:
1781                     nextToken(); // to ensure progress
1782                     syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
1783                 }
1784             }
1785             // Not reachable.
1786         default:
1787             return illegal();
1788         }
1789         return term3Rest(t, typeArgs);
1790     }
1791 
1792     private List<JCCase> switchExpressionStatementGroup() {
1793         ListBuffer<JCCase> caseExprs = new ListBuffer<>();
1794         int casePos = token.pos;
1795         ListBuffer<JCCaseLabel> pats = new ListBuffer<>();
1796 
1797         if (token.kind == DEFAULT) {
1798             nextToken();
1799             pats.append(toP(F.at(casePos).DefaultCaseLabel()));
1800         } else {
1801             accept(CASE);
1802             boolean allowDefault = false;
1803             while (true) {
1804                 JCCaseLabel label = parseCaseLabel(allowDefault);
1805                 pats.append(label);
1806                 if (token.kind != COMMA) break;
1807                 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
1808                 nextToken();
1809                 allowDefault = TreeInfo.isNullCaseLabel(label);
1810             };
1811         }
1812         JCExpression guard = parseGuard(pats.last());
1813         List<JCStatement> stats = null;
1814         JCTree body = null;
1815         CaseTree.CaseKind kind;
1816         switch (token.kind) {
1817             case ARROW:
1818                 checkSourceLevel(Feature.SWITCH_RULE);
1819                 nextToken();
1820                 if (token.kind == TokenKind.THROW || token.kind == TokenKind.LBRACE) {
1821                     stats = List.of(parseStatement());
1822                     body = stats.head;
1823                     kind = JCCase.RULE;
1824                 } else {
1825                     JCExpression value = parseExpression();
1826                     stats = List.of(to(F.at(value).Yield(value)));
1827                     body = value;
1828                     kind = JCCase.RULE;
1829                     accept(SEMI);
1830                 }
1831                 break;
1832             default:
1833                 accept(COLON, tk -> Errors.Expected2(COLON, ARROW));
1834                 stats = blockStatements();
1835                 kind = JCCase.STATEMENT;
1836                 break;
1837         }
1838         caseExprs.append(toP(F.at(casePos).Case(kind, pats.toList(), guard, stats, body)));
1839         return caseExprs.toList();
1840     }
1841 
1842     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
1843         if (typeArgs != null) illegal();
1844         while (true) {
1845             int pos1 = token.pos;
1846             final List<JCAnnotation> annos = typeAnnotationsOpt();
1847 
1848             if (token.kind == LBRACKET) {
1849                 nextToken();
1850                 if (isMode(TYPE)) {
1851                     int prevmode = mode;
1852                     selectTypeMode();
1853                     if (token.kind == RBRACKET) {
1854                         nextToken();
1855                         t = bracketsOpt(t);
1856                         t = toP(F.at(pos1).TypeArray(t));
1857                         if (token.kind == COLCOL) {
1858                             selectExprMode();
1859                             continue;
1860                         }
1861                         if (annos.nonEmpty()) {
1862                             t = toP(F.at(pos1).AnnotatedType(annos, t));
1863                         }
1864                         return t;
1865                     }
1866                     setMode(prevmode);
1867                 }
1868                 if (isMode(EXPR)) {
1869                     selectExprMode();
1870                     JCExpression t1 = term();
1871                     t = to(F.at(pos1).Indexed(t, t1));
1872                 }
1873                 accept(RBRACKET);
1874             } else if (token.kind == DOT) {
1875                 nextToken();
1876                 typeArgs = typeArgumentsOpt(EXPR);
1877                 if (token.kind == SUPER && isMode(EXPR)) {
1878                     selectExprMode();
1879                     t = to(F.at(pos1).Select(t, names._super));
1880                     nextToken();
1881                     t = arguments(typeArgs, t);
1882                     typeArgs = null;
1883                 } else if (token.kind == NEW && isMode(EXPR)) {
1884                     if (typeArgs != null) return illegal();
1885                     selectExprMode();
1886                     int pos2 = token.pos;
1887                     nextToken();
1888                     if (token.kind == LT) typeArgs = typeArguments(false);
1889                     t = innerCreator(pos2, typeArgs, t);
1890                     typeArgs = null;
1891                 } else {
1892                     List<JCAnnotation> tyannos = null;
1893                     if (isMode(TYPE) && token.kind == MONKEYS_AT) {
1894                         // is the mode check needed?
1895                         tyannos = typeAnnotationsOpt();
1896                     }
1897                     t = toP(F.at(pos1).Select(t, ident(true)));
1898                     if (token.pos <= endPosTable.errorEndPos &&
1899                         token.kind == MONKEYS_AT) {
1900                         //error recovery, case like:
1901                         //int i = expr.<missing-ident>
1902                         //@Deprecated
1903                         break;
1904                     }
1905                     if (tyannos != null && tyannos.nonEmpty()) {
1906                         t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1907                     }
1908                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1909                     typeArgs = null;
1910                 }
1911             } else if (isMode(EXPR) && token.kind == COLCOL) {
1912                 selectExprMode();
1913                 if (typeArgs != null) return illegal();
1914                 accept(COLCOL);
1915                 t = memberReferenceSuffix(pos1, t);
1916             } else {
1917                 if (!annos.isEmpty()) {
1918                     if (permitTypeAnnotationsPushBack)
1919                         typeAnnotationsPushedBack = annos;
1920                     else
1921                         return illegal(annos.head.pos);
1922                 }
1923                 break;
1924             }
1925         }
1926         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1927             selectExprMode();
1928             t = to(F.at(token.pos).Unary(
1929                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1930             nextToken();
1931         }
1932         return toP(t);
1933     }
1934 
1935     /**
1936      * If we see an identifier followed by a '&lt;' it could be an unbound
1937      * method reference or a binary expression. To disambiguate, look for a
1938      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
1939      */
1940     @SuppressWarnings("fallthrough")
1941     boolean isParameterizedTypePrefix() {
1942         int pos = 0, depth = 0;
1943         outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1944             switch (t.kind) {
1945                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1946                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1947                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1948                 case DOUBLE: case BOOLEAN: case CHAR:
1949                 case MONKEYS_AT:
1950                     break;
1951 
1952                 case LPAREN:
1953                     // skip annotation values
1954                     int nesting = 0;
1955                     for (; ; pos++) {
1956                         TokenKind tk2 = S.token(pos).kind;
1957                         switch (tk2) {
1958                             case EOF:
1959                                 return false;
1960                             case LPAREN:
1961                                 nesting++;
1962                                 break;
1963                             case RPAREN:
1964                                 nesting--;
1965                                 if (nesting == 0) {
1966                                     continue outer;
1967                                 }
1968                                 break;
1969                         }
1970                     }
1971 
1972                 case LT:
1973                     depth++; break;
1974                 case GTGTGT:
1975                     depth--;
1976                 case GTGT:
1977                     depth--;
1978                 case GT:
1979                     depth--;
1980                     if (depth == 0) {
1981                         TokenKind nextKind = S.token(pos + 1).kind;
1982                         return
1983                             nextKind == TokenKind.DOT ||
1984                             nextKind == TokenKind.LBRACKET ||
1985                             nextKind == TokenKind.COLCOL;
1986                     }
1987                     break;
1988                 default:
1989                     return false;
1990             }
1991         }
1992     }
1993 
1994     /**
1995      * If we see an identifier followed by a '&lt;' it could be an unbound
1996      * method reference or a binary expression. To disambiguate, look for a
1997      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
1998      */
1999     @SuppressWarnings("fallthrough")
2000     ParensResult analyzeParens() {
2001         int depth = 0;
2002         boolean type = false;
2003         ParensResult defaultResult = ParensResult.PARENS;
2004         outer: for (int lookahead = 0; ; lookahead++) {
2005             TokenKind tk = S.token(lookahead).kind;
2006             switch (tk) {
2007                 case COMMA:
2008                     type = true;
2009                 case EXTENDS: case SUPER: case DOT: case AMP:
2010                     //skip
2011                     break;
2012                 case QUES:
2013                     if (peekToken(lookahead, EXTENDS) ||
2014                             peekToken(lookahead, SUPER)) {
2015                         //wildcards
2016                         type = true;
2017                     }
2018                     break;
2019                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
2020                 case DOUBLE: case BOOLEAN: case CHAR: case VOID:
2021                     if (peekToken(lookahead, RPAREN)) {
2022                         //Type, ')' -> cast
2023                         return ParensResult.CAST;
2024                     } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
2025                         //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
2026                         return ParensResult.EXPLICIT_LAMBDA;
2027                     }
2028                     break;
2029                 case LPAREN:
2030                     if (lookahead != 0) {
2031                         // '(' in a non-starting position -> parens
2032                         return ParensResult.PARENS;
2033                     } else if (peekToken(lookahead, RPAREN)) {
2034                         // '(', ')' -> explicit lambda
2035                         return ParensResult.EXPLICIT_LAMBDA;
2036                     }
2037                     break;
2038                 case RPAREN:
2039                     // if we have seen something that looks like a type,
2040                     // then it's a cast expression
2041                     if (type) return ParensResult.CAST;
2042                     // otherwise, disambiguate cast vs. parenthesized expression
2043                     // based on subsequent token.
2044                     switch (S.token(lookahead + 1).kind) {
2045                         /*case PLUSPLUS: case SUBSUB: */
2046                         case BANG: case TILDE:
2047                         case LPAREN: case THIS: case SUPER:
2048                         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
2049                         case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
2050                         case STRINGFRAGMENT:
2051                         case TRUE: case FALSE: case NULL:
2052                         case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
2053                         case SWITCH:
2054                         case BYTE: case SHORT: case CHAR: case INT:
2055                         case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
2056                             return ParensResult.CAST;
2057                         default:
2058                             return defaultResult;
2059                     }
2060                 case UNDERSCORE:
2061                 case ASSERT:
2062                 case ENUM:
2063                 case IDENTIFIER:
2064                     if (peekToken(lookahead, LAX_IDENTIFIER)) {
2065                         // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
2066                         return ParensResult.EXPLICIT_LAMBDA;
2067                     } else if (peekToken(lookahead, RPAREN, ARROW)) {
2068                         // Identifier, ')' '->' -> implicit lambda
2069                         return !isMode(NOLAMBDA) ? ParensResult.IMPLICIT_LAMBDA
2070                                                  : ParensResult.PARENS;
2071                     } else if (depth == 0 && peekToken(lookahead, COMMA)) {
2072                         defaultResult = ParensResult.IMPLICIT_LAMBDA;
2073                     }
2074                     type = false;
2075                     break;
2076                 case FINAL:
2077                 case ELLIPSIS:
2078                     //those can only appear in explicit lambdas
2079                     return ParensResult.EXPLICIT_LAMBDA;
2080                 case MONKEYS_AT:
2081                     type = true;
2082                     lookahead = skipAnnotation(lookahead);
2083                     break;
2084                 case LBRACKET:
2085                     if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
2086                         // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
2087                         return ParensResult.EXPLICIT_LAMBDA;
2088                     } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
2089                             peekToken(lookahead, RBRACKET, AMP)) {
2090                         // '[', ']', ')' -> cast
2091                         // '[', ']', '&' -> cast (intersection type)
2092                         return ParensResult.CAST;
2093                     } else if (peekToken(lookahead, RBRACKET)) {
2094                         //consume the ']' and skip
2095                         type = true;
2096                         lookahead++;
2097                         break;
2098                     } else {
2099                         return ParensResult.PARENS;
2100                     }
2101                 case LT:
2102                     depth++; break;
2103                 case GTGTGT:
2104                     depth--;
2105                 case GTGT:
2106                     depth--;
2107                 case GT:
2108                     depth--;
2109                     if (depth == 0) {
2110                         if (peekToken(lookahead, RPAREN) ||
2111                                 peekToken(lookahead, AMP)) {
2112                             // '>', ')' -> cast
2113                             // '>', '&' -> cast
2114                             return ParensResult.CAST;
2115                         } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
2116                                 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
2117                                 peekToken(lookahead, ELLIPSIS)) {
2118                             // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
2119                             // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
2120                             // '>', '...' -> explicit lambda
2121                             return ParensResult.EXPLICIT_LAMBDA;
2122                         }
2123                         //it looks a type, but could still be (i) a cast to generic type,
2124                         //(ii) an unbound method reference or (iii) an explicit lambda
2125                         type = true;
2126                         break;
2127                     } else if (depth < 0) {
2128                         //unbalanced '<', '>' - not a generic type
2129                         return ParensResult.PARENS;
2130                     }
2131                     break;
2132                 default:
2133                     //this includes EOF
2134                     return defaultResult;
2135             }
2136         }
2137     }
2138 
2139     private int skipAnnotation(int lookahead) {
2140         lookahead += 1; //skip '@'
2141         while (peekToken(lookahead, DOT)) {
2142             lookahead += 2;
2143         }
2144         if (peekToken(lookahead, LPAREN)) {
2145             lookahead++;
2146             //skip annotation values
2147             int nesting = 0;
2148             for (; ; lookahead++) {
2149                 TokenKind tk2 = S.token(lookahead).kind;
2150                 switch (tk2) {
2151                     case EOF:
2152                         return lookahead;
2153                     case LPAREN:
2154                         nesting++;
2155                         break;
2156                     case RPAREN:
2157                         nesting--;
2158                         if (nesting == 0) {
2159                             return lookahead;
2160                         }
2161                     break;
2162                 }
2163             }
2164         }
2165         return lookahead;
2166     }
2167 
2168     /** Accepts all identifier-like tokens */
2169     protected Predicate<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
2170 
2171     enum ParensResult {
2172         CAST,
2173         EXPLICIT_LAMBDA,
2174         IMPLICIT_LAMBDA,
2175         PARENS
2176     }
2177 
2178     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
2179         List<JCVariableDecl> params = explicitParams ?
2180                 formalParameters(true, false) :
2181                 implicitParameters(hasParens);
2182         if (explicitParams) {
2183             LambdaClassifier lambdaClassifier = new LambdaClassifier();
2184             for (JCVariableDecl param: params) {
2185                 Name restrictedTypeName;
2186                 if (param.vartype != null &&
2187                         (restrictedTypeName = restrictedTypeName(param.vartype, false)) != null &&
2188                         param.vartype.hasTag(TYPEARRAY)) {
2189                     log.error(DiagnosticFlag.SYNTAX, param.pos,
2190                         Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source)
2191                             ? Errors.RestrictedTypeNotAllowedArray(restrictedTypeName) : Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
2192                 }
2193                 lambdaClassifier.addParameter(param);
2194                 if (lambdaClassifier.result() == LambdaParameterKind.ERROR) {
2195                     break;
2196                 }
2197             }
2198             if (lambdaClassifier.diagFragment != null) {
2199                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidLambdaParameterDeclaration(lambdaClassifier.diagFragment));
2200             }
2201             for (JCVariableDecl param: params) {
2202                 if (param.vartype != null
2203                         && restrictedTypeName(param.vartype, true) != null) {
2204                     checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS);
2205                     param.startPos = TreeInfo.getStartPos(param.vartype);
2206                     param.vartype = null;
2207                 }
2208             }
2209         }
2210         return lambdaExpressionOrStatementRest(params, pos);
2211     }
2212 
2213     enum LambdaParameterKind {
2214         VAR(0),
2215         EXPLICIT(1),
2216         IMPLICIT(2),
2217         ERROR(-1);
2218 
2219         private final int index;
2220 
2221         LambdaParameterKind(int index) {
2222             this.index = index;
2223         }
2224     }
2225 
2226     private static final Fragment[][] decisionTable = new Fragment[][] {
2227         /*              VAR                              EXPLICIT                         IMPLICIT  */
2228         /* VAR      */ {null,                            VarAndExplicitNotAllowed,        VarAndImplicitNotAllowed},
2229         /* EXPLICIT */ {VarAndExplicitNotAllowed,        null,                            ImplicitAndExplicitNotAllowed},
2230         /* IMPLICIT */ {VarAndImplicitNotAllowed,        ImplicitAndExplicitNotAllowed,   null},
2231     };
2232 
2233     class LambdaClassifier {
2234         LambdaParameterKind kind;
2235         Fragment diagFragment;
2236 
2237         /**
2238          * analyzeParens() has already classified the lambda as EXPLICIT_LAMBDA, due to
2239          * two consecutive identifiers. Because of that {@code (<explicit lambda>)}, the
2240          * parser will always attempt to parse a type, followed by a name. If the lambda
2241          * contains an illegal mix of implicit and explicit parameters, it is possible
2242          * for the parser to see a {@code ,} when expecting a name, in which case the
2243          * variable is created with an erroneous name. The logic below makes sure that
2244          * the lambda parameters are all declared with either an explicit type (e.g.
2245          * {@code String x}), or with an inferred type (using {@code var x}). Any other
2246          * combination is rejected.
2247          * */
2248         void addParameter(JCVariableDecl param) {
2249             Assert.check(param.vartype != null);
2250 
2251             if (param.name == names.error) {
2252                 reduce(LambdaParameterKind.IMPLICIT);
2253             }
2254             else if (restrictedTypeName(param.vartype, false) != null) {
2255                 reduce(LambdaParameterKind.VAR);
2256             } else {
2257                 reduce(LambdaParameterKind.EXPLICIT);
2258             }
2259         }
2260 
2261         private void reduce(LambdaParameterKind newKind) {
2262             if (kind == null) {
2263                 kind = newKind;
2264             } else if (kind != newKind && kind != LambdaParameterKind.ERROR) {
2265                 LambdaParameterKind currentKind = kind;
2266                 kind = LambdaParameterKind.ERROR;
2267                 boolean varIndex = currentKind.index == LambdaParameterKind.VAR.index ||
2268                         newKind.index == LambdaParameterKind.VAR.index;
2269                 diagFragment = Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source) || !varIndex ?
2270                         decisionTable[currentKind.index][newKind.index] : null;
2271             }
2272         }
2273 
2274         LambdaParameterKind result() {
2275             return kind;
2276         }
2277     }
2278 
2279     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
2280         accept(ARROW);
2281 
2282         return token.kind == LBRACE ?
2283             lambdaStatement(args, pos, token.pos) :
2284             lambdaExpression(args, pos);
2285     }
2286 
2287     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
2288         JCBlock block = block(pos2, 0);
2289         return toP(F.at(pos).Lambda(args, block));
2290     }
2291 
2292     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
2293         JCTree expr = parseExpression();
2294         return toP(F.at(pos).Lambda(args, expr));
2295     }
2296 
2297     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
2298      */
2299     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
2300         nextToken();
2301         if (token.kind == LPAREN || typeArgs != null) {
2302             t = arguments(typeArgs, t);
2303         } else if (token.kind == COLCOL) {
2304             if (typeArgs != null) return illegal();
2305             t = memberReferenceSuffix(t);
2306         } else {
2307             int pos = token.pos;
2308             accept(DOT);
2309             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
2310             t = toP(F.at(pos).Select(t, ident()));
2311             t = argumentsOpt(typeArgs, t);
2312         }
2313         return t;
2314     }
2315 
2316     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
2317      */
2318     JCPrimitiveTypeTree basicType() {
2319         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
2320         nextToken();
2321         return t;
2322     }
2323 
2324     /** ArgumentsOpt = [ Arguments ]
2325      */
2326     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
2327         if (isMode(EXPR) && token.kind == LPAREN || typeArgs != null) {
2328             selectExprMode();
2329             return arguments(typeArgs, t);
2330         } else {
2331             return t;
2332         }
2333     }
2334 
2335     /** Arguments = "(" [Expression { COMMA Expression }] ")"
2336      */
2337     List<JCExpression> arguments() {
2338         ListBuffer<JCExpression> args = new ListBuffer<>();
2339         if (token.kind == LPAREN) {
2340             nextToken();
2341             if (token.kind != RPAREN) {
2342                 args.append(parseExpression());
2343                 while (token.kind == COMMA) {
2344                     nextToken();
2345                     args.append(parseExpression());
2346                 }
2347             }
2348             accept(RPAREN, tk -> Errors.Expected2(RPAREN, COMMA));
2349         } else {
2350             syntaxError(token.pos, Errors.Expected(LPAREN));
2351         }
2352         return args.toList();
2353     }
2354 
2355     JCExpression arguments(List<JCExpression> typeArgs, JCExpression t) {
2356         int pos = token.pos;
2357         List<JCExpression> args = arguments();
2358         JCExpression mi = F.at(pos).Apply(typeArgs, t, args);
2359         if (t.hasTag(IDENT) && isInvalidUnqualifiedMethodIdentifier(((JCIdent) t).pos,
2360                                                                     ((JCIdent) t).name)) {
2361             log.error(DiagnosticFlag.SYNTAX, t, Errors.InvalidYield);
2362             mi = F.Erroneous(List.of(mi));
2363         }
2364         return toP(mi);
2365     }
2366 
2367     boolean isInvalidUnqualifiedMethodIdentifier(int pos, Name name) {
2368         if (name == names.yield) {
2369             if (allowYieldStatement) {
2370                 return true;
2371             } else {
2372                 log.warning(pos, Warnings.InvalidYield);
2373             }
2374         }
2375         return false;
2376     }
2377 
2378     /**  TypeArgumentsOpt = [ TypeArguments ]
2379      */
2380     JCExpression typeArgumentsOpt(JCExpression t) {
2381         if (token.kind == LT &&
2382             isMode(TYPE) &&
2383             !isMode(NOPARAMS)) {
2384             selectTypeMode();
2385             return typeArguments(t, false);
2386         } else {
2387             return t;
2388         }
2389     }
2390     List<JCExpression> typeArgumentsOpt() {
2391         return typeArgumentsOpt(TYPE);
2392     }
2393 
2394     List<JCExpression> typeArgumentsOpt(int useMode) {
2395         if (token.kind == LT) {
2396             if (!isMode(useMode) ||
2397                 isMode(NOPARAMS)) {
2398                 illegal();
2399             }
2400             setMode(useMode);
2401             return typeArguments(false);
2402         }
2403         return null;
2404     }
2405 
2406     /**
2407      *  {@literal
2408      *  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
2409      *  }
2410      */
2411     List<JCExpression> typeArguments(boolean diamondAllowed) {
2412         if (token.kind == LT) {
2413             nextToken();
2414             if (token.kind == GT && diamondAllowed) {
2415                 setMode(mode | DIAMOND);
2416                 nextToken();
2417                 return List.nil();
2418             } else {
2419                 ListBuffer<JCExpression> args = new ListBuffer<>();
2420                 args.append(!isMode(EXPR) ? typeArgument() : parseType());
2421                 while (token.kind == COMMA) {
2422                     nextToken();
2423                     args.append(!isMode(EXPR) ? typeArgument() : parseType());
2424                 }
2425                 switch (token.kind) {
2426 
2427                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
2428                 case GTGTGT: case GTGT:
2429                     token = S.split();
2430                     break;
2431                 case GT:
2432                     nextToken();
2433                     break;
2434                 default:
2435                     args.append(syntaxError(token.pos, Errors.Expected2(GT, COMMA)));
2436                     break;
2437                 }
2438                 return args.toList();
2439             }
2440         } else {
2441             return List.of(syntaxError(token.pos, Errors.Expected(LT)));
2442         }
2443     }
2444 
2445     /**
2446      *  {@literal
2447      *  TypeArgument = Type
2448      *               | [Annotations] "?"
2449      *               | [Annotations] "?" EXTENDS Type {"&" Type}
2450      *               | [Annotations] "?" SUPER Type
2451      *  }
2452      */
2453     JCExpression typeArgument() {
2454         List<JCAnnotation> annotations = typeAnnotationsOpt();
2455         if (token.kind != QUES) return parseType(false, annotations);
2456         int pos = token.pos;
2457         nextToken();
2458         JCExpression result;
2459         if (token.kind == EXTENDS) {
2460             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
2461             nextToken();
2462             JCExpression bound = parseType();
2463             result = F.at(pos).Wildcard(t, bound);
2464         } else if (token.kind == SUPER) {
2465             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
2466             nextToken();
2467             JCExpression bound = parseType();
2468             result = F.at(pos).Wildcard(t, bound);
2469         } else if (LAX_IDENTIFIER.test(token.kind)) {
2470             //error recovery
2471             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
2472             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
2473             JCIdent id = toP(F.at(token.pos).Ident(ident()));
2474             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
2475             reportSyntaxError(err, Errors.Expected3(GT, EXTENDS, SUPER));
2476             result = err;
2477         } else {
2478             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
2479             result = toP(F.at(pos).Wildcard(t, null));
2480         }
2481         if (!annotations.isEmpty()) {
2482             result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
2483         }
2484         return result;
2485     }
2486 
2487     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
2488         int pos = token.pos;
2489         List<JCExpression> args = typeArguments(diamondAllowed);
2490         return toP(F.at(pos).TypeApply(t, args));
2491     }
2492 
2493     /**
2494      * BracketsOpt = { [Annotations] "[" "]" }*
2495      *
2496      * <p>
2497      *
2498      * <code>annotations</code> is the list of annotations targeting
2499      * the expression <code>t</code>.
2500      */
2501     private JCExpression bracketsOpt(JCExpression t,
2502             List<JCAnnotation> annotations) {
2503         List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
2504 
2505         if (token.kind == LBRACKET) {
2506             int pos = token.pos;
2507             nextToken();
2508             t = bracketsOptCont(t, pos, nextLevelAnnotations);
2509         } else if (!nextLevelAnnotations.isEmpty()) {
2510             if (permitTypeAnnotationsPushBack) {
2511                 this.typeAnnotationsPushedBack = nextLevelAnnotations;
2512             } else {
2513                 return illegal(nextLevelAnnotations.head.pos);
2514             }
2515         }
2516 
2517         if (!annotations.isEmpty()) {
2518             t = toP(F.at(token.pos).AnnotatedType(annotations, t));
2519         }
2520         return t;
2521     }
2522 
2523     /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ]
2524      */
2525     private JCExpression bracketsOpt(JCExpression t) {
2526         return bracketsOpt(t, List.nil());
2527     }
2528 
2529     private JCExpression bracketsOptCont(JCExpression t, int pos,
2530             List<JCAnnotation> annotations) {
2531         accept(RBRACKET);
2532         t = bracketsOpt(t);
2533         t = toP(F.at(pos).TypeArray(t));
2534         if (annotations.nonEmpty()) {
2535             t = toP(F.at(pos).AnnotatedType(annotations, t));
2536         }
2537         return t;
2538     }
2539 
2540     /** BracketsSuffixExpr = "." CLASS
2541      *  BracketsSuffixType =
2542      */
2543     JCExpression bracketsSuffix(JCExpression t) {
2544         if (isMode(EXPR) && token.kind == DOT) {
2545             selectExprMode();
2546             int pos = token.pos;
2547             nextToken();
2548             accept(CLASS);
2549             if (token.pos == endPosTable.errorEndPos) {
2550                 // error recovery
2551                 Name name;
2552                 if (LAX_IDENTIFIER.test(token.kind)) {
2553                     name = token.name();
2554                     nextToken();
2555                 } else {
2556                     name = names.error;
2557                 }
2558                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
2559             } else {
2560                 Tag tag = t.getTag();
2561                 // Type annotations are illegal on class literals. Annotated non array class literals
2562                 // are complained about directly in term3(), Here check for type annotations on dimensions
2563                 // taking care to handle some interior dimension(s) being annotated.
2564                 if ((tag == TYPEARRAY && TreeInfo.containsTypeAnnotation(t)) || tag == ANNOTATED_TYPE)
2565                     syntaxError(token.pos, Errors.NoAnnotationsOnDotClass);
2566                 t = toP(F.at(pos).Select(t, names._class));
2567             }
2568         } else if (isMode(TYPE)) {
2569             if (token.kind != COLCOL) {
2570                 selectTypeMode();
2571             }
2572         } else if (token.kind != COLCOL) {
2573             syntaxError(token.pos, Errors.DotClassExpected);
2574         }
2575         return t;
2576     }
2577 
2578     /**
2579      * MemberReferenceSuffix = "::" [TypeArguments] Ident
2580      *                       | "::" [TypeArguments] "new"
2581      */
2582     JCExpression memberReferenceSuffix(JCExpression t) {
2583         int pos1 = token.pos;
2584         accept(COLCOL);
2585         return memberReferenceSuffix(pos1, t);
2586     }
2587 
2588     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
2589         selectExprMode();
2590         List<JCExpression> typeArgs = null;
2591         if (token.kind == LT) {
2592             typeArgs = typeArguments(false);
2593         }
2594         Name refName;
2595         ReferenceMode refMode;
2596         if (token.kind == NEW) {
2597             refMode = ReferenceMode.NEW;
2598             refName = names.init;
2599             nextToken();
2600         } else {
2601             refMode = ReferenceMode.INVOKE;
2602             refName = ident();
2603         }
2604         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
2605     }
2606 
2607     /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
2608      */
2609     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
2610         List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2611 
2612         switch (token.kind) {
2613         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2614         case DOUBLE: case BOOLEAN:
2615             if (typeArgs == null) {
2616                 if (newAnnotations.isEmpty()) {
2617                     return arrayCreatorRest(newpos, basicType());
2618                 } else {
2619                     return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
2620                 }
2621             }
2622             break;
2623         default:
2624         }
2625         JCExpression t = qualident(true);
2626 
2627         int prevmode = mode;
2628         selectTypeMode();
2629         boolean diamondFound = false;
2630         int lastTypeargsPos = -1;
2631         if (token.kind == LT) {
2632             lastTypeargsPos = token.pos;
2633             t = typeArguments(t, true);
2634             diamondFound = isMode(DIAMOND);
2635         }
2636         while (token.kind == DOT) {
2637             if (diamondFound) {
2638                 //cannot select after a diamond
2639                 illegal();
2640             }
2641             int pos = token.pos;
2642             nextToken();
2643             List<JCAnnotation> tyannos = typeAnnotationsOpt();
2644             t = toP(F.at(pos).Select(t, ident()));
2645 
2646             if (tyannos != null && tyannos.nonEmpty()) {
2647                 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
2648             }
2649 
2650             if (token.kind == LT) {
2651                 lastTypeargsPos = token.pos;
2652                 t = typeArguments(t, true);
2653                 diamondFound = isMode(DIAMOND);
2654             }
2655         }
2656         setMode(prevmode);
2657         if (token.kind == LBRACKET || token.kind == MONKEYS_AT) {
2658             // handle type annotations for non primitive arrays
2659             if (newAnnotations.nonEmpty()) {
2660                 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2661             }
2662 
2663             JCExpression e = arrayCreatorRest(newpos, t);
2664             if (diamondFound) {
2665                 reportSyntaxError(lastTypeargsPos, Errors.CannotCreateArrayWithDiamond);
2666                 return toP(F.at(newpos).Erroneous(List.of(e)));
2667             }
2668             else if (typeArgs != null) {
2669                 int pos = newpos;
2670                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
2671                     // note: this should always happen but we should
2672                     // not rely on this as the parser is continuously
2673                     // modified to improve error recovery.
2674                     pos = typeArgs.head.pos;
2675                 }
2676                 setErrorEndPos(S.prevToken().endPos);
2677                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
2678                 reportSyntaxError(err, Errors.CannotCreateArrayWithTypeArguments);
2679                 return toP(err);
2680             }
2681             return e;
2682         } else if (token.kind == LPAREN) {
2683             // handle type annotations for instantiations and anonymous classes
2684             if (newAnnotations.nonEmpty()) {
2685                 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2686             }
2687             return classCreatorRest(newpos, null, typeArgs, t);
2688         } else {
2689             setErrorEndPos(token.pos);
2690             reportSyntaxError(token.pos, Errors.Expected2(LPAREN, LBRACKET));
2691             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.nil(), null));
2692             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
2693         }
2694     }
2695 
2696     /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
2697      */
2698     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
2699         List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2700 
2701         JCExpression t = toP(F.at(token.pos).Ident(ident()));
2702 
2703         if (newAnnotations.nonEmpty()) {
2704             t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
2705         }
2706 
2707         if (token.kind == LT) {
2708             int prevmode = mode;
2709             t = typeArguments(t, true);
2710             setMode(prevmode);
2711         }
2712         return classCreatorRest(newpos, encl, typeArgs, t);
2713     }
2714 
2715     /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
2716      *                         | Expression "]" {[Annotations]  "[" Expression "]"} BracketsOpt )
2717      */
2718     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
2719         List<JCAnnotation> annos = typeAnnotationsOpt();
2720 
2721         accept(LBRACKET);
2722         if (token.kind == RBRACKET) {
2723             accept(RBRACKET);
2724             elemtype = bracketsOpt(elemtype, annos);
2725             if (token.kind == LBRACE) {
2726                 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
2727                 if (annos.nonEmpty()) {
2728                     // when an array initializer is present then
2729                     // the parsed annotations should target the
2730                     // new array tree
2731                     // bracketsOpt inserts the annotation in
2732                     // elemtype, and it needs to be corrected
2733                     //
2734                     JCAnnotatedType annotated = (JCAnnotatedType)elemtype;
2735                     assert annotated.annotations == annos;
2736                     na.annotations = annotated.annotations;
2737                     na.elemtype = annotated.underlyingType;
2738                 }
2739                 return na;
2740             } else {
2741                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.nil(), null));
2742                 return syntaxError(token.pos, List.of(t), Errors.ArrayDimensionMissing);
2743             }
2744         } else {
2745             ListBuffer<JCExpression> dims = new ListBuffer<>();
2746 
2747             // maintain array dimension type annotations
2748             ListBuffer<List<JCAnnotation>> dimAnnotations = new ListBuffer<>();
2749             dimAnnotations.append(annos);
2750 
2751             dims.append(parseExpression());
2752             accept(RBRACKET);
2753             while (token.kind == LBRACKET
2754                     || token.kind == MONKEYS_AT) {
2755                 List<JCAnnotation> maybeDimAnnos = typeAnnotationsOpt();
2756                 int pos = token.pos;
2757                 nextToken();
2758                 if (token.kind == RBRACKET) { // no dimension
2759                     elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
2760                 } else {
2761                     dimAnnotations.append(maybeDimAnnos);
2762                     dims.append(parseExpression());
2763                     accept(RBRACKET);
2764                 }
2765             }
2766 
2767             List<JCExpression> elems = null;
2768             int errpos = token.pos;
2769 
2770             if (token.kind == LBRACE) {
2771                 elems = arrayInitializerElements(newpos, elemtype);
2772             }
2773 
2774             JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), elems));
2775             na.dimAnnotations = dimAnnotations.toList();
2776 
2777             if (elems != null) {
2778                 return syntaxError(errpos, List.of(na), Errors.IllegalArrayCreationBothDimensionAndInitialization);
2779             }
2780 
2781             return na;
2782         }
2783     }
2784 
2785     /** ClassCreatorRest = Arguments [ClassBody]
2786      */
2787     JCNewClass classCreatorRest(int newpos,
2788                                   JCExpression encl,
2789                                   List<JCExpression> typeArgs,
2790                                   JCExpression t)
2791     {
2792         List<JCExpression> args = arguments();
2793         JCClassDecl body = null;
2794         if (token.kind == LBRACE) {
2795             ignoreDanglingComments(); // ignore any comments from before the '{'
2796             int pos = token.pos;
2797             List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
2798             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2799             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2800         }
2801         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2802     }
2803 
2804     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2805      */
2806     JCExpression arrayInitializer(int newpos, JCExpression t) {
2807         List<JCExpression> elems = arrayInitializerElements(newpos, t);
2808         return toP(F.at(newpos).NewArray(t, List.nil(), elems));
2809     }
2810 
2811     List<JCExpression> arrayInitializerElements(int newpos, JCExpression t) {
2812         accept(LBRACE);
2813         ListBuffer<JCExpression> elems = new ListBuffer<>();
2814         if (token.kind == COMMA) {
2815             nextToken();
2816         } else if (token.kind != RBRACE) {
2817             elems.append(variableInitializer());
2818             while (token.kind == COMMA) {
2819                 nextToken();
2820                 if (token.kind == RBRACE) break;
2821                 elems.append(variableInitializer());
2822             }
2823         }
2824         accept(RBRACE);
2825         return elems.toList();
2826     }
2827 
2828     /** VariableInitializer = ArrayInitializer | Expression
2829      */
2830     public JCExpression variableInitializer() {
2831         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
2832     }
2833 
2834     /** ParExpression = "(" Expression ")"
2835      */
2836     JCExpression parExpression() {
2837         int pos = token.pos;
2838         accept(LPAREN);
2839         JCExpression t = parseExpression();
2840         accept(RPAREN);
2841         return toP(F.at(pos).Parens(t));
2842     }
2843 
2844     /** Block = "{" BlockStatements "}"
2845      */
2846     JCBlock block(int pos, long flags) {
2847         accept(LBRACE);
2848         ignoreDanglingComments();   // ignore any comments from before the '{'
2849         List<JCStatement> stats = blockStatements();
2850         JCBlock t = F.at(pos).Block(flags, stats);
2851         while (token.kind == CASE || token.kind == DEFAULT) {
2852             syntaxError(token.pos, Errors.Orphaned(token.kind));
2853             switchBlockStatementGroups();
2854         }
2855         // the Block node has a field "bracePos" for first char of last token, which is
2856         // usually but not necessarily the last char of the last token.
2857         t.bracePos = token.pos;
2858         accept(RBRACE);
2859         return toP(t);
2860     }
2861 
2862     public JCBlock block() {
2863         return block(token.pos, 0);
2864     }
2865 
2866     /** BlockStatements = { BlockStatement }
2867      *  BlockStatement  = LocalVariableDeclarationStatement
2868      *                  | ClassOrInterfaceOrEnumDeclaration
2869      *                  | [Ident ":"] Statement
2870      *  LocalVariableDeclarationStatement
2871      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
2872      */
2873     List<JCStatement> blockStatements() {
2874         //todo: skip to anchor on error(?)
2875         int lastErrPos = -1;
2876         ListBuffer<JCStatement> stats = new ListBuffer<>();
2877         while (true) {
2878             List<JCStatement> stat = blockStatement();
2879             ignoreDanglingComments();  // ignore comments not consumed by the statement
2880             if (stat.isEmpty()) {
2881                 return stats.toList();
2882             } else {
2883                 // error recovery
2884                 if (token.pos == lastErrPos)
2885                     return stats.toList();
2886                 if (token.pos <= endPosTable.errorEndPos) {
2887                     skip(false, true, true, true);
2888                     lastErrPos = token.pos;
2889                 }
2890                 stats.addAll(stat);
2891             }
2892         }
2893     }
2894 
2895     /*
2896      * Parse a Statement (JLS 14.5). As an enhancement to improve error recovery,
2897      * this method will also recognize variable and class declarations (which are
2898      * not legal for a Statement) by delegating the parsing to BlockStatement (JLS 14.2).
2899      * If any illegal declarations are found, they will be wrapped in an erroneous tree,
2900      * and an error will be produced by this method.
2901      */
2902     JCStatement parseStatementAsBlock() {
2903         int pos = token.pos;
2904         List<JCStatement> stats = blockStatement();
2905         if (stats.isEmpty()) {
2906             JCErroneous e = syntaxError(pos, Errors.IllegalStartOfStmt);
2907             return toP(F.at(pos).Exec(e));
2908         } else {
2909             JCStatement first = stats.head;
2910             Error error = null;
2911             switch (first.getTag()) {
2912             case CLASSDEF:
2913                 error = Errors.ClassNotAllowed;
2914                 break;
2915             case VARDEF:
2916                 error = Errors.VariableNotAllowed;
2917                 break;
2918             }
2919             if (error != null) {
2920                 log.error(DiagnosticFlag.SYNTAX, first, error);
2921                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
2922                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
2923             }
2924             return first;
2925         }
2926     }
2927 
2928     /**This method parses a statement appearing inside a block.
2929      */
2930     List<JCStatement> blockStatement() {
2931         //todo: skip to anchor on error(?)
2932         Comment dc;
2933         int pos = token.pos;
2934         switch (token.kind) {
2935         case RBRACE: case CASE: case DEFAULT: case EOF:
2936             return List.nil();
2937         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
2938         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
2939         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
2940         case ASSERT:
2941             return List.of(parseSimpleStatement());
2942         case MONKEYS_AT:
2943         case FINAL: {
2944             dc = token.docComment();
2945             JCModifiers mods = modifiersOpt();
2946             if (isDeclaration()) {
2947                 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
2948             } else {
2949                 JCExpression t = parseType(true);
2950                 return localVariableDeclarations(mods, t, dc);
2951             }
2952         }
2953         case ABSTRACT: case STRICTFP: {
2954             dc = token.docComment();
2955             JCModifiers mods = modifiersOpt();
2956             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
2957         }
2958         case INTERFACE:
2959         case CLASS:
2960             dc = token.docComment();
2961             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2962         case ENUM:
2963             if (!allowRecords) {
2964                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum);
2965             }
2966             dc = token.docComment();
2967             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2968         case IDENTIFIER:
2969             if (token.name() == names.yield && allowYieldStatement) {
2970                 Token next = S.token(1);
2971                 boolean isYieldStatement;
2972                 switch (next.kind) {
2973                     case PLUS: case SUB: case STRINGLITERAL: case CHARLITERAL:
2974                     case STRINGFRAGMENT:
2975                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
2976                     case NULL: case IDENTIFIER: case UNDERSCORE: case TRUE: case FALSE:
2977                     case NEW: case SWITCH: case THIS: case SUPER:
2978                     case BYTE, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, VOID, BOOLEAN:
2979                         isYieldStatement = true;
2980                         break;
2981                     case PLUSPLUS: case SUBSUB:
2982                         isYieldStatement = S.token(2).kind != SEMI;
2983                         break;
2984                     case BANG: case TILDE:
2985                         isYieldStatement = S.token(1).kind != SEMI;
2986                         break;
2987                     case LPAREN:
2988                         int lookahead = 2;
2989                         int balance = 1;
2990                         boolean hasComma = false;
2991                         boolean inTypeArgs = false;
2992                         Token l;
2993                         while ((l = S.token(lookahead)).kind != EOF && balance != 0) {
2994                             switch (l.kind) {
2995                                 case LPAREN: balance++; break;
2996                                 case RPAREN: balance--; break;
2997                                 case COMMA: if (balance == 1 && !inTypeArgs) hasComma = true; break;
2998                                 case LT: inTypeArgs = true; break;
2999                                 case GT: inTypeArgs = false;
3000                             }
3001                             lookahead++;
3002                         }
3003                         isYieldStatement = (!hasComma && lookahead != 3) || l.kind == ARROW;
3004                         break;
3005                     case SEMI: //error recovery - this is not a valid statement:
3006                         isYieldStatement = true;
3007                         break;
3008                     default:
3009                         isYieldStatement = false;
3010                         break;
3011                 }
3012 
3013                 if (isYieldStatement) {
3014                     nextToken();
3015                     JCExpression t = term(EXPR);
3016                     accept(SEMI);
3017                     return List.of(toP(F.at(pos).Yield(t)));
3018                 }
3019 
3020                 //else intentional fall-through
3021             } else {
3022                 if (isNonSealedClassStart(true)) {
3023                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3024                     nextToken();
3025                     nextToken();
3026                     nextToken();
3027                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3028                 } else if (isSealedClassStart(true)) {
3029                     checkSourceLevel(Feature.SEALED_CLASSES);
3030                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3031                     nextToken();
3032                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3033                 }
3034             }
3035         }
3036         if ((isValueModifier()) && allowValueClasses) {
3037             checkSourceLevel(Feature.VALUE_CLASSES);
3038             dc = token.docComment();
3039             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
3040         }
3041         dc = token.docComment();
3042         if (isRecordStart() && allowRecords) {
3043             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3044         } else {
3045             Token prevToken = token;
3046             JCExpression t = term(EXPR | TYPE);
3047             if (token.kind == COLON && t.hasTag(IDENT)) {
3048                 nextToken();
3049                 JCStatement stat = parseStatementAsBlock();
3050                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3051             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3052                 pos = token.pos;
3053                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3054                 F.at(pos);
3055                 return localVariableDeclarations(mods, t, dc);
3056             } else {
3057                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3058                 t = checkExprStat(t);
3059                 accept(SEMI);
3060                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3061                 return List.of(expr);
3062             }
3063         }
3064     }
3065     //where
3066         private List<JCStatement> localVariableDeclarations(JCModifiers mods, JCExpression type, Comment dc) {
3067             if (dc != null) {
3068                 // ignore a well-placed doc comment, but save any misplaced ones
3069                 saveDanglingDocComments(dc);
3070             }
3071             ListBuffer<JCStatement> stats =
3072                     variableDeclarators(mods, type, new ListBuffer<>(), true);
3073             // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
3074             accept(SEMI);
3075             storeEnd(stats.last(), S.prevToken().endPos);
3076             return stats.toList();
3077         }
3078 
3079     /** Statement =
3080      *       Block
3081      *     | IF ParExpression Statement [ELSE Statement]
3082      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
3083      *     | FOR "(" FormalParameter : Expression ")" Statement
3084      *     | WHILE ParExpression Statement
3085      *     | DO Statement WHILE ParExpression ";"
3086      *     | TRY Block ( Catches | [Catches] FinallyPart )
3087      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
3088      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
3089      *     | SYNCHRONIZED ParExpression Block
3090      *     | RETURN [Expression] ";"
3091      *     | THROW Expression ";"
3092      *     | BREAK [Ident] ";"
3093      *     | CONTINUE [Ident] ";"
3094      *     | ASSERT Expression [ ":" Expression ] ";"
3095      *     | ";"
3096      */
3097     public JCStatement parseSimpleStatement() {
3098         ignoreDanglingComments(); // ignore comments before statement
3099         int pos = token.pos;
3100         switch (token.kind) {
3101         case LBRACE:
3102             return block();
3103         case IF: {
3104             nextToken();
3105             JCExpression cond = parExpression();
3106             JCStatement thenpart = parseStatementAsBlock();
3107             JCStatement elsepart = null;
3108             if (token.kind == ELSE) {
3109                 nextToken();
3110                 elsepart = parseStatementAsBlock();
3111             }
3112             return F.at(pos).If(cond, thenpart, elsepart);
3113         }
3114         case FOR: {
3115             nextToken();
3116             accept(LPAREN);
3117             List<JCStatement> inits = token.kind == SEMI ? List.nil() : forInit();
3118             if (inits.length() == 1 &&
3119                 inits.head.hasTag(VARDEF) &&
3120                 ((JCVariableDecl) inits.head).init == null &&
3121                 token.kind == COLON) {
3122                 JCVariableDecl var = (JCVariableDecl)inits.head;
3123                 accept(COLON);
3124                 JCExpression expr = parseExpression();
3125                 accept(RPAREN);
3126                 JCStatement body = parseStatementAsBlock();
3127                 return F.at(pos).ForeachLoop(var, expr, body);
3128             } else {
3129                 accept(SEMI);
3130                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
3131                 accept(SEMI);
3132                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.nil() : forUpdate();
3133                 accept(RPAREN);
3134                 JCStatement body = parseStatementAsBlock();
3135                 return F.at(pos).ForLoop(inits, cond, steps, body);
3136             }
3137         }
3138         case WHILE: {
3139             nextToken();
3140             JCExpression cond = parExpression();
3141             JCStatement body = parseStatementAsBlock();
3142             return F.at(pos).WhileLoop(cond, body);
3143         }
3144         case DO: {
3145             nextToken();
3146             JCStatement body = parseStatementAsBlock();
3147             accept(WHILE);
3148             JCExpression cond = parExpression();
3149             accept(SEMI);
3150             JCDoWhileLoop t = toP(F.at(pos).DoLoop(body, cond));
3151             return t;
3152         }
3153         case TRY: {
3154             nextToken();
3155             List<JCTree> resources = List.nil();
3156             if (token.kind == LPAREN) {
3157                 nextToken();
3158                 resources = resources();
3159                 accept(RPAREN);
3160             }
3161             JCBlock body = block();
3162             ListBuffer<JCCatch> catchers = new ListBuffer<>();
3163             JCBlock finalizer = null;
3164             if (token.kind == CATCH || token.kind == FINALLY) {
3165                 while (token.kind == CATCH) catchers.append(catchClause());
3166                 if (token.kind == FINALLY) {
3167                     nextToken();
3168                     finalizer = block();
3169                 }
3170             } else {
3171                 if (resources.isEmpty()) {
3172                     log.error(DiagnosticFlag.SYNTAX, pos, Errors.TryWithoutCatchFinallyOrResourceDecls);
3173                 }
3174             }
3175             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
3176         }
3177         case SWITCH: {
3178             nextToken();
3179             JCExpression selector = parExpression();
3180             accept(LBRACE);
3181             List<JCCase> cases = switchBlockStatementGroups();
3182             JCSwitch t = to(F.at(pos).Switch(selector, cases));
3183             t.bracePos = token.endPos;
3184             accept(RBRACE);
3185             return t;
3186         }
3187         case SYNCHRONIZED: {
3188             nextToken();
3189             JCExpression lock = parExpression();
3190             JCBlock body = block();
3191             return F.at(pos).Synchronized(lock, body);
3192         }
3193         case RETURN: {
3194             nextToken();
3195             JCExpression result = token.kind == SEMI ? null : parseExpression();
3196             accept(SEMI);
3197             JCReturn t = toP(F.at(pos).Return(result));
3198             return t;
3199         }
3200         case THROW: {
3201             nextToken();
3202             JCExpression exc = parseExpression();
3203             accept(SEMI);
3204             JCThrow t = toP(F.at(pos).Throw(exc));
3205             return t;
3206         }
3207         case BREAK: {
3208             nextToken();
3209             Name label = LAX_IDENTIFIER.test(token.kind) ? ident() : null;
3210             accept(SEMI);
3211             JCBreak t = toP(F.at(pos).Break(label));
3212             return t;
3213         }
3214         case CONTINUE: {
3215             nextToken();
3216             Name label = LAX_IDENTIFIER.test(token.kind) ? ident() : null;
3217             accept(SEMI);
3218             JCContinue t =  toP(F.at(pos).Continue(label));
3219             return t;
3220         }
3221         case SEMI:
3222             nextToken();
3223             return toP(F.at(pos).Skip());
3224         case ELSE:
3225             int elsePos = token.pos;
3226             nextToken();
3227             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.ElseWithoutIf);
3228         case FINALLY:
3229             int finallyPos = token.pos;
3230             nextToken();
3231             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.FinallyWithoutTry);
3232         case CATCH:
3233             return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, Errors.CatchWithoutTry);
3234         case ASSERT: {
3235             nextToken();
3236             JCExpression assertion = parseExpression();
3237             JCExpression message = null;
3238             if (token.kind == COLON) {
3239                 nextToken();
3240                 message = parseExpression();
3241             }
3242             accept(SEMI);
3243             JCAssert t = toP(F.at(pos).Assert(assertion, message));
3244             return t;
3245         }
3246         default:
3247             Assert.error();
3248             return null;
3249         }
3250     }
3251 
3252     @Override
3253     public JCStatement parseStatement() {
3254         return parseStatementAsBlock();
3255     }
3256 
3257     private JCStatement doRecover(int startPos, ErrorRecoveryAction action, Error errorKey) {
3258         int errPos = S.errPos();
3259         JCTree stm = action.doRecover(this);
3260         S.errPos(errPos);
3261         return toP(F.Exec(syntaxError(startPos, List.of(stm), errorKey)));
3262     }
3263 
3264     /** CatchClause     = CATCH "(" FormalParameter ")" Block
3265      * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below.
3266      */
3267     protected JCCatch catchClause() {
3268         int pos = token.pos;
3269         accept(CATCH);
3270         accept(LPAREN);
3271         JCModifiers mods = optFinal(Flags.PARAMETER);
3272         List<JCExpression> catchTypes = catchTypes();
3273         JCExpression paramType = catchTypes.size() > 1 ?
3274                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
3275                 catchTypes.head;
3276         JCVariableDecl formal = variableDeclaratorId(mods, paramType, true, false, false);
3277         accept(RPAREN);
3278         JCBlock body = block();
3279         return F.at(pos).Catch(formal, body);
3280     }
3281 
3282     List<JCExpression> catchTypes() {
3283         ListBuffer<JCExpression> catchTypes = new ListBuffer<>();
3284         catchTypes.add(parseType());
3285         while (token.kind == BAR) {
3286             nextToken();
3287             // Instead of qualident this is now parseType.
3288             // But would that allow too much, e.g. arrays or generics?
3289             catchTypes.add(parseType());
3290         }
3291         return catchTypes.toList();
3292     }
3293 
3294     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
3295      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
3296      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
3297      */
3298     List<JCCase> switchBlockStatementGroups() {
3299         ListBuffer<JCCase> cases = new ListBuffer<>();
3300         while (true) {
3301             int pos = token.pos;
3302             switch (token.kind) {
3303             case CASE:
3304             case DEFAULT:
3305                 cases.appendList(switchBlockStatementGroup());
3306                 break;
3307             case RBRACE: case EOF:
3308                 return cases.toList();
3309             default:
3310                 nextToken(); // to ensure progress
3311                 syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
3312             }
3313         }
3314     }
3315 
3316     protected List<JCCase> switchBlockStatementGroup() {
3317         int pos = token.pos;
3318         List<JCStatement> stats;
3319         JCCase c;
3320         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
3321         switch (token.kind) {
3322         case CASE: {
3323             nextToken();
3324             ListBuffer<JCCaseLabel> pats = new ListBuffer<>();
3325             boolean allowDefault = false;
3326             while (true) {
3327                 JCCaseLabel label = parseCaseLabel(allowDefault);
3328                 pats.append(label);
3329                 if (token.kind != COMMA) break;
3330                 nextToken();
3331                 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
3332                 allowDefault = TreeInfo.isNullCaseLabel(label);
3333             };
3334             JCExpression guard = parseGuard(pats.last());
3335             CaseTree.CaseKind caseKind;
3336             JCTree body = null;
3337             if (token.kind == ARROW) {
3338                 checkSourceLevel(Feature.SWITCH_RULE);
3339                 accept(ARROW);
3340                 caseKind = JCCase.RULE;
3341                 JCStatement statement = parseStatementAsBlock();
3342                 if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
3343                     log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
3344                 }
3345                 stats = List.of(statement);
3346                 body = stats.head;
3347             } else {
3348                 accept(COLON, tk -> Errors.Expected2(COLON, ARROW));
3349                 caseKind = JCCase.STATEMENT;
3350                 stats = blockStatements();
3351             }
3352             c = F.at(pos).Case(caseKind, pats.toList(), guard, stats, body);
3353             if (stats.isEmpty())
3354                 storeEnd(c, S.prevToken().endPos);
3355             return cases.append(c).toList();
3356         }
3357         case DEFAULT: {
3358             nextToken();
3359             JCCaseLabel defaultPattern = toP(F.at(pos).DefaultCaseLabel());
3360             JCExpression guard = parseGuard(defaultPattern);
3361             CaseTree.CaseKind caseKind;
3362             JCTree body = null;
3363             if (token.kind == ARROW) {
3364                 checkSourceLevel(Feature.SWITCH_RULE);
3365                 accept(ARROW);
3366                 caseKind = JCCase.RULE;
3367                 JCStatement statement = parseStatementAsBlock();
3368                 if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
3369                     log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
3370                 }
3371                 stats = List.of(statement);
3372                 body = stats.head;
3373             } else {
3374                 accept(COLON, tk -> Errors.Expected2(COLON, ARROW));
3375                 caseKind = JCCase.STATEMENT;
3376                 stats = blockStatements();
3377             }
3378             c = F.at(pos).Case(caseKind, List.of(defaultPattern), guard, stats, body);
3379             if (stats.isEmpty())
3380                 storeEnd(c, S.prevToken().endPos);
3381             return cases.append(c).toList();
3382         }
3383         }
3384         throw new AssertionError("should not reach here");
3385     }
3386 
3387     private JCCaseLabel parseCaseLabel(boolean allowDefault) {
3388         int patternPos = token.pos;
3389         JCCaseLabel label;
3390 
3391         if (token.kind == DEFAULT) {
3392             checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
3393             if (!allowDefault) {
3394                 reportSyntaxError(new SimpleDiagnosticPosition(token.pos),
3395                                   Errors.DefaultLabelNotAllowed);
3396             }
3397             nextToken();
3398             label = toP(F.at(patternPos).DefaultCaseLabel());
3399         } else {
3400             JCModifiers mods = optFinal(0);
3401             boolean pattern = mods.flags != 0 || mods.annotations.nonEmpty() ||
3402                               analyzePattern(0) == PatternResult.PATTERN;
3403             if (pattern) {
3404                 checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
3405                 JCPattern p = parsePattern(patternPos, mods, null, false, true);
3406                 return toP(F.at(patternPos).PatternCaseLabel(p));
3407             } else {
3408                 JCExpression expr = term(EXPR | NOLAMBDA);
3409                 return toP(F.at(patternPos).ConstantCaseLabel(expr));
3410             }
3411         }
3412 
3413         return label;
3414     }
3415 
3416     private JCExpression parseGuard(JCCaseLabel label) {
3417         JCExpression guard = null;
3418 
3419         if (token.kind == IDENTIFIER && token.name() == names.when) {
3420             int pos = token.pos;
3421 
3422             nextToken();
3423             guard = term(EXPR | NOLAMBDA);
3424 
3425             if (!(label instanceof JCPatternCaseLabel)) {
3426                 guard = syntaxError(pos, List.of(guard), Errors.GuardNotAllowed);
3427             }
3428         }
3429 
3430         return guard;
3431     }
3432     @SuppressWarnings("fallthrough")
3433     PatternResult analyzePattern(int lookahead) {
3434         int typeDepth = 0;
3435         int parenDepth = 0;
3436         PatternResult pendingResult = PatternResult.EXPRESSION;
3437         while (true) {
3438             TokenKind token = S.token(lookahead).kind;
3439             switch (token) {
3440                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
3441                 case DOUBLE: case BOOLEAN: case CHAR: case VOID:
3442                 case ASSERT, ENUM, IDENTIFIER:
3443                     if (typeDepth == 0 && peekToken(lookahead, LAX_IDENTIFIER)) {
3444                         if (parenDepth == 0) {
3445                             return PatternResult.PATTERN;
3446                         } else {
3447                             pendingResult = PatternResult.PATTERN;
3448                         }
3449                     } else if (typeDepth == 0 && parenDepth == 0 && (peekToken(lookahead, tk -> tk == ARROW || tk == COMMA))) {
3450                         return PatternResult.EXPRESSION;
3451                     }
3452                     break;
3453                 case UNDERSCORE:
3454                     // TODO: REFACTOR to remove the code duplication
3455                     if (typeDepth == 0 && peekToken(lookahead, tk -> tk == RPAREN || tk == COMMA)) {
3456                         return PatternResult.PATTERN;
3457                     } else if (typeDepth == 0 && peekToken(lookahead, LAX_IDENTIFIER)) {
3458                         if (parenDepth == 0) {
3459                             return PatternResult.PATTERN;
3460                         } else {
3461                             pendingResult = PatternResult.PATTERN;
3462                         }
3463                     }
3464                     break;
3465                 case DOT, QUES, EXTENDS, SUPER, COMMA: break;
3466                 case LT: typeDepth++; break;
3467                 case GTGTGT: typeDepth--;
3468                 case GTGT: typeDepth--;
3469                 case GT:
3470                     typeDepth--;
3471                     if (typeDepth == 0 && !peekToken(lookahead, DOT)) {
3472                          return peekToken(lookahead, LAX_IDENTIFIER) ||
3473                                 peekToken(lookahead, tk -> tk == LPAREN) ? PatternResult.PATTERN
3474                                                                          : PatternResult.EXPRESSION;
3475                     } else if (typeDepth < 0) return PatternResult.EXPRESSION;
3476                     break;
3477                 case MONKEYS_AT:
3478                     lookahead = skipAnnotation(lookahead);
3479                     break;
3480                 case LBRACKET:
3481                     if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
3482                         return PatternResult.PATTERN;
3483                     } else if (peekToken(lookahead, RBRACKET)) {
3484                         lookahead++;
3485                         break;
3486                     } else {
3487                         // This is a potential guard, if we are already in a pattern
3488                         return pendingResult;
3489                     }
3490                 case LPAREN:
3491                     if (S.token(lookahead + 1).kind == RPAREN) {
3492                         return parenDepth != 0 && S.token(lookahead + 2).kind == ARROW
3493                                 ? PatternResult.EXPRESSION
3494                                 : PatternResult.PATTERN;
3495                     }
3496                     parenDepth++; break;
3497                 case RPAREN:
3498                     parenDepth--;
3499                     if (parenDepth == 0 &&
3500                         typeDepth == 0 &&
3501                         peekToken(lookahead, TokenKind.IDENTIFIER) &&
3502                         S.token(lookahead + 1).name() == names.when) {
3503                         return PatternResult.PATTERN;
3504                     }
3505                     break;
3506                 case ARROW: return parenDepth > 0 ? PatternResult.EXPRESSION
3507                                                    : pendingResult;
3508                 case FINAL:
3509                     if (parenDepth > 0) return PatternResult.PATTERN;
3510                 default: return pendingResult;
3511             }
3512             lookahead++;
3513         }
3514     }
3515 
3516     private enum PatternResult {
3517         EXPRESSION,
3518         PATTERN;
3519     }
3520 
3521     /** MoreStatementExpressions = { COMMA StatementExpression }
3522      */
3523     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
3524                                                                     JCExpression first,
3525                                                                     T stats) {
3526         // This Exec is a "StatementExpression"; it subsumes no terminating token
3527         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
3528         while (token.kind == COMMA) {
3529             nextToken();
3530             pos = token.pos;
3531             JCExpression t = parseExpression();
3532             // This Exec is a "StatementExpression"; it subsumes no terminating token
3533             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
3534         }
3535         return stats;
3536     }
3537 
3538     /** ForInit = StatementExpression MoreStatementExpressions
3539      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
3540      */
3541     List<JCStatement> forInit() {
3542         ListBuffer<JCStatement> stats = new ListBuffer<>();
3543         int pos = token.pos;
3544         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3545             return variableDeclarators(optFinal(0), parseType(true), stats, true).toList();
3546         } else {
3547             JCExpression t = term(EXPR | TYPE);
3548             if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3549                 return variableDeclarators(modifiersOpt(), t, stats, true).toList();
3550             } else if (wasTypeMode() && token.kind == COLON) {
3551                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.BadInitializer("for-loop"));
3552                 return List.of((JCStatement)F.at(pos).VarDef(modifiersOpt(), names.error, t, null));
3553             } else {
3554                 return moreStatementExpressions(pos, t, stats).toList();
3555             }
3556         }
3557     }
3558 
3559     /** ForUpdate = StatementExpression MoreStatementExpressions
3560      */
3561     List<JCExpressionStatement> forUpdate() {
3562         return moreStatementExpressions(token.pos,
3563                                         parseExpression(),
3564                                         new ListBuffer<JCExpressionStatement>()).toList();
3565     }
3566 
3567     /** AnnotationsOpt = { '@' Annotation }
3568      *
3569      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3570      */
3571     protected List<JCAnnotation> annotationsOpt(Tag kind) {
3572         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
3573         ListBuffer<JCAnnotation> buf = new ListBuffer<>();
3574         int prevmode = mode;
3575         while (token.kind == MONKEYS_AT) {
3576             int pos = token.pos;
3577             nextToken();
3578             buf.append(annotation(pos, kind));
3579         }
3580         setLastMode(mode);
3581         setMode(prevmode);
3582         List<JCAnnotation> annotations = buf.toList();
3583 
3584         return annotations;
3585     }
3586 
3587     List<JCAnnotation> typeAnnotationsOpt() {
3588         List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION);
3589         return annotations;
3590     }
3591 
3592     /** ModifiersOpt = { Modifier }
3593      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
3594      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
3595      *           | "@" Annotation
3596      */
3597     protected JCModifiers modifiersOpt() {
3598         return modifiersOpt(null);
3599     }
3600     protected JCModifiers modifiersOpt(JCModifiers partial) {
3601         long flags;
3602         ListBuffer<JCAnnotation> annotations = new ListBuffer<>();
3603         int pos;
3604         if (partial == null) {
3605             flags = 0;
3606             pos = token.pos;
3607         } else {
3608             flags = partial.flags;
3609             annotations.appendList(partial.annotations);
3610             pos = partial.pos;
3611         }
3612         if (token.deprecatedFlag()) {
3613             flags |= Flags.DEPRECATED;
3614         }
3615         int lastPos;
3616     loop:
3617         while (true) {
3618             long flag;
3619             switch (token.kind) {
3620             case PRIVATE     : flag = Flags.PRIVATE; break;
3621             case PROTECTED   : flag = Flags.PROTECTED; break;
3622             case PUBLIC      : flag = Flags.PUBLIC; break;
3623             case STATIC      : flag = Flags.STATIC; break;
3624             case TRANSIENT   : flag = Flags.TRANSIENT; break;
3625             case FINAL       : flag = Flags.FINAL; break;
3626             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3627             case NATIVE      : flag = Flags.NATIVE; break;
3628             case VOLATILE    : flag = Flags.VOLATILE; break;
3629             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3630             case STRICTFP    : flag = Flags.STRICTFP; break;
3631             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3632             case DEFAULT     : flag = Flags.DEFAULT; break;
3633             case ERROR       : flag = 0; nextToken(); break;
3634             case IDENTIFIER  : {
3635                 if (isNonSealedClassStart(false)) {
3636                     flag = Flags.NON_SEALED;
3637                     nextToken();
3638                     nextToken();
3639                     break;
3640                 }
3641                 if (isSealedClassStart(false)) {
3642                     checkSourceLevel(Feature.SEALED_CLASSES);
3643                     flag = Flags.SEALED;
3644                     break;
3645                 }
3646                 if (isValueModifier()) {
3647                     checkSourceLevel(Feature.VALUE_CLASSES);
3648                     flag = Flags.VALUE_CLASS;
3649                     break;
3650                 }
3651                 break loop;
3652             }
3653             default: break loop;
3654             }
3655             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3656             lastPos = token.pos;
3657             nextToken();
3658             if (flag == Flags.ANNOTATION) {
3659                 if (token.kind != INTERFACE) {
3660                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3661                     // if first modifier is an annotation, set pos to annotation's.
3662                     if (flags == 0 && annotations.isEmpty())
3663                         pos = ann.pos;
3664                     annotations.append(ann);
3665                     flag = 0;
3666                 }
3667             }
3668             flags |= flag;
3669         }
3670         switch (token.kind) {
3671         case ENUM: flags |= Flags.ENUM; break;
3672         case INTERFACE: flags |= Flags.INTERFACE; break;
3673         default: break;
3674         }
3675 
3676         /* A modifiers tree with no modifier tokens or annotations
3677          * has no text position. */
3678         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
3679             pos = Position.NOPOS;
3680 
3681         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
3682         if (pos != Position.NOPOS)
3683             storeEnd(mods, S.prevToken().endPos);
3684         return mods;
3685     }
3686 
3687     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
3688      *
3689      * @param pos position of "@" token
3690      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3691      */
3692     JCAnnotation annotation(int pos, Tag kind) {
3693         // accept(AT); // AT consumed by caller
3694         JCTree ident = qualident(false);
3695         List<JCExpression> fieldValues = annotationFieldValuesOpt();
3696         JCAnnotation ann;
3697         if (kind == Tag.ANNOTATION) {
3698             ann = F.at(pos).Annotation(ident, fieldValues);
3699         } else if (kind == Tag.TYPE_ANNOTATION) {
3700             ann = F.at(pos).TypeAnnotation(ident, fieldValues);
3701         } else {
3702             throw new AssertionError("Unhandled annotation kind: " + kind);
3703         }
3704         return toP(ann);
3705     }
3706 
3707     List<JCExpression> annotationFieldValuesOpt() {
3708         return (token.kind == LPAREN) ? annotationFieldValues() : List.nil();
3709     }
3710 
3711     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
3712     List<JCExpression> annotationFieldValues() {
3713         accept(LPAREN);
3714         ListBuffer<JCExpression> buf = new ListBuffer<>();
3715         if (token.kind != RPAREN) {
3716             buf.append(annotationFieldValue());
3717             while (token.kind == COMMA) {
3718                 nextToken();
3719                 buf.append(annotationFieldValue());
3720             }
3721         }
3722         accept(RPAREN);
3723         return buf.toList();
3724     }
3725 
3726     /** AnnotationFieldValue    = AnnotationValue
3727      *                          | Identifier "=" AnnotationValue
3728      */
3729     JCExpression annotationFieldValue() {
3730         if (LAX_IDENTIFIER.test(token.kind)) {
3731             selectExprMode();
3732             JCExpression t1 = term1();
3733             if (t1.hasTag(IDENT) && token.kind == EQ) {
3734                 int pos = token.pos;
3735                 accept(EQ);
3736                 JCExpression v = annotationValue();
3737                 return toP(F.at(pos).Assign(t1, v));
3738             } else {
3739                 return t1;
3740             }
3741         }
3742         return annotationValue();
3743     }
3744 
3745     /* AnnotationValue          = ConditionalExpression
3746      *                          | Annotation
3747      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
3748      */
3749     JCExpression annotationValue() {
3750         int pos;
3751         switch (token.kind) {
3752         case MONKEYS_AT:
3753             pos = token.pos;
3754             nextToken();
3755             return annotation(pos, Tag.ANNOTATION);
3756         case LBRACE:
3757             pos = token.pos;
3758             accept(LBRACE);
3759             ListBuffer<JCExpression> buf = new ListBuffer<>();
3760             if (token.kind == COMMA) {
3761                 nextToken();
3762             } else if (token.kind != RBRACE) {
3763                 buf.append(annotationValue());
3764                 while (token.kind == COMMA) {
3765                     nextToken();
3766                     if (token.kind == RBRACE) break;
3767                     buf.append(annotationValue());
3768                 }
3769             }
3770             accept(RBRACE, tk -> Errors.AnnotationMissingElementValue);
3771             return toP(F.at(pos).NewArray(null, List.nil(), buf.toList()));
3772         default:
3773             selectExprMode();
3774             return term1();
3775         }
3776     }
3777 
3778     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
3779      */
3780     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
3781                                                                          JCExpression type,
3782                                                                          T vdefs,
3783                                                                          boolean localDecl)
3784     {
3785         return variableDeclaratorsRest(token.pos, mods, type, identOrUnderscore(), false, null, vdefs, localDecl);
3786     }
3787 
3788     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
3789      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
3790      *
3791      *  @param reqInit  Is an initializer always required?
3792      *  @param dc       The documentation comment for the variable declarations, or null.
3793      */
3794     protected <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
3795                                                                      JCModifiers mods,
3796                                                                      JCExpression type,
3797                                                                      Name name,
3798                                                                      boolean reqInit,
3799                                                                      Comment dc,
3800                                                                      T vdefs,
3801                                                                      boolean localDecl)
3802     {
3803         JCVariableDecl head = variableDeclaratorRest(pos, mods, type, name, reqInit, dc, localDecl, false);
3804         vdefs.append(head);
3805         while (token.kind == COMMA) {
3806             // All but last of multiple declarators subsume a comma
3807             storeEnd((JCTree)vdefs.last(), token.endPos);
3808             nextToken();
3809             vdefs.append(variableDeclarator(mods, type, reqInit, dc, localDecl));
3810         }
3811         return vdefs;
3812     }
3813 
3814     /** VariableDeclarator = Ident VariableDeclaratorRest
3815      *  ConstantDeclarator = Ident ConstantDeclaratorRest
3816      */
3817     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc, boolean localDecl) {
3818         return variableDeclaratorRest(token.pos, mods, type, identOrUnderscore(), reqInit, dc, localDecl, true);
3819     }
3820 
3821     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
3822      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
3823      *
3824      *  @param reqInit  Is an initializer always required?
3825      *  @param dc       The documentation comment for the variable declarations, or null.
3826      */
3827     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
3828                                   boolean reqInit, Comment dc, boolean localDecl, boolean compound) {
3829         boolean declaredUsingVar = false;
3830         JCExpression init = null;
3831         type = bracketsOpt(type);
3832 
3833         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
3834             if (!localDecl) {
3835                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.UseOfUnderscoreNotAllowed);
3836             }
3837             name = names.empty;
3838         }
3839 
3840         saveDanglingDocComments(dc);
3841 
3842         if (token.kind == EQ) {
3843             nextToken();
3844             init = variableInitializer();
3845         }
3846         else if (reqInit) syntaxError(token.pos, Errors.Expected(EQ));
3847 
3848         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.empty
3849                 && localDecl
3850                 && init == null
3851                 && token.kind != COLON) { // if its unnamed local variable, it needs to have an init unless in enhanced-for
3852             syntaxError(token.pos, Errors.Expected(EQ));
3853         }
3854 
3855         int startPos = Position.NOPOS;
3856         JCTree elemType = TreeInfo.innermostType(type, true);
3857         if (elemType.hasTag(IDENT)) {
3858             Name typeName = ((JCIdent) elemType).name;
3859             if (restrictedTypeNameStartingAtSource(typeName, pos, !compound && localDecl) != null) {
3860                 if (typeName != names.var) {
3861                     reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedHere(typeName));
3862                 } else if (type.hasTag(TYPEARRAY) && !compound) {
3863                     //error - 'var' and arrays
3864                     reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedArray(typeName));
3865                 } else {
3866                     declaredUsingVar = true;
3867                     if (compound)
3868                         //error - 'var' in compound local var decl
3869                         reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
3870                     startPos = TreeInfo.getStartPos(mods);
3871                     if (startPos == Position.NOPOS)
3872                         startPos = TreeInfo.getStartPos(type);
3873                     //implicit type
3874                     type = null;
3875                 }
3876             }
3877         }
3878         JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init, declaredUsingVar));
3879         result.startPos = startPos;
3880         return attach(result, dc);
3881     }
3882 
3883     Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
3884         switch (e.getTag()) {
3885             case IDENT:
3886                 return restrictedTypeNameStartingAtSource(((JCIdent)e).name, e.pos, shouldWarn) != null ? ((JCIdent)e).name : null;
3887             case TYPEARRAY:
3888                 return restrictedTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
3889             default:
3890                 return null;
3891         }
3892     }
3893 
3894     Source restrictedTypeNameStartingAtSource(Name name, int pos, boolean shouldWarn) {
3895         if (name == names.var) {
3896             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3897                 return Source.JDK10;
3898             } else if (shouldWarn) {
3899                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3900             }
3901         }
3902         if (name == names.yield) {
3903             if (allowYieldStatement) {
3904                 return Source.JDK14;
3905             } else if (shouldWarn) {
3906                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3907             }
3908         }
3909         if (name == names.record) {
3910             if (allowRecords) {
3911                 return Source.JDK14;
3912             } else if (shouldWarn) {
3913                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3914             }
3915         }
3916         if (name == names.value) {
3917             if (allowValueClasses) {
3918                 return Source.JDK23;
3919             } else if (shouldWarn) {
3920                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3921             }
3922         }
3923         if (name == names.sealed) {
3924             if (allowSealedTypes) {
3925                 return Source.JDK15;
3926             } else if (shouldWarn) {
3927                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3928             }
3929         }
3930         if (name == names.permits) {
3931             if (allowSealedTypes) {
3932                 return Source.JDK15;
3933             } else if (shouldWarn) {
3934                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3935             }
3936         }
3937         return null;
3938     }
3939 
3940     /** VariableDeclaratorId = Ident BracketsOpt
3941      */
3942     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
3943         int pos = token.pos;
3944         Name name;
3945         if (allowThisIdent ||
3946             !lambdaParameter ||
3947             LAX_IDENTIFIER.test(token.kind) ||
3948             mods.flags != Flags.PARAMETER ||
3949             mods.annotations.nonEmpty()) {
3950             JCExpression pn;
3951             if (token.kind == UNDERSCORE && (catchParameter || lambdaParameter)) {
3952                 pn = toP(F.at(token.pos).Ident(identOrUnderscore()));
3953             } else {
3954                 pn = qualident(false);
3955             }
3956             if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
3957                 name = ((JCIdent)pn).name;
3958             } else if (lambdaParameter && type == null) {
3959                 // we have a lambda parameter that is not an identifier this is a syntax error
3960                 type = pn;
3961                 name = names.empty;
3962                 reportSyntaxError(pos, Errors.Expected(IDENTIFIER));
3963             } else {
3964                 if (allowThisIdent) {
3965                     if ((mods.flags & Flags.VARARGS) != 0) {
3966                         log.error(token.pos, Errors.VarargsAndReceiver);
3967                     }
3968                     if (token.kind == LBRACKET) {
3969                         log.error(token.pos, Errors.ArrayAndReceiver);
3970                     }
3971                     if (pn.hasTag(Tag.SELECT) && ((JCFieldAccess)pn).name != names._this) {
3972                         log.error(token.pos, Errors.WrongReceiver);
3973                     }
3974                 }
3975                 return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
3976             }
3977         } else {
3978             /** if it is a lambda parameter and the token kind is not an identifier,
3979              *  and there are no modifiers or annotations, then this means that the compiler
3980              *  supposed the lambda to be explicit but it can contain a mix of implicit,
3981              *  var or explicit parameters. So we assign the error name to the parameter name
3982              *  instead of issuing an error and analyze the lambda parameters as a whole at
3983              *  a higher level.
3984              */
3985             name = names.error;
3986         }
3987         if ((mods.flags & Flags.VARARGS) != 0 &&
3988                 token.kind == LBRACKET) {
3989             log.error(token.pos, Errors.VarargsAndOldArraySyntax);
3990         }
3991         if (recordComponent && token.kind == LBRACKET) {
3992             log.error(token.pos, Errors.RecordComponentAndOldArraySyntax);
3993         }
3994         type = bracketsOpt(type);
3995 
3996         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
3997             name = names.empty;
3998         }
3999 
4000         return toP(F.at(pos).VarDef(mods, name, type, null,
4001                 type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var));
4002     }
4003 
4004     /** Resources = Resource { ";" Resources }
4005      */
4006     List<JCTree> resources() {
4007         ListBuffer<JCTree> defs = new ListBuffer<>();
4008         defs.append(resource());
4009         while (token.kind == SEMI) {
4010             // All but last of multiple declarators must subsume a semicolon
4011             storeEnd(defs.last(), token.endPos);
4012             int semiColonPos = token.pos;
4013             nextToken();
4014             if (token.kind == RPAREN) { // Optional trailing semicolon
4015                                        // after last resource
4016                 break;
4017             }
4018             defs.append(resource());
4019         }
4020         return defs.toList();
4021     }
4022 
4023     /** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression
4024      *           | Expression
4025      */
4026     protected JCTree resource() {
4027         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
4028             JCModifiers mods = optFinal(0);
4029             JCExpression t = parseType(true);
4030             return variableDeclaratorRest(token.pos, mods, t, identOrUnderscore(), true, null, true, false);
4031         }
4032         JCExpression t = term(EXPR | TYPE);
4033         if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
4034             JCModifiers mods = F.Modifiers(0);
4035             return variableDeclaratorRest(token.pos, mods, t, identOrUnderscore(), true, null, true, false);
4036         } else {
4037             checkSourceLevel(Feature.EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES);
4038             if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
4039                 log.error(t.pos(), Errors.TryWithResourcesExprNeedsVar);
4040             }
4041 
4042             return t;
4043         }
4044     }
4045 
4046     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
4047      */
4048     public JCTree.JCCompilationUnit parseCompilationUnit() {
4049         Token firstToken = token;
4050         JCModifiers mods = null;
4051         boolean consumedToplevelDoc = false;
4052         boolean seenImport = false;
4053         boolean seenPackage = false;
4054         ListBuffer<JCTree> defs = new ListBuffer<>();
4055         if (token.kind == MONKEYS_AT)
4056             mods = modifiersOpt();
4057 
4058         if (token.kind == PACKAGE) {
4059             int packagePos = token.pos;
4060             List<JCAnnotation> annotations = List.nil();
4061             seenPackage = true;
4062             if (mods != null) {
4063                 checkNoMods(mods.flags & ~Flags.DEPRECATED);
4064                 annotations = mods.annotations;
4065                 mods = null;
4066             }
4067             nextToken();
4068             JCExpression pid = qualident(false);
4069             accept(SEMI);
4070             JCPackageDecl pd = toP(F.at(packagePos).PackageDecl(annotations, pid));
4071             attach(pd, firstToken.docComment());
4072             consumedToplevelDoc = true;
4073             defs.append(pd);
4074             updateUnexpectedTopLevelDefinitionStartError(true);
4075         }
4076 
4077         boolean firstTypeDecl = true;   // have we seen a class, enum, or interface declaration yet?
4078         boolean isImplicitClass = false;
4079         OUTER: while (token.kind != EOF) {
4080             if (token.pos <= endPosTable.errorEndPos) {
4081                 // error recovery
4082                 skip(firstTypeDecl, false, false, false);
4083                 if (token.kind == EOF)
4084                     break;
4085             }
4086             // JLS 7.3 doesn't allow extra semicolons after package or import declarations,
4087             // but here we try to provide a more helpful error message if we encounter any.
4088             // Do that by slurping in as many semicolons as possible, and then seeing what
4089             // comes after before deciding how best to handle them.
4090             ListBuffer<JCTree> semiList = new ListBuffer<>();
4091             while (firstTypeDecl && mods == null && token.kind == SEMI) {
4092                 int pos = token.pos;
4093                 nextToken();
4094                 semiList.append(toP(F.at(pos).Skip()));
4095                 if (token.kind == EOF)
4096                     break OUTER;
4097             }
4098             if (firstTypeDecl && mods == null && token.kind == IMPORT) {
4099                 if (!semiList.isEmpty()) {
4100                     if (source.compareTo(Source.JDK21) >= 0)
4101                         reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
4102                     else
4103                         log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
4104                 }
4105                 seenImport = true;
4106                 defs.append(importDeclaration());
4107             } else {
4108                 Comment docComment = token.docComment();
4109                 if (firstTypeDecl && !seenImport && !seenPackage) {
4110                     docComment = firstToken.docComment();
4111                     consumedToplevelDoc = true;
4112                 }
4113                 if (mods != null || token.kind != SEMI)
4114                     mods = modifiersOpt(mods);
4115                 if (firstTypeDecl && token.kind == IDENTIFIER) {
4116                     if (!semiList.isEmpty()) {
4117                         if (source.compareTo(Source.JDK21) >= 0)
4118                             reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
4119                         else
4120                             log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
4121                     }
4122                     ModuleKind kind = ModuleKind.STRONG;
4123                     if (token.name() == names.open) {
4124                         kind = ModuleKind.OPEN;
4125                         nextToken();
4126                     }
4127                     if (token.kind == IDENTIFIER && token.name() == names.module) {
4128                         if (mods != null) {
4129                             checkNoMods(mods.flags & ~Flags.DEPRECATED);
4130                         }
4131                         defs.append(moduleDecl(mods, kind, docComment));
4132                         consumedToplevelDoc = true;
4133                         break;
4134                     } else if (kind != ModuleKind.STRONG) {
4135                         reportSyntaxError(token.pos, Errors.ExpectedModule);
4136                     }
4137                 }
4138 
4139                 defs.appendList(semiList.toList());
4140                 boolean isTopLevelMethodOrField = false;
4141 
4142                 // Due to a significant number of existing negative tests
4143                 // this code speculatively tests to see if a top level method
4144                 // or field can parse. If the method or field can parse then
4145                 // it is parsed. Otherwise, parsing continues as though
4146                 // implicitly declared classes did not exist and error reporting
4147                 // is the same as in the past.
4148                 if (!isDeclaration(true)) {
4149                     final JCModifiers finalMods = mods;
4150                     JavacParser speculative = new VirtualParser(this);
4151                     List<JCTree> speculativeResult =
4152                             speculative.topLevelMethodOrFieldDeclaration(finalMods, null);
4153                     if (speculativeResult.head.hasTag(METHODDEF) ||
4154                         speculativeResult.head.hasTag(VARDEF)) {
4155                         isTopLevelMethodOrField = true;
4156                     }
4157                 }
4158 
4159                 if (isTopLevelMethodOrField) {
4160                     checkSourceLevel(token.pos, Feature.IMPLICIT_CLASSES);
4161                     defs.appendList(topLevelMethodOrFieldDeclaration(mods, docComment));
4162                     isImplicitClass = true;
4163                 } else if (isDefiniteStatementStartToken()) {
4164                     int startPos = token.pos;
4165                     List<JCStatement> statements = blockStatement();
4166                     defs.append(syntaxError(startPos,
4167                                             statements,
4168                                             Errors.StatementNotExpected,
4169                                             true));
4170                 } else {
4171                     JCTree def = typeDeclaration(mods, docComment);
4172                     if (def instanceof JCExpressionStatement statement)
4173                         def = statement.expr;
4174                     defs.append(def);
4175                 }
4176 
4177                 mods = null;
4178                 firstTypeDecl = false;
4179             }
4180         }
4181         List<JCTree> topLevelDefs = isImplicitClass ? constructImplicitClass(defs.toList(), S.prevToken().endPos) : defs.toList();
4182         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(topLevelDefs);
4183         if (!consumedToplevelDoc)
4184             attach(toplevel, firstToken.docComment());
4185         if (defs.isEmpty())
4186             storeEnd(toplevel, S.prevToken().endPos);
4187         if (keepDocComments)
4188             toplevel.docComments = docComments;
4189         if (keepLineMap)
4190             toplevel.lineMap = S.getLineMap();
4191         toplevel.endPositions = this.endPosTable;
4192         return toplevel;
4193     }
4194 
4195     // Restructure top level to be an implicitly declared class.
4196     private List<JCTree> constructImplicitClass(List<JCTree> origDefs, int endPos) {
4197         ListBuffer<JCTree> topDefs = new ListBuffer<>();
4198         ListBuffer<JCTree> defs = new ListBuffer<>();
4199 
4200         for (JCTree def : origDefs) {
4201             if (def.hasTag(Tag.PACKAGEDEF)) {
4202                 log.error(def.pos(), Errors.ImplicitClassShouldNotHavePackageDeclaration);
4203             } else if (def.hasTag(Tag.IMPORT) || def.hasTag(Tag.MODULEIMPORT)) {
4204                 topDefs.append(def);
4205             } else if (!def.hasTag(Tag.SKIP)) {
4206                 defs.append(def);
4207             }
4208         }
4209 
4210         int primaryPos = getStartPos(defs.first());
4211         String simplename = PathFileObject.getSimpleName(log.currentSourceFile());
4212 
4213         if (simplename.endsWith(".java")) {
4214             simplename = simplename.substring(0, simplename.length() - ".java".length());
4215         }
4216         if (!SourceVersion.isIdentifier(simplename) || SourceVersion.isKeyword(simplename)) {
4217             log.error(primaryPos, Errors.BadFileName(simplename));
4218         }
4219 
4220         Name name = names.fromString(simplename);
4221         JCModifiers implicitMods = F.at(Position.NOPOS)
4222                 .Modifiers(Flags.FINAL|Flags.IMPLICIT_CLASS, List.nil());
4223         JCClassDecl implicit = F.at(primaryPos).ClassDef(
4224                 implicitMods, name, List.nil(), null, List.nil(), List.nil(),
4225                 defs.toList());
4226         storeEnd(implicit, endPos);
4227         topDefs.append(implicit);
4228         return topDefs.toList();
4229     }
4230 
4231     JCModuleDecl moduleDecl(JCModifiers mods, ModuleKind kind, Comment dc) {
4232         int pos = token.pos;
4233         checkSourceLevel(Feature.MODULES);
4234 
4235         nextToken();
4236         JCExpression name = qualident(false);
4237         List<JCDirective> directives = null;
4238 
4239         accept(LBRACE);
4240         directives = moduleDirectiveList();
4241         accept(RBRACE);
4242         int endPos = S.prevToken().endPos;
4243         accept(EOF);
4244 
4245         JCModuleDecl result = F.at(pos).ModuleDef(mods, kind, name, directives);
4246         storeEnd(result, endPos);
4247         return attach(result, dc);
4248     }
4249 
4250     List<JCDirective> moduleDirectiveList() {
4251         ListBuffer<JCDirective> defs = new ListBuffer<>();
4252         while (token.kind == IDENTIFIER) {
4253             int pos = token.pos;
4254             if (token.name() == names.requires) {
4255                 nextToken();
4256                 boolean isTransitive = false;
4257                 boolean isStaticPhase = false;
4258             loop:
4259                 while (true) {
4260                     switch (token.kind) {
4261                         case IDENTIFIER:
4262                             if (token.name() == names.transitive) {
4263                                 Token t1 = S.token(1);
4264                                 if (t1.kind == SEMI || t1.kind == DOT) {
4265                                     break loop;
4266                                 }
4267                                 if (isTransitive) {
4268                                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
4269                                 }
4270                                 isTransitive = true;
4271                                 break;
4272                             } else {
4273                                 break loop;
4274                             }
4275                         case STATIC:
4276                             if (isStaticPhase) {
4277                                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
4278                             }
4279                             isStaticPhase = true;
4280                             break;
4281                         default:
4282                             break loop;
4283                     }
4284                     nextToken();
4285                 }
4286                 JCExpression moduleName = qualident(false);
4287                 accept(SEMI);
4288                 defs.append(toP(F.at(pos).Requires(isTransitive, isStaticPhase, moduleName)));
4289             } else if (token.name() == names.exports || token.name() == names.opens) {
4290                 boolean exports = token.name() == names.exports;
4291                 nextToken();
4292                 JCExpression pkgName = qualident(false);
4293                 List<JCExpression> moduleNames = null;
4294                 if (token.kind == IDENTIFIER && token.name() == names.to) {
4295                     nextToken();
4296                     moduleNames = qualidentList(false);
4297                 }
4298                 accept(SEMI);
4299                 JCDirective d;
4300                 if (exports) {
4301                     d = F.at(pos).Exports(pkgName, moduleNames);
4302                 } else {
4303                     d = F.at(pos).Opens(pkgName, moduleNames);
4304                 }
4305                 defs.append(toP(d));
4306             } else if (token.name() == names.provides) {
4307                 nextToken();
4308                 JCExpression serviceName = qualident(false);
4309                 List<JCExpression> implNames;
4310                 if (token.kind == IDENTIFIER && token.name() == names.with) {
4311                     nextToken();
4312                     implNames = qualidentList(false);
4313                 } else {
4314                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ExpectedStr("'" + names.with + "'"));
4315                     implNames = List.nil();
4316                 }
4317                 accept(SEMI);
4318                 defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
4319             } else if (token.name() == names.uses) {
4320                 nextToken();
4321                 JCExpression service = qualident(false);
4322                 accept(SEMI);
4323                 defs.append(toP(F.at(pos).Uses(service)));
4324             } else {
4325                 setErrorEndPos(pos);
4326                 reportSyntaxError(pos, Errors.InvalidModuleDirective);
4327                 break;
4328             }
4329         }
4330         return defs.toList();
4331     }
4332 
4333     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
4334      */
4335     protected JCTree importDeclaration() {
4336         int pos = token.pos;
4337         nextToken();
4338         boolean importStatic = false;
4339         if (token.kind == STATIC) {
4340             importStatic = true;
4341             nextToken();
4342         } else if (token.kind == IDENTIFIER && token.name() == names.module &&
4343                    peekToken(TokenKind.IDENTIFIER)) {
4344             checkSourceLevel(Feature.MODULE_IMPORTS);
4345             nextToken();
4346             JCExpression moduleName = qualident(false);
4347             accept(SEMI);
4348             return toP(F.at(pos).ModuleImport(moduleName));
4349         }
4350         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
4351         do {
4352             int pos1 = token.pos;
4353             accept(DOT);
4354             if (token.kind == STAR) {
4355                 pid = to(F.at(pos1).Select(pid, names.asterisk));
4356                 nextToken();
4357                 break;
4358             } else {
4359                 pid = toP(F.at(pos1).Select(pid, ident()));
4360             }
4361         } while (token.kind == DOT);
4362         accept(SEMI);
4363         return toP(F.at(pos).Import((JCFieldAccess)pid, importStatic));
4364     }
4365 
4366     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
4367      *                  | ";"
4368      */
4369     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
4370         int pos = token.pos;
4371         if (mods == null && token.kind == SEMI) {
4372             nextToken();
4373             return toP(F.at(pos).Skip());
4374         } else {
4375             return classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
4376         }
4377     }
4378 
4379     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
4380      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
4381      *  @param mods     Any modifiers starting the class or interface declaration
4382      *  @param dc       The documentation comment for the class, or null.
4383      */
4384     protected JCStatement classOrRecordOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
4385         if (token.kind == CLASS) {
4386             return classDeclaration(mods, dc);
4387         } if (isRecordStart()) {
4388             return recordDeclaration(mods, dc);
4389         } else if (token.kind == INTERFACE) {
4390             return interfaceDeclaration(mods, dc);
4391         } else if (token.kind == ENUM) {
4392             return enumDeclaration(mods, dc);
4393         } else {
4394             int pos = token.pos;
4395             List<JCTree> errs;
4396             if (LAX_IDENTIFIER.test(token.kind)) {
4397                 errs = List.of(mods, toP(F.at(pos).Ident(ident())));
4398                 setErrorEndPos(token.pos);
4399             } else {
4400                 errs = List.of(mods);
4401             }
4402 
4403             return toP(F.Exec(syntaxError(pos, errs, unexpectedTopLevelDefinitionStartError)));
4404 
4405         }
4406     }
4407 
4408     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
4409      *                     [IMPLEMENTS TypeList] ClassBody
4410      *  @param mods    The modifiers starting the class declaration
4411      *  @param dc       The documentation comment for the class, or null.
4412      */
4413     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
4414         int pos = token.pos;
4415         accept(CLASS);
4416         Name name = typeName();
4417 
4418         List<JCTypeParameter> typarams = typeParametersOpt();
4419 
4420         JCExpression extending = null;
4421         if (token.kind == EXTENDS) {
4422             nextToken();
4423             extending = parseType();
4424         }
4425         List<JCExpression> implementing = List.nil();
4426         if (token.kind == IMPLEMENTS) {
4427             nextToken();
4428             implementing = typeList();
4429         }
4430         List<JCExpression> permitting = permitsClause(mods, "class");
4431 
4432         saveDanglingDocComments(dc);
4433 
4434         List<JCTree> defs = classInterfaceOrRecordBody(name, false, false);
4435         JCClassDecl result = toP(F.at(pos).ClassDef(
4436             mods, name, typarams, extending, implementing, permitting, defs));
4437         return attach(result, dc);
4438     }
4439 
4440     protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) {
4441         int pos = token.pos;
4442         nextToken();
4443         mods.flags |= Flags.RECORD;
4444         Name name = typeName();
4445 
4446         List<JCTypeParameter> typarams = typeParametersOpt();
4447 
4448         List<JCVariableDecl> headerFields = formalParameters(false, true);
4449 
4450         List<JCExpression> implementing = List.nil();
4451         if (token.kind == IMPLEMENTS) {
4452             nextToken();
4453             implementing = typeList();
4454         }
4455 
4456         saveDanglingDocComments(dc);
4457 
4458         List<JCTree> defs = classInterfaceOrRecordBody(name, false, true);
4459         java.util.List<JCVariableDecl> fields = new ArrayList<>();
4460         for (JCVariableDecl field : headerFields) {
4461             fields.add(field);
4462         }
4463         for (JCTree def : defs) {
4464             if (def.hasTag(METHODDEF)) {
4465                 JCMethodDecl methDef = (JCMethodDecl) def;
4466                 if (methDef.name == names.init && methDef.params.isEmpty() && (methDef.mods.flags & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0) {
4467                     ListBuffer<JCVariableDecl> tmpParams = new ListBuffer<>();
4468                     for (JCVariableDecl param : headerFields) {
4469                         tmpParams.add(F.at(param)
4470                                 // we will get flags plus annotations from the record component
4471                                 .VarDef(F.Modifiers(Flags.PARAMETER | Flags.GENERATED_MEMBER | Flags.MANDATED | param.mods.flags & Flags.VARARGS,
4472                                         param.mods.annotations),
4473                                 param.name, param.vartype, null));
4474                     }
4475                     methDef.params = tmpParams.toList();
4476                 }
4477             }
4478         }
4479         for (int i = fields.size() - 1; i >= 0; i--) {
4480             JCVariableDecl field = fields.get(i);
4481             defs = defs.prepend(field);
4482         }
4483         JCClassDecl result = toP(F.at(pos).ClassDef(mods, name, typarams, null, implementing, defs));
4484         return attach(result, dc);
4485     }
4486 
4487     Name typeName() {
4488         int pos = token.pos;
4489         Name name = ident();
4490         Source source = restrictedTypeNameStartingAtSource(name, pos, true);
4491         if (source != null) {
4492             reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, source));
4493         }
4494         return name;
4495     }
4496 
4497     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
4498      *                         [EXTENDS TypeList] InterfaceBody
4499      *  @param mods    The modifiers starting the interface declaration
4500      *  @param dc       The documentation comment for the interface, or null.
4501      */
4502     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
4503         int pos = token.pos;
4504         accept(INTERFACE);
4505 
4506         Name name = typeName();
4507 
4508         List<JCTypeParameter> typarams = typeParametersOpt();
4509 
4510         List<JCExpression> extending = List.nil();
4511         if (token.kind == EXTENDS) {
4512             nextToken();
4513             extending = typeList();
4514         }
4515         List<JCExpression> permitting = permitsClause(mods, "interface");
4516 
4517         saveDanglingDocComments(dc);
4518 
4519         List<JCTree> defs;
4520         defs = classInterfaceOrRecordBody(name, true, false);
4521         JCClassDecl result = toP(F.at(pos).ClassDef(
4522             mods, name, typarams, null, extending, permitting, defs));
4523         return attach(result, dc);
4524     }
4525 
4526     List<JCExpression> permitsClause(JCModifiers mods, String classOrInterface) {
4527         if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
4528             checkSourceLevel(Feature.SEALED_CLASSES);
4529             if ((mods.flags & Flags.SEALED) == 0) {
4530                 log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed(classOrInterface)));
4531             }
4532             nextToken();
4533             return qualidentList(false);
4534         }
4535         return List.nil();
4536     }
4537 
4538     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
4539      *  @param mods    The modifiers starting the enum declaration
4540      *  @param dc       The documentation comment for the enum, or null.
4541      */
4542     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
4543         int pos = token.pos;
4544         accept(ENUM);
4545 
4546         Name name = typeName();
4547 
4548         int typeNamePos = token.pos;
4549         List<JCTypeParameter> typarams = typeParametersOpt(true);
4550         if (typarams == null || !typarams.isEmpty()) {
4551             int errorPosition = typarams == null
4552                     ? typeNamePos
4553                     : typarams.head.pos;
4554             log.error(DiagnosticFlag.SYNTAX, errorPosition, Errors.EnumCantBeGeneric);
4555         }
4556 
4557         List<JCExpression> implementing = List.nil();
4558         if (token.kind == IMPLEMENTS) {
4559             nextToken();
4560             implementing = typeList();
4561         }
4562 
4563         saveDanglingDocComments(dc);
4564 
4565         List<JCTree> defs = enumBody(name);
4566         mods.flags |= Flags.ENUM;
4567         JCClassDecl result = toP(F.at(pos).
4568             ClassDef(mods, name, List.nil(),
4569                      null, implementing, defs));
4570         return attach(result, dc);
4571     }
4572 
4573     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
4574      *                  [ ";" {ClassBodyDeclaration} ] "}"
4575      */
4576     List<JCTree> enumBody(Name enumName) {
4577         accept(LBRACE);
4578         ListBuffer<JCTree> defs = new ListBuffer<>();
4579         boolean wasSemi = false;
4580         boolean hasStructuralErrors = false;
4581         boolean wasError = false;
4582         if (token.kind == COMMA) {
4583             nextToken();
4584             if (token.kind == SEMI) {
4585                 wasSemi = true;
4586                 nextToken();
4587             } else if (token.kind != RBRACE) {
4588                 reportSyntaxError(S.prevToken().endPos,
4589                                   Errors.Expected2(RBRACE, SEMI));
4590                 wasError = true;
4591             }
4592         }
4593         while (token.kind != RBRACE && token.kind != EOF) {
4594             if (token.kind == SEMI) {
4595                 accept(SEMI);
4596                 wasSemi = true;
4597                 if (token.kind == RBRACE || token.kind == EOF) break;
4598             }
4599             EnumeratorEstimate memberType = estimateEnumeratorOrMember(enumName);
4600             if (memberType == EnumeratorEstimate.UNKNOWN) {
4601                 memberType = wasSemi ? EnumeratorEstimate.MEMBER
4602                                      : EnumeratorEstimate.ENUMERATOR;
4603             }
4604             if (memberType == EnumeratorEstimate.ENUMERATOR) {
4605                 wasError = false;
4606                 if (wasSemi && !hasStructuralErrors) {
4607                     reportSyntaxError(token.pos, Errors.EnumConstantNotExpected);
4608                     hasStructuralErrors = true;
4609                 }
4610                 defs.append(enumeratorDeclaration(enumName));
4611                 if (token.pos <= endPosTable.errorEndPos) {
4612                     // error recovery
4613                    skip(false, true, true, false);
4614                 } else {
4615                     if (token.kind != RBRACE && token.kind != SEMI && token.kind != EOF) {
4616                         if (token.kind == COMMA) {
4617                             nextToken();
4618                         } else {
4619                             setErrorEndPos(token.pos);
4620                             reportSyntaxError(S.prevToken().endPos,
4621                                               Errors.Expected3(COMMA, RBRACE, SEMI));
4622                             wasError = true;
4623                         }
4624                     }
4625                 }
4626             } else {
4627                 if (!wasSemi && !hasStructuralErrors && !wasError) {
4628                     reportSyntaxError(token.pos, Errors.EnumConstantExpected);
4629                     hasStructuralErrors = true;
4630                 }
4631                 wasError = false;
4632                 defs.appendList(classOrInterfaceOrRecordBodyDeclaration(null, enumName,
4633                                                                 false, false));
4634                 if (token.pos <= endPosTable.errorEndPos) {
4635                     // error recovery
4636                    skip(false, true, true, false);
4637                 }
4638             }
4639         }
4640         accept(RBRACE);
4641         return defs.toList();
4642     }
4643 
4644     @SuppressWarnings("fallthrough")
4645     private EnumeratorEstimate estimateEnumeratorOrMember(Name enumName) {
4646         // if we are seeing a record declaration inside of an enum we want the same error message as expected for a
4647         // let's say an interface declaration inside an enum
4648         boolean ident = token.kind == TokenKind.IDENTIFIER ||
4649                         token.kind == TokenKind.UNDERSCORE;
4650         if (ident && token.name() != enumName &&
4651                 (!allowRecords || !isRecordStart())) {
4652             Token next = S.token(1);
4653             switch (next.kind) {
4654                 case LPAREN: case LBRACE: case COMMA: case SEMI:
4655                     return EnumeratorEstimate.ENUMERATOR;
4656             }
4657         }
4658         switch (token.kind) {
4659             case IDENTIFIER:
4660                 if (allowRecords && isRecordStart()) {
4661                     return EnumeratorEstimate.MEMBER;
4662                 }
4663             case MONKEYS_AT: case LT: case UNDERSCORE:
4664                 return EnumeratorEstimate.UNKNOWN;
4665             default:
4666                 return EnumeratorEstimate.MEMBER;
4667         }
4668     }
4669 
4670     private enum EnumeratorEstimate {
4671         ENUMERATOR,
4672         MEMBER,
4673         UNKNOWN;
4674     }
4675 
4676     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
4677      */
4678     JCTree enumeratorDeclaration(Name enumName) {
4679         Comment dc = token.docComment();
4680         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
4681         if (token.deprecatedFlag()) {
4682             flags |= Flags.DEPRECATED;
4683         }
4684         int pos = token.pos;
4685         List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
4686         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
4687         List<JCExpression> typeArgs = typeArgumentsOpt();
4688         int identPos = token.pos;
4689         Name name = ident();
4690         int createPos = token.pos;
4691 
4692         saveDanglingDocComments(dc);
4693 
4694         List<JCExpression> args = (token.kind == LPAREN)
4695             ? arguments() : List.nil();
4696 
4697         JCClassDecl body = null;
4698         if (token.kind == LBRACE) {
4699             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM);
4700             List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
4701             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
4702         }
4703         if (args.isEmpty() && body == null)
4704             createPos = identPos;
4705         JCIdent ident = F.at(identPos).Ident(enumName);
4706         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
4707         if (createPos != identPos)
4708             storeEnd(create, S.prevToken().endPos);
4709         ident = F.at(identPos).Ident(enumName);
4710         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
4711         return attach(result, dc);
4712     }
4713 
4714     /** TypeList = Type {"," Type}
4715      */
4716     List<JCExpression> typeList() {
4717         ListBuffer<JCExpression> ts = new ListBuffer<>();
4718         ts.append(parseType());
4719         while (token.kind == COMMA) {
4720             nextToken();
4721             ts.append(parseType());
4722         }
4723         return ts.toList();
4724     }
4725 
4726     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
4727      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
4728      */
4729     List<JCTree> classInterfaceOrRecordBody(Name className, boolean isInterface, boolean isRecord) {
4730         accept(LBRACE);
4731         if (token.pos <= endPosTable.errorEndPos) {
4732             // error recovery
4733             skip(false, true, false, false);
4734             if (token.kind == LBRACE)
4735                 nextToken();
4736             else
4737                 return List.nil();
4738         }
4739         ListBuffer<JCTree> defs = new ListBuffer<>();
4740         while (token.kind != RBRACE && token.kind != EOF) {
4741             defs.appendList(classOrInterfaceOrRecordBodyDeclaration(null, className, isInterface, isRecord));
4742             if (token.pos <= endPosTable.errorEndPos) {
4743                // error recovery
4744                skip(false, true, true, false);
4745             }
4746         }
4747         accept(RBRACE);
4748         return defs.toList();
4749     }
4750 
4751     /** ClassBodyDeclaration =
4752      *      ";"
4753      *    | [STATIC] Block
4754      *    | ModifiersOpt
4755      *      ( Type Ident
4756      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
4757      *      | VOID Ident VoidMethodDeclaratorRest
4758      *      | TypeParameters [Annotations]
4759      *        ( Type Ident MethodDeclaratorRest
4760      *        | VOID Ident VoidMethodDeclaratorRest
4761      *        )
4762      *      | Ident ConstructorDeclaratorRest
4763      *      | TypeParameters Ident ConstructorDeclaratorRest
4764      *      | ClassOrInterfaceOrEnumDeclaration
4765      *      )
4766      *  InterfaceBodyDeclaration =
4767      *      ";"
4768      *    | ModifiersOpt
4769      *      ( Type Ident
4770      *        ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
4771      *      | VOID Ident MethodDeclaratorRest
4772      *      | TypeParameters [Annotations]
4773      *        ( Type Ident MethodDeclaratorRest
4774      *        | VOID Ident VoidMethodDeclaratorRest
4775      *        )
4776      *      | ClassOrInterfaceOrEnumDeclaration
4777      *      )
4778      *
4779      */
4780     protected List<JCTree> classOrInterfaceOrRecordBodyDeclaration(JCModifiers mods, Name className,
4781                                                                    boolean isInterface,
4782                                                                    boolean isRecord) {
4783         if (token.kind == SEMI) {
4784             nextToken();
4785             return List.nil();
4786         } else {
4787             Comment dc = token.docComment();
4788             int pos = token.pos;
4789             mods = modifiersOpt(mods);
4790             if (isDeclaration()) {
4791                 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
4792             } else if (token.kind == LBRACE &&
4793                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
4794                        mods.annotations.isEmpty()) {
4795                 if (isInterface) {
4796                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InitializerNotAllowed);
4797                 } else if (isRecord && (mods.flags & Flags.STATIC) == 0) {
4798                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InstanceInitializerNotAllowedInRecords);
4799                 }
4800                 ignoreDanglingComments();   // no declaration with which dangling comments can be associated
4801                 return List.of(block(pos, mods.flags));
4802             } else if (isDefiniteStatementStartToken()) {
4803                 int startPos = token.pos;
4804                 List<JCStatement> statements = blockStatement();
4805                 return List.of(syntaxError(startPos,
4806                                            statements,
4807                                            Errors.StatementNotExpected));
4808             } else {
4809                 return constructorOrMethodOrFieldDeclaration(mods, className, isInterface, isRecord, dc);
4810             }
4811         }
4812     }
4813 
4814     private List<JCTree> constructorOrMethodOrFieldDeclaration(JCModifiers mods, Name className,
4815                                                                boolean isInterface,
4816                                                                boolean isRecord, Comment dc) {
4817         int pos;
4818         pos = token.pos;
4819         List<JCTypeParameter> typarams = typeParametersOpt();
4820         // if there are type parameters but no modifiers, save the start
4821         // position of the method in the modifiers.
4822         if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4823             mods.pos = pos;
4824             storeEnd(mods, pos);
4825         }
4826         List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4827 
4828         if (annosAfterParams.nonEmpty()) {
4829             mods.annotations = mods.annotations.appendList(annosAfterParams);
4830             if (mods.pos == Position.NOPOS)
4831                 mods.pos = mods.annotations.head.pos;
4832         }
4833 
4834         Token tk = token;
4835         pos = token.pos;
4836         JCExpression type;
4837         boolean isVoid = token.kind == VOID;
4838 
4839         if (isVoid) {
4840             type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4841             nextToken();
4842         } else {
4843             // method returns types are un-annotated types
4844             type = unannotatedType(false);
4845         }
4846 
4847         // Constructor
4848         if ((token.kind == LPAREN && !isInterface ||
4849                 isRecord && token.kind == LBRACE) && type.hasTag(IDENT)) {
4850             if (isInterface || tk.name() != className) {
4851                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq);
4852             } else if (annosAfterParams.nonEmpty()) {
4853                 illegal(annosAfterParams.head.pos);
4854             }
4855 
4856             if (isRecord && token.kind == LBRACE) {
4857                 mods.flags |= Flags.COMPACT_RECORD_CONSTRUCTOR;
4858             }
4859 
4860             return List.of(methodDeclaratorRest(
4861                     pos, mods, null, names.init, typarams,
4862                     isInterface, true, isRecord, dc));
4863         }
4864 
4865         // Record constructor
4866         if (isRecord && type.hasTag(IDENT) && token.kind == THROWS) {
4867             // trying to define a compact constructor with a throws clause
4868             log.error(DiagnosticFlag.SYNTAX, token.pos,
4869                     Errors.InvalidCanonicalConstructorInRecord(
4870                             Fragments.Compact,
4871                             className,
4872                             Fragments.ThrowsClauseNotAllowedForCanonicalConstructor(Fragments.Compact)));
4873             skip(false, true, false, false);
4874             return List.of(methodDeclaratorRest(
4875                     pos, mods, null, names.init, typarams,
4876                     isInterface, true, isRecord, dc));
4877         }
4878 
4879         pos = token.pos;
4880         Name name = ident();
4881 
4882         // Method
4883         if (token.kind == LPAREN) {
4884             return List.of(methodDeclaratorRest(
4885                     pos, mods, type, name, typarams,
4886                     isInterface, isVoid, false, dc));
4887         }
4888 
4889         // Field
4890         if (!isVoid && typarams.isEmpty()) {
4891             if (!isRecord || (isRecord && (mods.flags & Flags.STATIC) != 0)) {
4892                 List<JCTree> defs =
4893                     variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4894                                             new ListBuffer<JCTree>(), false).toList();
4895                 accept(SEMI);
4896                 storeEnd(defs.last(), S.prevToken().endPos);
4897                 return defs;
4898             }
4899 
4900             int errPos = pos;
4901             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4902                     new ListBuffer<JCTree>(), false).toList();
4903             accept(SEMI);
4904             return List.of(syntaxError(errPos, null, Errors.RecordCannotDeclareInstanceFields));
4905          }
4906 
4907          pos = token.pos;
4908          List<JCTree> err;
4909 
4910          // Error recovery
4911          if (isVoid || typarams.nonEmpty()) {
4912              JCMethodDecl m =
4913                      toP(F.at(pos).MethodDef(mods, name, type, typarams,
4914                                              List.nil(), List.nil(), null, null));
4915              attach(m, dc);
4916              err = List.of(m);
4917          } else {
4918              err = List.nil();
4919          }
4920 
4921          return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
4922     }
4923 
4924     private List<JCTree> topLevelMethodOrFieldDeclaration(JCModifiers mods, Comment dc) throws AssertionError {
4925         int pos = token.pos;
4926         dc = dc == null ? token.docComment() : dc;
4927         List<JCTypeParameter> typarams = typeParametersOpt();
4928 
4929         // if there are type parameters but no modifiers, save the start
4930         // position of the method in the modifiers.
4931         if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4932             mods.pos = pos;
4933             storeEnd(mods, pos);
4934         }
4935 
4936         List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4937 
4938         if (annosAfterParams.nonEmpty()) {
4939             mods.annotations = mods.annotations.appendList(annosAfterParams);
4940             if (mods.pos == Position.NOPOS)
4941                 mods.pos = mods.annotations.head.pos;
4942         }
4943 
4944         pos = token.pos;
4945         JCExpression type;
4946         boolean isVoid = token.kind == VOID;
4947 
4948         if (isVoid) {
4949             type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4950             nextToken();
4951         } else {
4952             type = unannotatedType(false);
4953         }
4954 
4955         if (token.kind == IDENTIFIER) {
4956             pos = token.pos;
4957             Name name = ident();
4958 
4959             // Method
4960             if (token.kind == LPAREN) {
4961                 return List.of(methodDeclaratorRest(pos, mods, type, name, typarams,
4962                         false, isVoid, false, dc));
4963             }
4964 
4965             // Field
4966             if (!isVoid && typarams.isEmpty() && (token.kind == EQ || token.kind == SEMI)) {
4967                 List<JCTree> defs =
4968                         variableDeclaratorsRest(pos, mods, type, name, false, dc,
4969                                 new ListBuffer<JCTree>(), false).toList();
4970                 accept(SEMI);
4971                 storeEnd(defs.last(), S.prevToken().endPos);
4972 
4973                 return defs;
4974             }
4975         } else if (token.kind == LPAREN && type.hasTag(IDENT)) {
4976             log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq);
4977 
4978             return List.of(methodDeclaratorRest(
4979                     pos, mods, null, names.init, typarams,
4980                     false, true, false, dc));
4981         }
4982 
4983         return List.of(F.Erroneous());
4984     }
4985 
4986     protected boolean isDeclaration() {
4987         return isDeclaration(allowRecords);
4988     }
4989 
4990     private boolean isDeclaration(boolean allowRecords) {
4991         return token.kind == CLASS ||
4992                token.kind == INTERFACE ||
4993                token.kind == ENUM ||
4994                isRecordStart() && allowRecords;
4995     }
4996 
4997     /**
4998      * {@return true if and only if the current token is definitelly a token that
4999      *  starts a statement.}
5000      */
5001     private boolean isDefiniteStatementStartToken() {
5002         return switch (token.kind) {
5003             case IF, WHILE, DO, SWITCH, RETURN, TRY, FOR, ASSERT, BREAK,
5004                  CONTINUE, THROW -> true;
5005             default -> false;
5006         };
5007     }
5008 
5009     protected boolean isRecordStart() {
5010         if (token.kind == IDENTIFIER && token.name() == names.record && peekToken(TokenKind.IDENTIFIER)) {
5011             checkSourceLevel(Feature.RECORDS);
5012             return true;
5013         } else {
5014             return false;
5015         }
5016     }
5017 
5018     protected boolean isNonSealedClassStart(boolean local) {
5019         if (isNonSealedIdentifier(token, 0)) {
5020             Token next = S.token(3);
5021             return allowedAfterSealedOrNonSealed(next, local, true);
5022         }
5023         return false;
5024     }
5025 
5026     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
5027         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
5028             Token tokenSub = S.token(lookAheadOffset + 1);
5029             Token tokenSealed = S.token(lookAheadOffset + 2);
5030             if (someToken.endPos == tokenSub.pos &&
5031                     tokenSub.endPos == tokenSealed.pos &&
5032                     tokenSealed.name() == names.sealed) {
5033                 checkSourceLevel(Feature.SEALED_CLASSES);
5034                 return true;
5035             }
5036         }
5037         return false;
5038     }
5039 
5040     protected boolean isValueModifier() {
5041         if (token.kind == IDENTIFIER && token.name() == names.value) {
5042             boolean isValueModifier = false;
5043             Token next = S.token(1);
5044             switch (next.kind) {
5045                 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
5046                 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
5047                 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
5048                 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
5049                 case CLASS: case INTERFACE: case ENUM:
5050                     isValueModifier = true;
5051                     break;
5052                 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
5053                     if (next.name() == names.record || next.name() == names.value
5054                             || (mode & EXPR) != 0)
5055                         isValueModifier = true;
5056                     break;
5057             }
5058             if (isValueModifier) {
5059                 checkSourceLevel(Feature.VALUE_CLASSES);
5060                 return true;
5061             }
5062         }
5063         return false;
5064     }
5065 
5066     protected boolean isSealedClassStart(boolean local) {
5067         if (token.name() == names.sealed) {
5068             Token next = S.token(1);
5069             if (allowedAfterSealedOrNonSealed(next, local, false)) {
5070                 checkSourceLevel(Feature.SEALED_CLASSES);
5071                 return true;
5072             }
5073         }
5074         return false;
5075     }
5076 
5077     private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5078         return local ?
5079             switch (next.kind) {
5080                 case MONKEYS_AT -> {
5081                     Token afterNext = S.token(2);
5082                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5083                 }
5084                 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5085                 default -> false;
5086             } :
5087             switch (next.kind) {
5088                 case MONKEYS_AT -> {
5089                     Token afterNext = S.token(2);
5090                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5091                 }
5092                 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5093                 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
5094                         next.name() == names.sealed ||
5095                         allowValueClasses && next.name() == names.value;
5096                 default -> false;
5097             };
5098     }
5099 
5100     /** MethodDeclaratorRest =
5101      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5102      *  VoidMethodDeclaratorRest =
5103      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
5104      *  ConstructorDeclaratorRest =
5105      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5106      */
5107     protected JCTree methodDeclaratorRest(int pos,
5108                               JCModifiers mods,
5109                               JCExpression type,
5110                               Name name,
5111                               List<JCTypeParameter> typarams,
5112                               boolean isInterface, boolean isVoid,
5113                               boolean isRecord,
5114                               Comment dc) {
5115         if (isInterface) {
5116             if ((mods.flags & Flags.PRIVATE) != 0) {
5117                 checkSourceLevel(Feature.PRIVATE_INTERFACE_METHODS);
5118             }
5119         }
5120         JCVariableDecl prevReceiverParam = this.receiverParam;
5121         try {
5122             this.receiverParam = null;
5123             // Parsing formalParameters sets the receiverParam, if present
5124             List<JCVariableDecl> params = List.nil();
5125             List<JCExpression> thrown = List.nil();
5126             boolean unclosedParameterList;
5127             if (!isRecord || name != names.init || token.kind == LPAREN) {
5128                 params = formalParameters();
5129                 unclosedParameterList = token.pos == endPosTable.errorEndPos;
5130                 if (!isVoid) type = bracketsOpt(type);
5131                 if (token.kind == THROWS) {
5132                     nextToken();
5133                     thrown = qualidentList(true);
5134                 }
5135             } else {
5136                 unclosedParameterList = false;
5137             }
5138 
5139             saveDanglingDocComments(dc);
5140 
5141             JCBlock body = null;
5142             JCExpression defaultValue;
5143             if (token.kind == LBRACE) {
5144                 body = block();
5145                 defaultValue = null;
5146             } else {
5147                 if (token.kind == DEFAULT) {
5148                     accept(DEFAULT);
5149                     defaultValue = annotationValue();
5150                     accept(SEMI);
5151                 } else {
5152                     defaultValue = null;
5153                     accept(SEMI, tk -> Errors.Expected2(LBRACE, SEMI));
5154                 }
5155                 if (token.pos <= endPosTable.errorEndPos) {
5156                     // error recovery
5157                     // look if there is a probable missing opening brace,
5158                     // and if yes, parse as a block
5159                     boolean parseAsBlock = openingBraceMissing(unclosedParameterList);
5160 
5161                     if (parseAsBlock) {
5162                         body = block();
5163                     }
5164                 }
5165             }
5166 
5167             JCMethodDecl result =
5168                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
5169                                             receiverParam, params, thrown,
5170                                             body, defaultValue));
5171             return attach(result, dc);
5172         } finally {
5173             this.receiverParam = prevReceiverParam;
5174         }
5175     }
5176 
5177     /**
5178      * After seeing a method header, and not seeing an opening left brace,
5179      * attempt to estimate if acting as if the left brace was present and
5180      * parsing the upcoming code will get better results than not parsing
5181      * the code as a block.
5182      *
5183      * The estimate is as follows:
5184      * - tokens are skipped until member, statement or identifier is found,
5185      * - then, if there is a left brace, parse as a block,
5186      * - otherwise, if the head was broken, do not parse as a block,
5187      * - otherwise, look at the next token and:
5188      *   - if it definitelly starts a statement, parse as a block,
5189      *   - otherwise, if it is a closing/right brace, count opening and closing
5190      *     braces in the rest of the file, to see if imaginarily "adding" an opening
5191      *     brace would lead to a balanced count - if yes, parse as a block,
5192      *   - otherwise, speculatively parse the following code as a block, and if
5193      *     it contains statements that cannot be members, parse as a block,
5194      *   - otherwise, don't parse as a block.
5195      *
5196      * @param unclosedParameterList whether there was a serious problem in the
5197      *                              parameters list
5198      * @return true if and only if the following code should be parsed as a block.
5199      */
5200     private boolean openingBraceMissing(boolean unclosedParameterList) {
5201         skip(false, true, !unclosedParameterList, !unclosedParameterList);
5202 
5203         if (token.kind == LBRACE) {
5204             return true;
5205         } else if (unclosedParameterList) {
5206             return false;
5207         } else {
5208             return switch (token.kind) {
5209                 //definitelly sees a statement:
5210                 case CASE, DEFAULT, IF, FOR, WHILE, DO, TRY, SWITCH,
5211                     RETURN, THROW, BREAK, CONTINUE, ELSE, FINALLY,
5212                     CATCH, THIS, SUPER, NEW -> true;
5213                 case RBRACE -> {
5214                     //check if adding an opening brace would balance out
5215                     //the opening and closing braces:
5216                     int braceBalance = 1;
5217                     VirtualScanner virtualScanner = new VirtualScanner(S);
5218 
5219                     virtualScanner.nextToken();
5220 
5221                     while (virtualScanner.token().kind != TokenKind.EOF) {
5222                         switch (virtualScanner.token().kind) {
5223                             case LBRACE -> braceBalance++;
5224                             case RBRACE -> braceBalance--;
5225                         }
5226                         virtualScanner.nextToken();
5227                     }
5228 
5229                     yield braceBalance == 0;
5230                 }
5231                 default -> {
5232                     //speculatively try to parse as a block, and check
5233                     //if the result would suggest there is a block
5234                     //e.g.: it contains a statement that is not
5235                     //a member declaration
5236                     JavacParser speculative = new VirtualParser(this);
5237                     JCBlock speculativeResult =
5238                             speculative.block();
5239                     if (!speculativeResult.stats.isEmpty()) {
5240                         JCStatement last = speculativeResult.stats.last();
5241                         yield !speculativeResult.stats.stream().allMatch(s -> s.hasTag(VARDEF) ||
5242                                 s.hasTag(CLASSDEF) ||
5243                                 s.hasTag(BLOCK) ||
5244                                 s == last) ||
5245                             !(last instanceof JCExpressionStatement exprStatement &&
5246                             exprStatement.expr.hasTag(ERRONEOUS));
5247                     } else {
5248                         yield false;
5249                     }
5250                 }
5251             };
5252         }
5253     }
5254 
5255     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
5256      */
5257     List<JCExpression> qualidentList(boolean allowAnnos) {
5258         ListBuffer<JCExpression> ts = new ListBuffer<>();
5259 
5260         List<JCAnnotation> typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
5261         JCExpression qi = qualident(allowAnnos);
5262         if (!typeAnnos.isEmpty()) {
5263             JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
5264             ts.append(at);
5265         } else {
5266             ts.append(qi);
5267         }
5268         while (token.kind == COMMA) {
5269             nextToken();
5270 
5271             typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
5272             qi = qualident(allowAnnos);
5273             if (!typeAnnos.isEmpty()) {
5274                 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
5275                 ts.append(at);
5276             } else {
5277                 ts.append(qi);
5278             }
5279         }
5280         return ts.toList();
5281     }
5282 
5283     /**
5284      *  {@literal
5285      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
5286      *  }
5287      */
5288     protected List<JCTypeParameter> typeParametersOpt() {
5289         return typeParametersOpt(false);
5290     }
5291     /** Parses a potentially empty type parameter list if needed with `allowEmpty`.
5292      *  The caller is free to choose the desirable error message in this (erroneous) case.
5293      */
5294     protected List<JCTypeParameter> typeParametersOpt(boolean parseEmpty) {
5295         if (token.kind == LT) {
5296             ListBuffer<JCTypeParameter> typarams = new ListBuffer<>();
5297             nextToken();
5298 
5299             if (parseEmpty && token.kind == GT) {
5300                 accept(GT);
5301                 return null;
5302             }
5303 
5304             typarams.append(typeParameter());
5305             while (token.kind == COMMA) {
5306                 nextToken();
5307                 typarams.append(typeParameter());
5308             }
5309             accept(GT);
5310             return typarams.toList();
5311         } else {
5312             return List.nil();
5313         }
5314     }
5315 
5316     /**
5317      *  {@literal
5318      *  TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
5319      *  TypeParameterBound = EXTENDS Type {"&" Type}
5320      *  TypeVariable = Ident
5321      *  }
5322      */
5323     JCTypeParameter typeParameter() {
5324         int pos = token.pos;
5325         List<JCAnnotation> annos = typeAnnotationsOpt();
5326         Name name = typeName();
5327         ListBuffer<JCExpression> bounds = new ListBuffer<>();
5328         if (token.kind == EXTENDS) {
5329             nextToken();
5330             bounds.append(parseType());
5331             while (token.kind == AMP) {
5332                 nextToken();
5333                 bounds.append(parseType());
5334             }
5335         }
5336         return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
5337     }
5338 
5339     /** FormalParameters = "(" [ FormalParameterList ] ")"
5340      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
5341      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
5342      */
5343     List<JCVariableDecl> formalParameters() {
5344         return formalParameters(false, false);
5345     }
5346     List<JCVariableDecl> formalParameters(boolean lambdaParameters, boolean recordComponents) {
5347         ListBuffer<JCVariableDecl> params = new ListBuffer<>();
5348         JCVariableDecl lastParam;
5349         accept(LPAREN);
5350         if (token.kind != RPAREN) {
5351             this.allowThisIdent = !lambdaParameters && !recordComponents;
5352             lastParam = formalParameter(lambdaParameters, recordComponents);
5353             if (lastParam.nameexpr != null) {
5354                 this.receiverParam = lastParam;
5355             } else {
5356                 params.append(lastParam);
5357             }
5358             this.allowThisIdent = false;
5359             while (token.kind == COMMA) {
5360                 if ((lastParam.mods.flags & Flags.VARARGS) != 0) {
5361                     log.error(DiagnosticFlag.SYNTAX, lastParam, Errors.VarargsMustBeLast);
5362                 }
5363                 nextToken();
5364                 params.append(lastParam = formalParameter(lambdaParameters, recordComponents));
5365             }
5366         }
5367         if (token.kind == RPAREN) {
5368             nextToken();
5369         } else {
5370             setErrorEndPos(token.pos);
5371             reportSyntaxError(S.prevToken().endPos, Errors.Expected3(COMMA, RPAREN, LBRACKET));
5372         }
5373         return params.toList();
5374     }
5375 
5376     List<JCVariableDecl> implicitParameters(boolean hasParens) {
5377         if (hasParens) {
5378             accept(LPAREN);
5379         }
5380         ListBuffer<JCVariableDecl> params = new ListBuffer<>();
5381         if (token.kind != RPAREN && token.kind != ARROW) {
5382             params.append(implicitParameter());
5383             while (token.kind == COMMA) {
5384                 nextToken();
5385                 params.append(implicitParameter());
5386             }
5387         }
5388         if (hasParens) {
5389             accept(RPAREN);
5390         }
5391         return params.toList();
5392     }
5393 
5394     JCModifiers optFinal(long flags) {
5395         JCModifiers mods = modifiersOpt();
5396         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
5397         mods.flags |= flags;
5398         return mods;
5399     }
5400 
5401     /**
5402      * Inserts the annotations (and possibly a new array level)
5403      * to the left-most type in an array or nested type.
5404      *
5405      * When parsing a type like {@code @B Outer.Inner @A []}, the
5406      * {@code @A} annotation should target the array itself, while
5407      * {@code @B} targets the nested type {@code Outer}.
5408      *
5409      * Currently the parser parses the annotation first, then
5410      * the array, and then inserts the annotation to the left-most
5411      * nested type.
5412      *
5413      * When {@code createNewLevel} is true, then a new array
5414      * level is inserted as the most inner type, and have the
5415      * annotations target it.  This is useful in the case of
5416      * varargs, e.g. {@code String @A [] @B ...}, as the parser
5417      * first parses the type {@code String @A []} then inserts
5418      * a new array level with {@code @B} annotation.
5419      */
5420     private JCExpression insertAnnotationsToMostInner(
5421             JCExpression type, List<JCAnnotation> annos,
5422             boolean createNewLevel) {
5423         int origEndPos = getEndPos(type);
5424         JCExpression mostInnerType = type;
5425         JCArrayTypeTree mostInnerArrayType = null;
5426         while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) {
5427             mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType);
5428             mostInnerType = mostInnerArrayType.elemtype;
5429         }
5430 
5431         if (createNewLevel) {
5432             mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType));
5433             origEndPos = getEndPos(mostInnerType);
5434         }
5435 
5436         JCExpression mostInnerTypeToReturn = mostInnerType;
5437         if (annos.nonEmpty()) {
5438             JCExpression lastToModify = mostInnerType;
5439 
5440             while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) ||
5441                     TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
5442                 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) {
5443                     lastToModify = mostInnerType;
5444                     mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression();
5445                 }
5446                 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
5447                     lastToModify = mostInnerType;
5448                     mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz;
5449                 }
5450             }
5451 
5452             mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType);
5453 
5454             if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) {
5455                 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType;
5456             } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) {
5457                 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType;
5458             } else {
5459                 // We never saw a SELECT or TYPEAPPLY, return the annotated type.
5460                 mostInnerTypeToReturn = mostInnerType;
5461             }
5462         }
5463 
5464         if (mostInnerArrayType == null) {
5465             return mostInnerTypeToReturn;
5466         } else {
5467             mostInnerArrayType.elemtype = mostInnerTypeToReturn;
5468             return storeEnd(type, origEndPos);
5469         }
5470     }
5471 
5472     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
5473      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
5474      */
5475     protected JCVariableDecl formalParameter(boolean lambdaParameter, boolean recordComponent) {
5476         JCModifiers mods = !recordComponent ? optFinal(Flags.PARAMETER) : modifiersOpt();
5477         if (recordComponent && mods.flags != 0) {
5478             log.error(mods.pos, Errors.RecordCantDeclareFieldModifiers);
5479         }
5480         if (recordComponent) {
5481             mods.flags |= Flags.RECORD | Flags.FINAL | Flags.PRIVATE | Flags.GENERATED_MEMBER;
5482         }
5483         // need to distinguish between vararg annos and array annos
5484         // look at typeAnnotationsPushedBack comment
5485         this.permitTypeAnnotationsPushBack = true;
5486         JCExpression type = parseType(lambdaParameter);
5487         this.permitTypeAnnotationsPushBack = false;
5488 
5489         if (token.kind == ELLIPSIS) {
5490             List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack;
5491             typeAnnotationsPushedBack = List.nil();
5492             mods.flags |= Flags.VARARGS;
5493             // insert var arg type annotations
5494             type = insertAnnotationsToMostInner(type, varargsAnnos, true);
5495             nextToken();
5496         } else {
5497             // if not a var arg, then typeAnnotationsPushedBack should be null
5498             if (typeAnnotationsPushedBack.nonEmpty()) {
5499                 reportSyntaxError(typeAnnotationsPushedBack.head.pos, Errors.IllegalStartOfType);
5500             }
5501             typeAnnotationsPushedBack = List.nil();
5502         }
5503         return variableDeclaratorId(mods, type, false, lambdaParameter, recordComponent);
5504     }
5505 
5506     protected JCVariableDecl implicitParameter() {
5507         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
5508         return variableDeclaratorId(mods, null, false, true, false);
5509     }
5510 
5511 /* ---------- auxiliary methods -------------- */
5512     /** Check that given tree is a legal expression statement.
5513      */
5514     protected JCExpression checkExprStat(JCExpression t) {
5515         if (!TreeInfo.isExpressionStatement(t)) {
5516             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
5517             log.error(DiagnosticFlag.SYNTAX, ret, Errors.NotStmt);
5518             return ret;
5519         } else {
5520             return t;
5521         }
5522     }
5523 
5524     /** Return precedence of operator represented by token,
5525      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
5526      */
5527     static int prec(TokenKind token) {
5528         JCTree.Tag oc = optag(token);
5529         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
5530     }
5531 
5532     /**
5533      * Return the lesser of two positions, making allowance for either one
5534      * being unset.
5535      */
5536     static int earlier(int pos1, int pos2) {
5537         if (pos1 == Position.NOPOS)
5538             return pos2;
5539         if (pos2 == Position.NOPOS)
5540             return pos1;
5541         return (pos1 < pos2 ? pos1 : pos2);
5542     }
5543 
5544     /** Return operation tag of binary operator represented by token,
5545      *  No_TAG if token is not a binary operator.
5546      */
5547     static JCTree.Tag optag(TokenKind token) {
5548         switch (token) {
5549         case BARBAR:
5550             return OR;
5551         case AMPAMP:
5552             return AND;
5553         case BAR:
5554             return BITOR;
5555         case BAREQ:
5556             return BITOR_ASG;
5557         case CARET:
5558             return BITXOR;
5559         case CARETEQ:
5560             return BITXOR_ASG;
5561         case AMP:
5562             return BITAND;
5563         case AMPEQ:
5564             return BITAND_ASG;
5565         case EQEQ:
5566             return JCTree.Tag.EQ;
5567         case BANGEQ:
5568             return NE;
5569         case LT:
5570             return JCTree.Tag.LT;
5571         case GT:
5572             return JCTree.Tag.GT;
5573         case LTEQ:
5574             return LE;
5575         case GTEQ:
5576             return GE;
5577         case LTLT:
5578             return SL;
5579         case LTLTEQ:
5580             return SL_ASG;
5581         case GTGT:
5582             return SR;
5583         case GTGTEQ:
5584             return SR_ASG;
5585         case GTGTGT:
5586             return USR;
5587         case GTGTGTEQ:
5588             return USR_ASG;
5589         case PLUS:
5590             return JCTree.Tag.PLUS;
5591         case PLUSEQ:
5592             return PLUS_ASG;
5593         case SUB:
5594             return MINUS;
5595         case SUBEQ:
5596             return MINUS_ASG;
5597         case STAR:
5598             return MUL;
5599         case STAREQ:
5600             return MUL_ASG;
5601         case SLASH:
5602             return DIV;
5603         case SLASHEQ:
5604             return DIV_ASG;
5605         case PERCENT:
5606             return MOD;
5607         case PERCENTEQ:
5608             return MOD_ASG;
5609         case INSTANCEOF:
5610             return TYPETEST;
5611         default:
5612             return NO_TAG;
5613         }
5614     }
5615 
5616     /** Return operation tag of unary operator represented by token,
5617      *  No_TAG if token is not a binary operator.
5618      */
5619     static JCTree.Tag unoptag(TokenKind token) {
5620         switch (token) {
5621         case PLUS:
5622             return POS;
5623         case SUB:
5624             return NEG;
5625         case BANG:
5626             return NOT;
5627         case TILDE:
5628             return COMPL;
5629         case PLUSPLUS:
5630             return PREINC;
5631         case SUBSUB:
5632             return PREDEC;
5633         default:
5634             return NO_TAG;
5635         }
5636     }
5637 
5638     /** Return type tag of basic type represented by token,
5639      *  NONE if token is not a basic type identifier.
5640      */
5641     static TypeTag typetag(TokenKind token) {
5642         switch (token) {
5643         case BYTE:
5644             return TypeTag.BYTE;
5645         case CHAR:
5646             return TypeTag.CHAR;
5647         case SHORT:
5648             return TypeTag.SHORT;
5649         case INT:
5650             return TypeTag.INT;
5651         case LONG:
5652             return TypeTag.LONG;
5653         case FLOAT:
5654             return TypeTag.FLOAT;
5655         case DOUBLE:
5656             return TypeTag.DOUBLE;
5657         case BOOLEAN:
5658             return TypeTag.BOOLEAN;
5659         default:
5660             return TypeTag.NONE;
5661         }
5662     }
5663 
5664     void checkSourceLevel(Feature feature) {
5665         checkSourceLevel(token.pos, feature);
5666     }
5667 
5668     protected void checkSourceLevel(int pos, Feature feature) {
5669         if (preview.isPreview(feature) && !preview.isEnabled()) {
5670             //preview feature without --preview flag, error
5671             log.error(DiagnosticFlag.SOURCE_LEVEL, pos, preview.disabledError(feature));
5672         } else if (!feature.allowedInSource(source)) {
5673             //incompatible source level, error
5674             log.error(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name));
5675         } else if (preview.isPreview(feature)) {
5676             //use of preview feature, warn
5677             preview.warnPreview(pos, feature);
5678         }
5679     }
5680 
5681     private void updateUnexpectedTopLevelDefinitionStartError(boolean hasPackageDecl) {
5682         //TODO: proper tests for this logic (and updates):
5683         if (parseModuleInfo) {
5684             unexpectedTopLevelDefinitionStartError = Errors.ExpectedModuleOrOpen;
5685         } else if (Feature.IMPLICIT_CLASSES.allowedInSource(source) && !hasPackageDecl) {
5686             unexpectedTopLevelDefinitionStartError = Errors.ClassMethodOrFieldExpected;
5687         } else if (allowRecords) {
5688             unexpectedTopLevelDefinitionStartError = Errors.Expected4(CLASS, INTERFACE, ENUM, "record");
5689         } else {
5690             unexpectedTopLevelDefinitionStartError = Errors.Expected3(CLASS, INTERFACE, ENUM);
5691         }
5692     }
5693 
5694     /**
5695      * A straightforward {@link EndPosTable} implementation.
5696      */
5697     protected static class SimpleEndPosTable extends AbstractEndPosTable {
5698 
5699         private final IntHashTable endPosMap = new IntHashTable();
5700 
5701         @Override
5702         public <T extends JCTree> T storeEnd(T tree, int endpos) {
5703             endPosMap.put(tree, Math.max(endpos, errorEndPos));
5704             return tree;
5705         }
5706 
5707         @Override
5708         public int getEndPos(JCTree tree) {
5709             int value = endPosMap.get(tree);
5710             // As long as Position.NOPOS==-1, this just returns value.
5711             return (value == -1) ? Position.NOPOS : value;
5712         }
5713 
5714         @Override
5715         public int replaceTree(JCTree oldTree, JCTree newTree) {
5716             int pos = endPosMap.remove(oldTree);
5717             if (pos != -1 && newTree != null) {
5718                 storeEnd(newTree, pos);
5719             }
5720             return pos;
5721         }
5722     }
5723 
5724     /**
5725      * A minimal implementation that only stores what's required.
5726      */
5727     protected static class MinimalEndPosTable extends SimpleEndPosTable {
5728 
5729         @Override
5730         public <T extends JCTree> T storeEnd(T tree, int endpos) {
5731             switch (tree.getTag()) {
5732             case MODULEDEF:
5733             case PACKAGEDEF:
5734             case CLASSDEF:
5735             case METHODDEF:
5736             case VARDEF:
5737                 break;
5738             default:
5739                 return tree;
5740             }
5741             return super.storeEnd(tree, endpos);
5742         }
5743     }
5744 
5745     protected abstract static class AbstractEndPosTable implements EndPosTable {
5746 
5747         /**
5748          * Store the last error position.
5749          */
5750         public int errorEndPos = Position.NOPOS;
5751 
5752         @Override
5753         public void setErrorEndPos(int errPos) {
5754             if (errPos > errorEndPos) {
5755                 errorEndPos = errPos;
5756             }
5757         }
5758     }
5759 }