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