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