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