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