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