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