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