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