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