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