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