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