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.parser.Tokens.Comment.CommentStyle;
  44 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  45 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  46 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  47 import com.sun.tools.javac.tree.*;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 import com.sun.tools.javac.util.*;
  50 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  51 import com.sun.tools.javac.util.JCDiagnostic.Error;
  52 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  53 import com.sun.tools.javac.util.List;
  54 
  55 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  56 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  57 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  58 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  59 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  60 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  61 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  62 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  63 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  64 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  65 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  66 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
  67 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
  68 
  69 /**
  70  * The parser maps a token sequence into an abstract syntax tree.
  71  * The parser is a hand-written recursive-descent parser that
  72  * implements the grammar described in the Java Language Specification.
  73  * For efficiency reasons, an operator precedence scheme is used
  74  * for parsing binary operation expressions.
  75  *
  76  *  <p><b>This is NOT part of any supported API.
  77  *  If you write code that depends on this, you do so at your own risk.
  78  *  This code and its internal interfaces are subject to change or
  79  *  deletion without notice.</b>
  80  */
  81 public class JavacParser implements Parser {
  82 
  83     /** The number of precedence levels of infix operators.
  84      */
  85     private static final int infixPrecedenceLevels = 10;
  86 
  87     /** Is the parser instantiated to parse a module-info file ?
  88      */
  89     private final boolean parseModuleInfo;
  90 
  91     /** The scanner used for lexical analysis.
  92      */
  93     protected Lexer S;
  94 
  95     /** The factory to be used for abstract syntax tree construction.
  96      */
  97     protected TreeMaker F;
  98 
  99     /** The log to be used for error diagnostics.
 100      */
 101     private Log log;
 102 
 103     /** The Source language setting. */
 104     private Source source;
 105 
 106     /** The Preview language setting. */
 107     private Preview preview;
 108 
 109     /** The name table. */
 110     private Names names;
 111 
 112     /** End position mappings container */
 113     protected final AbstractEndPosTable endPosTable;
 114 
 115     // Because of javac's limited lookahead, some contexts are ambiguous in
 116     // the presence of type annotations even though they are not ambiguous
 117     // in the absence of type annotations.  Consider this code:
 118     //   void m(String [] m) { }
 119     //   void m(String ... m) { }
 120     // After parsing "String", javac calls bracketsOpt which immediately
 121     // returns if the next character is not '['.  Similarly, javac can see
 122     // if the next token is ... and in that case parse an ellipsis.  But in
 123     // the presence of type annotations:
 124     //   void m(String @A [] m) { }
 125     //   void m(String @A ... m) { }
 126     // no finite lookahead is enough to determine whether to read array
 127     // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
 128     // bracketsOpt first reads all the leading annotations and only then
 129     // discovers that it needs to fail.  bracketsOpt needs a way to push
 130     // back the extra annotations that it read.  (But, bracketsOpt should
 131     // not *always* be allowed to push back extra annotations that it finds
 132     // -- in most contexts, any such extra annotation is an error.
 133     //
 134     // The following two variables permit type annotations that have
 135     // already been read to be stored for later use.  Alternate
 136     // implementations are possible but would cause much larger changes to
 137     // the parser.
 138 
 139     /** Type annotations that have already been read but have not yet been used. **/
 140     private List<JCAnnotation> typeAnnotationsPushedBack = List.nil();
 141 
 142     /**
 143      * If the parser notices extra annotations, then it either immediately
 144      * issues an error (if this variable is false) or places the extra
 145      * annotations in variable typeAnnotationsPushedBack (if this variable
 146      * is true).
 147      */
 148     private boolean permitTypeAnnotationsPushBack = false;
 149 
 150     interface ErrorRecoveryAction {
 151         JCTree doRecover(JavacParser parser);
 152     }
 153 
 154     enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
 155         BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
 156         CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
 157     }
 158 
 159     /** Construct a parser from a given scanner, tree factory and log.
 160      */
 161     protected JavacParser(ParserFactory fac,
 162                           Lexer S,
 163                           boolean keepDocComments,
 164                           boolean keepLineMap,
 165                           boolean keepEndPositions) {
 166         this(fac, S, keepDocComments, keepLineMap, keepEndPositions, false);
 167 
 168     }
 169     /** Construct a parser from a given scanner, tree factory and log.
 170      */
 171     @SuppressWarnings("this-escape")
 172     protected JavacParser(ParserFactory fac,
 173                      Lexer S,
 174                      boolean keepDocComments,
 175                      boolean keepLineMap,
 176                      boolean keepEndPositions,
 177                      boolean parseModuleInfo) {
 178         this.S = S;
 179         nextToken(); // prime the pump
 180         this.F = fac.F;
 181         this.log = fac.log;
 182         this.names = fac.names;
 183         this.source = fac.source;
 184         this.preview = fac.preview;
 185         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
 186         this.keepDocComments = keepDocComments;
 187         this.parseModuleInfo = parseModuleInfo;
 188         this.docComments = newDocCommentTable(keepDocComments, fac);
 189         this.keepLineMap = keepLineMap;
 190         this.errorTree = F.Erroneous();
 191         this.endPosTable = newEndPosTable(keepEndPositions);
 192         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 193         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 194         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 195     }
 196 
 197     /** Construct a parser from an existing parser, with minimal overhead.
 198      */
 199     @SuppressWarnings("this-escape")
 200     protected JavacParser(JavacParser parser,
 201                           Lexer S) {
 202         this.S = S;
 203         this.token = parser.token;
 204         this.F = parser.F;
 205         this.log = parser.log;
 206         this.names = parser.names;
 207         this.source = parser.source;
 208         this.preview = parser.preview;
 209         this.allowStringFolding = parser.allowStringFolding;
 210         this.keepDocComments = false;
 211         this.parseModuleInfo = false;
 212         this.docComments = null;
 213         this.errorTree = F.Erroneous();
 214         this.endPosTable = newEndPosTable(false);
 215         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 216         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 217         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 218     }
 219 
 220     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
 221         return  keepEndPositions
 222                 ? new SimpleEndPosTable(this)
 223                 : new EmptyEndPosTable(this);
 224     }
 225 
 226     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
 227         return keepDocComments ? new LazyDocCommentTable(fac) : null;
 228     }
 229 
 230     /** Switch: should we fold strings?
 231      */
 232     boolean allowStringFolding;
 233 
 234     /** Switch: should we keep docComments?
 235      */
 236     boolean keepDocComments;
 237 
 238     /** Switch: should we keep line table?
 239      */
 240     boolean keepLineMap;
 241 
 242     /** Switch: is "this" allowed as an identifier?
 243      * This is needed to parse receiver types.
 244      */
 245     boolean allowThisIdent;
 246 
 247     /** Switch: is yield statement allowed in this source level?
 248      */
 249     boolean allowYieldStatement;
 250 
 251     /** Switch: are records allowed in this source level?
 252      */
 253     boolean allowRecords;
 254 
 255     /** Switch: are sealed types allowed in this source level?
 256      */
 257     boolean allowSealedTypes;
 258 
 259     /** The type of the method receiver, as specified by a first "this" parameter.
 260      */
 261     JCVariableDecl receiverParam;
 262 
 263     /** When terms are parsed, the mode determines which is expected:
 264      *     mode = EXPR        : an expression
 265      *     mode = TYPE        : a type
 266      *     mode = NOPARAMS    : no parameters allowed for type
 267      *     mode = TYPEARG     : type argument
 268      *     mode |= NOLAMBDA   : lambdas are not allowed
 269      */
 270     protected static final int EXPR          = 1 << 0;
 271     protected static final int TYPE          = 1 << 1;
 272     protected static final int NOPARAMS      = 1 << 2;
 273     protected static final int TYPEARG       = 1 << 3;
 274     protected static final int DIAMOND       = 1 << 4;
 275     protected static final int NOLAMBDA      = 1 << 5;
 276 
 277     protected void setMode(int mode) {
 278         this.mode = mode;
 279     }
 280 
 281     protected void setLastMode(int mode) {
 282         lastmode = mode;
 283     }
 284 
 285     protected boolean isMode(int mode) {
 286         return (this.mode & mode) != 0;
 287     }
 288 
 289     protected boolean wasTypeMode() {
 290         return (lastmode & TYPE) != 0;
 291     }
 292 
 293     protected void selectExprMode() {
 294         setMode((mode & NOLAMBDA) | EXPR);
 295     }
 296 
 297     protected void selectTypeMode() {
 298         setMode((mode & NOLAMBDA) | TYPE);
 299     }
 300 
 301     /** The current mode.
 302      */
 303     protected int mode = 0;
 304 
 305     /** The mode of the term that was parsed last.
 306      */
 307     protected int lastmode = 0;
 308 
 309     /* ---------- token management -------------- */
 310 
 311     protected Token token;
 312 
 313     public Token token() {
 314         return token;
 315     }
 316 
 317     public void nextToken() {
 318         S.nextToken();
 319         token = S.token();
 320     }
 321 
 322     protected boolean peekToken(Predicate<TokenKind> tk) {
 323         return peekToken(0, tk);
 324     }
 325 
 326     protected boolean peekToken(int lookahead, Predicate<TokenKind> tk) {
 327         return tk.test(S.token(lookahead + 1).kind);
 328     }
 329 
 330     protected boolean peekToken(Predicate<TokenKind> tk1, Predicate<TokenKind> tk2) {
 331         return peekToken(0, tk1, tk2);
 332     }
 333 
 334     protected boolean peekToken(int lookahead, Predicate<TokenKind> tk1, Predicate<TokenKind> tk2) {
 335         return tk1.test(S.token(lookahead + 1).kind) &&
 336                 tk2.test(S.token(lookahead + 2).kind);
 337     }
 338 
 339     protected boolean peekToken(Predicate<TokenKind> tk1, Predicate<TokenKind> tk2, Predicate<TokenKind> tk3) {
 340         return peekToken(0, tk1, tk2, tk3);
 341     }
 342 
 343     protected boolean peekToken(int lookahead, Predicate<TokenKind> tk1, Predicate<TokenKind> tk2, Predicate<TokenKind> tk3) {
 344         return tk1.test(S.token(lookahead + 1).kind) &&
 345                 tk2.test(S.token(lookahead + 2).kind) &&
 346                 tk3.test(S.token(lookahead + 3).kind);
 347     }
 348 
 349     @SuppressWarnings("unchecked")
 350     protected boolean peekToken(Predicate<TokenKind>... kinds) {
 351         return peekToken(0, kinds);
 352     }
 353 
 354     @SuppressWarnings("unchecked")
 355     protected boolean peekToken(int lookahead, Predicate<TokenKind>... kinds) {
 356         for (Predicate<TokenKind> kind : kinds) {
 357             if (!kind.test(S.token(++lookahead).kind)) {
 358                 return false;
 359             }
 360         }
 361         return true;
 362     }
 363 
 364     /* ---------- error recovery -------------- */
 365 
 366     private JCErroneous errorTree;
 367 
 368     /** Skip forward until a suitable stop token is found.
 369      */
 370     protected void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
 371          while (true) {
 372              switch (token.kind) {
 373                 case SEMI:
 374                     nextToken();
 375                     return;
 376                 case PUBLIC:
 377                 case FINAL:
 378                 case ABSTRACT:
 379                 case MONKEYS_AT:
 380                 case EOF:
 381                 case CLASS:
 382                 case INTERFACE:
 383                 case ENUM:
 384                     return;
 385                 case IMPORT:
 386                     if (stopAtImport)
 387                         return;
 388                     break;
 389                 case LBRACE:
 390                 case RBRACE:
 391                 case PRIVATE:
 392                 case PROTECTED:
 393                 case STATIC:
 394                 case TRANSIENT:
 395                 case NATIVE:
 396                 case VOLATILE:
 397                 case SYNCHRONIZED:
 398                 case STRICTFP:
 399                 case LT:
 400                 case BYTE:
 401                 case SHORT:
 402                 case CHAR:
 403                 case INT:
 404                 case LONG:
 405                 case FLOAT:
 406                 case DOUBLE:
 407                 case BOOLEAN:
 408                 case VOID:
 409                     if (stopAtMemberDecl)
 410                         return;
 411                     break;
 412                 case UNDERSCORE:
 413                 case IDENTIFIER:
 414                    if (stopAtIdentifier)
 415                         return;
 416                     break;
 417                 case CASE:
 418                 case DEFAULT:
 419                 case IF:
 420                 case FOR:
 421                 case WHILE:
 422                 case DO:
 423                 case TRY:
 424                 case SWITCH:
 425                 case RETURN:
 426                 case THROW:
 427                 case BREAK:
 428                 case CONTINUE:
 429                 case ELSE:
 430                 case FINALLY:
 431                 case CATCH:
 432                 case THIS:
 433                 case SUPER:
 434                 case NEW:
 435                     if (stopAtStatement)
 436                         return;
 437                     break;
 438                 case ASSERT:
 439                     if (stopAtStatement)
 440                         return;
 441                     break;
 442             }
 443             nextToken();
 444         }
 445     }
 446 
 447     protected JCErroneous syntaxError(int pos, Error errorKey) {
 448         return syntaxError(pos, List.nil(), errorKey);
 449     }
 450 
 451     protected JCErroneous syntaxError(int pos, List<JCTree> errs, Error errorKey) {
 452         setErrorEndPos(pos);
 453         JCErroneous err = F.at(pos).Erroneous(errs);
 454         reportSyntaxError(err, errorKey);
 455         if (errs != null) {
 456             JCTree last = errs.last();
 457             if (last != null)
 458                 storeEnd(last, pos);
 459         }
 460         return toP(err);
 461     }
 462 
 463     private static final int RECOVERY_THRESHOLD = 50;
 464     private int errorPos = Position.NOPOS;
 465     private int count = 0;
 466 
 467     /**
 468      * Report a syntax using the given the position parameter and arguments,
 469      * unless one was already reported at the same position.
 470      */
 471     protected void reportSyntaxError(int pos, Error errorKey) {
 472         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
 473         reportSyntaxError(diag, errorKey);
 474     }
 475 
 476     /**
 477      * Report a syntax error using the given DiagnosticPosition object and
 478      * arguments, unless one was already reported at the same position.
 479      */
 480     protected void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, Error errorKey) {
 481         int pos = diagPos.getPreferredPosition();
 482         if (pos > S.errPos() || pos == Position.NOPOS) {
 483             if (token.kind == EOF) {
 484                 log.error(DiagnosticFlag.SYNTAX, diagPos, Errors.PrematureEof);
 485             } else {
 486                 log.error(DiagnosticFlag.SYNTAX, diagPos, errorKey);
 487             }
 488         }
 489         S.errPos(pos);
 490         if (token.pos == errorPos && token.kind != EOF) {
 491             //check for a possible infinite loop in parsing:
 492             Assert.check(count++ < RECOVERY_THRESHOLD);
 493         } else {
 494             count = 0;
 495             errorPos = token.pos;
 496         }
 497     }
 498 
 499     /** If next input token matches given token, skip it, otherwise report
 500      *  an error.
 501      */
 502     public void accept(TokenKind tk) {
 503         accept(tk, Errors::Expected);
 504     }
 505 
 506     /** If next input token matches given token, skip it, otherwise report
 507      *  an error.
 508      */
 509     public void accept(TokenKind tk, Function<TokenKind, Error> errorProvider) {
 510         if (token.kind == tk) {
 511             nextToken();
 512         } else {
 513             setErrorEndPos(token.pos);
 514             reportSyntaxError(S.prevToken().endPos, errorProvider.apply(tk));
 515         }
 516     }
 517 
 518     /** Report an illegal start of expression/type error at given position.
 519      */
 520     JCExpression illegal(int pos) {
 521         setErrorEndPos(pos);
 522         if (isMode(EXPR))
 523             return syntaxError(pos, Errors.IllegalStartOfExpr);
 524         else
 525             return syntaxError(pos, Errors.IllegalStartOfType);
 526 
 527     }
 528 
 529     /** Report an illegal start of expression/type error at current position.
 530      */
 531     JCExpression illegal() {
 532         return illegal(token.pos);
 533     }
 534 
 535     /** Diagnose a modifier flag from the set, if any. */
 536     protected void checkNoMods(long mods) {
 537         checkNoMods(token.pos, mods);
 538     }
 539 
 540     protected void checkNoMods(int pos, long mods) {
 541         if (mods != 0) {
 542             long lowestMod = mods & -mods;
 543             log.error(DiagnosticFlag.SYNTAX, pos, Errors.ModNotAllowedHere(Flags.asFlagSet(lowestMod)));
 544         }
 545     }
 546 
 547 /* ---------- doc comments --------- */
 548 
 549     /** A table to store all documentation comments
 550      *  indexed by the tree nodes they refer to.
 551      *  defined only if option flag keepDocComment is set.
 552      */
 553     private final DocCommentTable docComments;
 554 
 555     /** Make an entry into docComments hashtable,
 556      *  provided flag keepDocComments is set and given doc comment is non-null.
 557      *  @param tree   The tree to be used as index in the hashtable
 558      *  @param dc     The doc comment to associate with the tree, or null.
 559      */
 560     protected void attach(JCTree tree, Comment dc) {
 561         if (keepDocComments && dc != null) {
 562 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
 563             docComments.putComment(tree, dc);
 564         }
 565     }
 566 
 567 /* -------- source positions ------- */
 568 
 569     protected void setErrorEndPos(int errPos) {
 570         endPosTable.setErrorEndPos(errPos);
 571     }
 572 
 573     protected void storeEnd(JCTree tree, int endpos) {
 574         endPosTable.storeEnd(tree, endpos);
 575     }
 576 
 577     protected <T extends JCTree> T to(T t) {
 578         return endPosTable.to(t);
 579     }
 580 
 581     protected <T extends JCTree> T toP(T t) {
 582         return endPosTable.toP(t);
 583     }
 584 
 585     /** Get the start position for a tree node.  The start position is
 586      * defined to be the position of the first character of the first
 587      * token of the node's source text.
 588      * @param tree  The tree node
 589      */
 590     public int getStartPos(JCTree tree) {
 591         return TreeInfo.getStartPos(tree);
 592     }
 593 
 594     /**
 595      * Get the end position for a tree node.  The end position is
 596      * defined to be the position of the last character of the last
 597      * token of the node's source text.  Returns Position.NOPOS if end
 598      * positions are not generated or the position is otherwise not
 599      * found.
 600      * @param tree  The tree node
 601      */
 602     public int getEndPos(JCTree tree) {
 603         return endPosTable.getEndPos(tree);
 604     }
 605 
 606 
 607 
 608 /* ---------- parsing -------------- */
 609 
 610     /**
 611      * Ident = IDENTIFIER
 612      */
 613     public Name ident() {
 614         return ident(false);
 615     }
 616 
 617     protected Name ident(boolean allowClass) {
 618         return ident(allowClass, false);
 619     }
 620 
 621     public Name identOrUnderscore() {
 622         return ident(false, true);
 623     }
 624 
 625     protected Name ident(boolean allowClass, boolean asVariable) {
 626         if (token.kind == IDENTIFIER) {
 627             Name name = token.name();
 628             nextToken();
 629             return name;
 630         } else if (token.kind == ASSERT) {
 631             log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.AssertAsIdentifier);
 632             nextToken();
 633             return names.error;
 634         } else if (token.kind == ENUM) {
 635             log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.EnumAsIdentifier);
 636             nextToken();
 637             return names.error;
 638         } else if (token.kind == THIS) {
 639             if (allowThisIdent) {
 640                 Name name = token.name();
 641                 nextToken();
 642                 return name;
 643             } else {
 644                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ThisAsIdentifier);
 645                 nextToken();
 646                 return names.error;
 647             }
 648         } else if (token.kind == UNDERSCORE) {
 649             if (Feature.UNDERSCORE_IDENTIFIER.allowedInSource(source)) {
 650                 log.warning(token.pos, Warnings.UnderscoreAsIdentifier);
 651             } else if (asVariable) {
 652                 checkSourceLevel(Feature.UNNAMED_VARIABLES);
 653                 if (peekToken(LBRACKET)) {
 654                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UseOfUnderscoreNotAllowedWithBrackets);
 655                 }
 656             } else {
 657                 if (preview.isEnabled() && Feature.UNNAMED_VARIABLES.allowedInSource(source)) {
 658                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UseOfUnderscoreNotAllowed);
 659                 } else {
 660                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UnderscoreAsIdentifier);
 661                 }
 662             }
 663             Name name = token.name();
 664             nextToken();
 665             return name;
 666         } else {
 667             accept(IDENTIFIER);
 668             if (allowClass && token.kind == CLASS) {
 669                 nextToken();
 670                 return names._class;
 671             }
 672             return names.error;
 673         }
 674     }
 675 
 676     /**
 677      * Qualident = Ident { DOT [Annotations] Ident }
 678      */
 679     public JCExpression qualident(boolean allowAnnos) {
 680         JCExpression t = toP(F.at(token.pos).Ident(ident()));
 681         while (token.kind == DOT) {
 682             int pos = token.pos;
 683             nextToken();
 684             List<JCAnnotation> tyannos = null;
 685             if (allowAnnos) {
 686                 tyannos = typeAnnotationsOpt();
 687             }
 688             t = toP(F.at(pos).Select(t, ident()));
 689             if (tyannos != null && tyannos.nonEmpty()) {
 690                 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
 691             }
 692         }
 693         return t;
 694     }
 695 
 696     /**
 697      * StringTemplate =
 698      *    [STRINGFRAGMENT] [EmbeddedExpression]
 699      *  | STRINGLITERAL
 700      *
 701      * EmbeddedExpression =
 702      *  LBRACE term RBRACE
 703      */
 704     JCExpression stringTemplate(JCExpression processor) {
 705         checkSourceLevel(Feature.STRING_TEMPLATES);
 706         // Disable standalone string templates
 707         if (processor == null) {
 708             log.error(DiagnosticFlag.SYNTAX, token.pos,
 709                     Errors.ProcessorMissingFromStringTemplateExpression);
 710         }
 711         int oldmode = mode;
 712         selectExprMode();
 713         Token stringToken = token;
 714         int pos = stringToken.pos;
 715         int endPos = stringToken.endPos;
 716         TokenKind kind = stringToken.kind;
 717         String string = token.stringVal();
 718         List<String> fragments = List.of(string);
 719         List<JCExpression> expressions = List.nil();
 720         nextToken();
 721         if (kind != STRINGLITERAL) {
 722             while (token.kind == STRINGFRAGMENT) {
 723                 stringToken = token;
 724                 endPos = stringToken.endPos;
 725                 string = stringToken.stringVal();
 726                 fragments = fragments.append(string);
 727                 nextToken();
 728              }
 729             while (token.pos < endPos && token.kind != DEFAULT && token.kind != ERROR) {
 730                 accept(LBRACE);
 731                 JCExpression expression = token.kind == RBRACE ? F.at(pos).Literal(TypeTag.BOT, null)
 732                                                                : term(EXPR);
 733                 expressions = expressions.append(expression);
 734                 if (token.kind != ERROR) {
 735                     accept(RBRACE);
 736                 }
 737             }
 738             // clean up remaining expression tokens if error
 739             while (token.pos < endPos && token.kind != DEFAULT) {
 740                 nextToken();
 741             }
 742             S.setPrevToken(stringToken);
 743         }
 744         JCExpression t = toP(F.at(pos).StringTemplate(processor, fragments, expressions));
 745         setMode(oldmode);
 746         return t;
 747     }
 748 
 749     JCExpression literal(Name prefix) {
 750         return literal(prefix, token.pos);
 751     }
 752 
 753     /**
 754      * Literal =
 755      *     INTLITERAL
 756      *   | LONGLITERAL
 757      *   | FLOATLITERAL
 758      *   | DOUBLELITERAL
 759      *   | CHARLITERAL
 760      *   | STRINGLITERAL
 761      *   | TRUE
 762      *   | FALSE
 763      *   | NULL
 764      */
 765     JCExpression literal(Name prefix, int pos) {
 766         JCExpression t = errorTree;
 767         switch (token.kind) {
 768         case INTLITERAL:
 769             try {
 770                 t = F.at(pos).Literal(
 771                     TypeTag.INT,
 772                     Convert.string2int(strval(prefix), token.radix()));
 773             } catch (NumberFormatException ex) {
 774                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.IntNumberTooLarge(strval(prefix)));
 775             }
 776             break;
 777         case LONGLITERAL:
 778             try {
 779                 t = F.at(pos).Literal(
 780                     TypeTag.LONG,
 781                     Long.valueOf(Convert.string2long(strval(prefix), token.radix())));
 782             } catch (NumberFormatException ex) {
 783                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.IntNumberTooLarge(strval(prefix)));
 784             }
 785             break;
 786         case FLOATLITERAL: {
 787             String proper = token.radix() == 16 ?
 788                     ("0x"+ token.stringVal()) :
 789                     token.stringVal();
 790             Float n;
 791             try {
 792                 n = Float.valueOf(proper);
 793             } catch (NumberFormatException ex) {
 794                 // error already reported in scanner
 795                 n = Float.NaN;
 796             }
 797             if (n.floatValue() == 0.0f && !isZero(proper))
 798                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooSmall);
 799             else if (n.floatValue() == Float.POSITIVE_INFINITY)
 800                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooLarge);
 801             else
 802                 t = F.at(pos).Literal(TypeTag.FLOAT, n);
 803             break;
 804         }
 805         case DOUBLELITERAL: {
 806             String proper = token.radix() == 16 ?
 807                     ("0x"+ token.stringVal()) :
 808                     token.stringVal();
 809             Double n;
 810             try {
 811                 n = Double.valueOf(proper);
 812             } catch (NumberFormatException ex) {
 813                 // error already reported in scanner
 814                 n = Double.NaN;
 815             }
 816             if (n.doubleValue() == 0.0d && !isZero(proper))
 817                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooSmall);
 818             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
 819                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooLarge);
 820             else
 821                 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
 822             break;
 823         }
 824         case CHARLITERAL:
 825             t = F.at(pos).Literal(
 826                 TypeTag.CHAR,
 827                 token.stringVal().charAt(0) + 0);
 828             break;
 829         case STRINGLITERAL:
 830             t = F.at(pos).Literal(
 831                 TypeTag.CLASS,
 832                 token.stringVal());
 833             break;
 834         case TRUE: case FALSE:
 835             t = F.at(pos).Literal(
 836                 TypeTag.BOOLEAN,
 837                 (token.kind == TRUE ? 1 : 0));
 838             break;
 839         case NULL:
 840             t = F.at(pos).Literal(
 841                 TypeTag.BOT,
 842                 null);
 843             break;
 844         default:
 845             Assert.error();
 846         }
 847         if (t == errorTree)
 848             t = F.at(pos).Erroneous();
 849         storeEnd(t, token.endPos);
 850         nextToken();
 851         return t;
 852     }
 853     //where
 854         boolean isZero(String s) {
 855             char[] cs = s.toCharArray();
 856             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
 857             int i = ((base==16) ? 2 : 0);
 858             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
 859             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
 860         }
 861 
 862         String strval(Name prefix) {
 863             String s = token.stringVal();
 864             return prefix.isEmpty() ? s : prefix + s;
 865         }
 866 
 867     /** terms can be either expressions or types.
 868      */
 869     public JCExpression parseExpression() {
 870         return term(EXPR);
 871     }
 872 
 873     /** parses patterns.
 874      */
 875     public JCPattern parsePattern(int pos, JCModifiers mods, JCExpression parsedType,
 876                                   boolean allowVar, boolean checkGuard) {
 877         JCPattern pattern;
 878         mods = mods != null ? mods : optFinal(0);
 879         JCExpression e;
 880         if (token.kind == UNDERSCORE && parsedType == null) {
 881             nextToken();
 882             checkSourceLevel(Feature.UNNAMED_VARIABLES);
 883             pattern = toP(F.at(token.pos).AnyPattern());
 884         }
 885         else {
 886             if (parsedType == null) {
 887                 boolean var = token.kind == IDENTIFIER && token.name() == names.var;
 888                 e = unannotatedType(allowVar, TYPE | NOLAMBDA);
 889                 if (var) {
 890                     e = null;
 891                 }
 892             } else {
 893                 e = parsedType;
 894             }
 895             if (token.kind == LPAREN) {
 896                 //deconstruction pattern:
 897                 checkSourceLevel(Feature.RECORD_PATTERNS);
 898                 ListBuffer<JCPattern> nested = new ListBuffer<>();
 899                 if (!peekToken(RPAREN)) {
 900                     do {
 901                         nextToken();
 902                         JCPattern nestedPattern = parsePattern(token.pos, null, null, true, false);
 903                         nested.append(nestedPattern);
 904                     } while (token.kind == COMMA);
 905                 } else {
 906                     nextToken();
 907                 }
 908                 accept(RPAREN);
 909                 pattern = toP(F.at(pos).RecordPattern(e, nested.toList()));
 910                 if (mods.annotations.nonEmpty()) {
 911                     log.error(mods.annotations.head.pos(), Errors.RecordPatternsAnnotationsNotAllowed);
 912                 }
 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.comment(CommentStyle.JAVADOC);
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.comment(CommentStyle.JAVADOC);
2833             JCModifiers mods = modifiersOpt();
2834             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
2835         }
2836         case INTERFACE:
2837         case CLASS:
2838             dc = token.comment(CommentStyle.JAVADOC);
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.comment(CommentStyle.JAVADOC);
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.comment(CommentStyle.JAVADOC)));
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.comment(CommentStyle.JAVADOC)));
2907                 }
2908             }
2909         }
2910         if (isRecordStart() && allowRecords) {
2911             dc = token.comment(CommentStyle.JAVADOC);
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                     }
3314                     break;
3315                 case UNDERSCORE:
3316                     // TODO: REFACTOR to remove the code duplication
3317                     if (typeDepth == 0 && peekToken(lookahead, tk -> tk == RPAREN || tk == COMMA)) {
3318                         return PatternResult.PATTERN;
3319                     } else if (typeDepth == 0 && peekToken(lookahead, LAX_IDENTIFIER)) {
3320                         if (parenDepth == 0) {
3321                             return PatternResult.PATTERN;
3322                         } else {
3323                             pendingResult = PatternResult.PATTERN;
3324                         }
3325                     }
3326                     break;
3327                 case DOT, QUES, EXTENDS, SUPER, COMMA: break;
3328                 case LT: typeDepth++; break;
3329                 case GTGTGT: typeDepth--;
3330                 case GTGT: typeDepth--;
3331                 case GT:
3332                     typeDepth--;
3333                     if (typeDepth == 0) {
3334                          return peekToken(lookahead, LAX_IDENTIFIER) ||
3335                                 peekToken(lookahead, tk -> tk == LPAREN) ? PatternResult.PATTERN
3336                                                                          : PatternResult.EXPRESSION;
3337                     } else if (typeDepth < 0) return PatternResult.EXPRESSION;
3338                     break;
3339                 case MONKEYS_AT:
3340                     lookahead = skipAnnotation(lookahead);
3341                     break;
3342                 case LBRACKET:
3343                     if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
3344                         return PatternResult.PATTERN;
3345                     } else if (peekToken(lookahead, RBRACKET)) {
3346                         lookahead++;
3347                         break;
3348                     } else {
3349                         // This is a potential guard, if we are already in a pattern
3350                         return pendingResult;
3351                     }
3352                 case LPAREN:
3353                     if (S.token(lookahead + 1).kind == RPAREN) {
3354                         return parenDepth != 0 && S.token(lookahead + 2).kind == ARROW
3355                                 ? PatternResult.EXPRESSION
3356                                 : PatternResult.PATTERN;
3357                     }
3358                     parenDepth++; break;
3359                 case RPAREN: parenDepth--; break;
3360                 case ARROW: return parenDepth > 0 ? PatternResult.EXPRESSION
3361                                                    : pendingResult;
3362                 default: return pendingResult;
3363             }
3364             lookahead++;
3365         }
3366     }
3367 
3368     private enum PatternResult {
3369         EXPRESSION,
3370         PATTERN;
3371     }
3372 
3373     /** MoreStatementExpressions = { COMMA StatementExpression }
3374      */
3375     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
3376                                                                     JCExpression first,
3377                                                                     T stats) {
3378         // This Exec is a "StatementExpression"; it subsumes no terminating token
3379         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
3380         while (token.kind == COMMA) {
3381             nextToken();
3382             pos = token.pos;
3383             JCExpression t = parseExpression();
3384             // This Exec is a "StatementExpression"; it subsumes no terminating token
3385             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
3386         }
3387         return stats;
3388     }
3389 
3390     /** ForInit = StatementExpression MoreStatementExpressions
3391      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
3392      */
3393     List<JCStatement> forInit() {
3394         ListBuffer<JCStatement> stats = new ListBuffer<>();
3395         int pos = token.pos;
3396         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3397             return variableDeclarators(optFinal(0), parseType(true), stats, true).toList();
3398         } else {
3399             JCExpression t = term(EXPR | TYPE);
3400             if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3401                 return variableDeclarators(modifiersOpt(), t, stats, true).toList();
3402             } else if (wasTypeMode() && token.kind == COLON) {
3403                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.BadInitializer("for-loop"));
3404                 return List.of((JCStatement)F.at(pos).VarDef(modifiersOpt(), names.error, t, null));
3405             } else {
3406                 return moreStatementExpressions(pos, t, stats).toList();
3407             }
3408         }
3409     }
3410 
3411     /** ForUpdate = StatementExpression MoreStatementExpressions
3412      */
3413     List<JCExpressionStatement> forUpdate() {
3414         return moreStatementExpressions(token.pos,
3415                                         parseExpression(),
3416                                         new ListBuffer<JCExpressionStatement>()).toList();
3417     }
3418 
3419     /** AnnotationsOpt = { '@' Annotation }
3420      *
3421      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3422      */
3423     protected List<JCAnnotation> annotationsOpt(Tag kind) {
3424         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
3425         ListBuffer<JCAnnotation> buf = new ListBuffer<>();
3426         int prevmode = mode;
3427         while (token.kind == MONKEYS_AT) {
3428             int pos = token.pos;
3429             nextToken();
3430             buf.append(annotation(pos, kind));
3431         }
3432         setLastMode(mode);
3433         setMode(prevmode);
3434         List<JCAnnotation> annotations = buf.toList();
3435 
3436         return annotations;
3437     }
3438 
3439     List<JCAnnotation> typeAnnotationsOpt() {
3440         List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION);
3441         return annotations;
3442     }
3443 
3444     /** ModifiersOpt = { Modifier }
3445      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
3446      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
3447      *           | "@" Annotation
3448      */
3449     protected JCModifiers modifiersOpt() {
3450         return modifiersOpt(null);
3451     }
3452     protected JCModifiers modifiersOpt(JCModifiers partial) {
3453         long flags;
3454         ListBuffer<JCAnnotation> annotations = new ListBuffer<>();
3455         int pos;
3456         if (partial == null) {
3457             flags = 0;
3458             pos = token.pos;
3459         } else {
3460             flags = partial.flags;
3461             annotations.appendList(partial.annotations);
3462             pos = partial.pos;
3463         }
3464         if (token.deprecatedFlag()) {
3465             flags |= Flags.DEPRECATED;
3466         }
3467         int lastPos;
3468     loop:
3469         while (true) {
3470             long flag;
3471             switch (token.kind) {
3472             case PRIVATE     : flag = Flags.PRIVATE; break;
3473             case PROTECTED   : flag = Flags.PROTECTED; break;
3474             case PUBLIC      : flag = Flags.PUBLIC; break;
3475             case STATIC      : flag = Flags.STATIC; break;
3476             case TRANSIENT   : flag = Flags.TRANSIENT; break;
3477             case FINAL       : flag = Flags.FINAL; break;
3478             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3479             case NATIVE      : flag = Flags.NATIVE; break;
3480             case VOLATILE    : flag = Flags.VOLATILE; break;
3481             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3482             case STRICTFP    : flag = Flags.STRICTFP; break;
3483             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3484             case DEFAULT     : flag = Flags.DEFAULT; break;
3485             case ERROR       : flag = 0; nextToken(); break;
3486             case IDENTIFIER  : {
3487                 if (isNonSealedClassStart(false)) {
3488                     flag = Flags.NON_SEALED;
3489                     nextToken();
3490                     nextToken();
3491                     break;
3492                 }
3493                 if (isSealedClassStart(false)) {
3494                     checkSourceLevel(Feature.SEALED_CLASSES);
3495                     flag = Flags.SEALED;
3496                     break;
3497                 }
3498                 break loop;
3499             }
3500             default: break loop;
3501             }
3502             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3503             lastPos = token.pos;
3504             nextToken();
3505             if (flag == Flags.ANNOTATION) {
3506                 if (token.kind != INTERFACE) {
3507                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3508                     // if first modifier is an annotation, set pos to annotation's.
3509                     if (flags == 0 && annotations.isEmpty())
3510                         pos = ann.pos;
3511                     annotations.append(ann);
3512                     flag = 0;
3513                 }
3514             }
3515             flags |= flag;
3516         }
3517         switch (token.kind) {
3518         case ENUM: flags |= Flags.ENUM; break;
3519         case INTERFACE: flags |= Flags.INTERFACE; break;
3520         default: break;
3521         }
3522 
3523         /* A modifiers tree with no modifier tokens or annotations
3524          * has no text position. */
3525         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
3526             pos = Position.NOPOS;
3527 
3528         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
3529         if (pos != Position.NOPOS)
3530             storeEnd(mods, S.prevToken().endPos);
3531         return mods;
3532     }
3533 
3534     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
3535      *
3536      * @param pos position of "@" token
3537      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3538      */
3539     JCAnnotation annotation(int pos, Tag kind) {
3540         // accept(AT); // AT consumed by caller
3541         JCTree ident = qualident(false);
3542         List<JCExpression> fieldValues = annotationFieldValuesOpt();
3543         JCAnnotation ann;
3544         if (kind == Tag.ANNOTATION) {
3545             ann = F.at(pos).Annotation(ident, fieldValues);
3546         } else if (kind == Tag.TYPE_ANNOTATION) {
3547             ann = F.at(pos).TypeAnnotation(ident, fieldValues);
3548         } else {
3549             throw new AssertionError("Unhandled annotation kind: " + kind);
3550         }
3551 
3552         storeEnd(ann, S.prevToken().endPos);
3553         return ann;
3554     }
3555 
3556     List<JCExpression> annotationFieldValuesOpt() {
3557         return (token.kind == LPAREN) ? annotationFieldValues() : List.nil();
3558     }
3559 
3560     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
3561     List<JCExpression> annotationFieldValues() {
3562         accept(LPAREN);
3563         ListBuffer<JCExpression> buf = new ListBuffer<>();
3564         if (token.kind != RPAREN) {
3565             buf.append(annotationFieldValue());
3566             while (token.kind == COMMA) {
3567                 nextToken();
3568                 buf.append(annotationFieldValue());
3569             }
3570         }
3571         accept(RPAREN);
3572         return buf.toList();
3573     }
3574 
3575     /** AnnotationFieldValue    = AnnotationValue
3576      *                          | Identifier "=" AnnotationValue
3577      */
3578     JCExpression annotationFieldValue() {
3579         if (LAX_IDENTIFIER.test(token.kind)) {
3580             selectExprMode();
3581             JCExpression t1 = term1();
3582             if (t1.hasTag(IDENT) && token.kind == EQ) {
3583                 int pos = token.pos;
3584                 accept(EQ);
3585                 JCExpression v = annotationValue();
3586                 return toP(F.at(pos).Assign(t1, v));
3587             } else {
3588                 return t1;
3589             }
3590         }
3591         return annotationValue();
3592     }
3593 
3594     /* AnnotationValue          = ConditionalExpression
3595      *                          | Annotation
3596      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
3597      */
3598     JCExpression annotationValue() {
3599         int pos;
3600         switch (token.kind) {
3601         case MONKEYS_AT:
3602             pos = token.pos;
3603             nextToken();
3604             return annotation(pos, Tag.ANNOTATION);
3605         case LBRACE:
3606             pos = token.pos;
3607             accept(LBRACE);
3608             ListBuffer<JCExpression> buf = new ListBuffer<>();
3609             if (token.kind == COMMA) {
3610                 nextToken();
3611             } else if (token.kind != RBRACE) {
3612                 buf.append(annotationValue());
3613                 while (token.kind == COMMA) {
3614                     nextToken();
3615                     if (token.kind == RBRACE) break;
3616                     buf.append(annotationValue());
3617                 }
3618             }
3619             accept(RBRACE, tk -> Errors.AnnotationMissingElementValue);
3620             return toP(F.at(pos).NewArray(null, List.nil(), buf.toList()));
3621         default:
3622             selectExprMode();
3623             return term1();
3624         }
3625     }
3626 
3627     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
3628      */
3629     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
3630                                                                          JCExpression type,
3631                                                                          T vdefs,
3632                                                                          boolean localDecl)
3633     {
3634         return variableDeclaratorsRest(token.pos, mods, type, identOrUnderscore(), false, null, vdefs, localDecl);
3635     }
3636 
3637     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
3638      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
3639      *
3640      *  @param reqInit  Is an initializer always required?
3641      *  @param dc       The documentation comment for the variable declarations, or null.
3642      */
3643     protected <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
3644                                                                      JCModifiers mods,
3645                                                                      JCExpression type,
3646                                                                      Name name,
3647                                                                      boolean reqInit,
3648                                                                      Comment dc,
3649                                                                      T vdefs,
3650                                                                      boolean localDecl)
3651     {
3652         JCVariableDecl head = variableDeclaratorRest(pos, mods, type, name, reqInit, dc, localDecl, false);
3653         vdefs.append(head);
3654         while (token.kind == COMMA) {
3655             // All but last of multiple declarators subsume a comma
3656             storeEnd((JCTree)vdefs.last(), token.endPos);
3657             nextToken();
3658             vdefs.append(variableDeclarator(mods, type, reqInit, dc, localDecl));
3659         }
3660         return vdefs;
3661     }
3662 
3663     /** VariableDeclarator = Ident VariableDeclaratorRest
3664      *  ConstantDeclarator = Ident ConstantDeclaratorRest
3665      */
3666     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc, boolean localDecl) {
3667         return variableDeclaratorRest(token.pos, mods, type, identOrUnderscore(), reqInit, dc, localDecl, true);
3668     }
3669 
3670     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
3671      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
3672      *
3673      *  @param reqInit  Is an initializer always required?
3674      *  @param dc       The documentation comment for the variable declarations, or null.
3675      */
3676     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
3677                                   boolean reqInit, Comment dc, boolean localDecl, boolean compound) {
3678         boolean declaredUsingVar = false;
3679         JCExpression init = null;
3680         type = bracketsOpt(type);
3681 
3682         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
3683             if (!localDecl) {
3684                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.UseOfUnderscoreNotAllowed);
3685             }
3686             name = names.empty;
3687         }
3688 
3689         if (token.kind == EQ) {
3690             nextToken();
3691             init = variableInitializer();
3692         }
3693         else if (reqInit) syntaxError(token.pos, Errors.Expected(EQ));
3694 
3695         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.empty
3696                 && localDecl
3697                 && init == null
3698                 && token.kind != COLON) { // if its unnamed local variable, it needs to have an init unless in enhanced-for
3699             syntaxError(token.pos, Errors.Expected(EQ));
3700         }
3701 
3702         int startPos = Position.NOPOS;
3703         JCTree elemType = TreeInfo.innermostType(type, true);
3704         if (elemType.hasTag(IDENT)) {
3705             Name typeName = ((JCIdent) elemType).name;
3706             if (restrictedTypeNameStartingAtSource(typeName, pos, !compound && localDecl) != null) {
3707                 if (typeName != names.var) {
3708                     reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedHere(typeName));
3709                 } else if (type.hasTag(TYPEARRAY) && !compound) {
3710                     //error - 'var' and arrays
3711                     reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedArray(typeName));
3712                 } else {
3713                     declaredUsingVar = true;
3714                     if (compound)
3715                         //error - 'var' in compound local var decl
3716                         reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
3717                     startPos = TreeInfo.getStartPos(mods);
3718                     if (startPos == Position.NOPOS)
3719                         startPos = TreeInfo.getStartPos(type);
3720                     //implicit type
3721                     type = null;
3722                 }
3723             }
3724         }
3725         JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init, declaredUsingVar));
3726         attach(result, dc);
3727         result.startPos = startPos;
3728         return result;
3729     }
3730 
3731     Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
3732         switch (e.getTag()) {
3733             case IDENT:
3734                 return restrictedTypeNameStartingAtSource(((JCIdent)e).name, e.pos, shouldWarn) != null ? ((JCIdent)e).name : null;
3735             case TYPEARRAY:
3736                 return restrictedTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
3737             default:
3738                 return null;
3739         }
3740     }
3741 
3742     Source restrictedTypeNameStartingAtSource(Name name, int pos, boolean shouldWarn) {
3743         if (name == names.var) {
3744             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3745                 return Source.JDK10;
3746             } else if (shouldWarn) {
3747                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3748             }
3749         }
3750         if (name == names.yield) {
3751             if (allowYieldStatement) {
3752                 return Source.JDK14;
3753             } else if (shouldWarn) {
3754                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3755             }
3756         }
3757         if (name == names.record) {
3758             if (allowRecords) {
3759                 return Source.JDK14;
3760             } else if (shouldWarn) {
3761                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3762             }
3763         }
3764         if (name == names.sealed) {
3765             if (allowSealedTypes) {
3766                 return Source.JDK15;
3767             } else if (shouldWarn) {
3768                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3769             }
3770         }
3771         if (name == names.permits) {
3772             if (allowSealedTypes) {
3773                 return Source.JDK15;
3774             } else if (shouldWarn) {
3775                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3776             }
3777         }
3778         return null;
3779     }
3780 
3781     /** VariableDeclaratorId = Ident BracketsOpt
3782      */
3783     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
3784         int pos = token.pos;
3785         Name name;
3786         if (allowThisIdent ||
3787             !lambdaParameter ||
3788             LAX_IDENTIFIER.test(token.kind) ||
3789             mods.flags != Flags.PARAMETER ||
3790             mods.annotations.nonEmpty()) {
3791             JCExpression pn;
3792             if (token.kind == UNDERSCORE && (catchParameter || lambdaParameter)) {
3793                 pn = toP(F.at(token.pos).Ident(identOrUnderscore()));
3794             } else {
3795                 pn = qualident(false);
3796             }
3797             if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
3798                 name = ((JCIdent)pn).name;
3799             } else if (lambdaParameter && type == null) {
3800                 // we have a lambda parameter that is not an identifier this is a syntax error
3801                 type = pn;
3802                 name = names.empty;
3803                 reportSyntaxError(pos, Errors.Expected(IDENTIFIER));
3804             } else {
3805                 if (allowThisIdent) {
3806                     if ((mods.flags & Flags.VARARGS) != 0) {
3807                         log.error(token.pos, Errors.VarargsAndReceiver);
3808                     }
3809                     if (token.kind == LBRACKET) {
3810                         log.error(token.pos, Errors.ArrayAndReceiver);
3811                     }
3812                     if (pn.hasTag(Tag.SELECT) && ((JCFieldAccess)pn).name != names._this) {
3813                         log.error(token.pos, Errors.WrongReceiver);
3814                     }
3815                 }
3816                 return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
3817             }
3818         } else {
3819             /** if it is a lambda parameter and the token kind is not an identifier,
3820              *  and there are no modifiers or annotations, then this means that the compiler
3821              *  supposed the lambda to be explicit but it can contain a mix of implicit,
3822              *  var or explicit parameters. So we assign the error name to the parameter name
3823              *  instead of issuing an error and analyze the lambda parameters as a whole at
3824              *  a higher level.
3825              */
3826             name = names.error;
3827         }
3828         if ((mods.flags & Flags.VARARGS) != 0 &&
3829                 token.kind == LBRACKET) {
3830             log.error(token.pos, Errors.VarargsAndOldArraySyntax);
3831         }
3832         if (recordComponent && token.kind == LBRACKET) {
3833             log.error(token.pos, Errors.RecordComponentAndOldArraySyntax);
3834         }
3835         type = bracketsOpt(type);
3836 
3837         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
3838             name = names.empty;
3839         }
3840 
3841         return toP(F.at(pos).VarDef(mods, name, type, null,
3842                 type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var));
3843     }
3844 
3845     /** Resources = Resource { ";" Resources }
3846      */
3847     List<JCTree> resources() {
3848         ListBuffer<JCTree> defs = new ListBuffer<>();
3849         defs.append(resource());
3850         while (token.kind == SEMI) {
3851             // All but last of multiple declarators must subsume a semicolon
3852             storeEnd(defs.last(), token.endPos);
3853             int semiColonPos = token.pos;
3854             nextToken();
3855             if (token.kind == RPAREN) { // Optional trailing semicolon
3856                                        // after last resource
3857                 break;
3858             }
3859             defs.append(resource());
3860         }
3861         return defs.toList();
3862     }
3863 
3864     /** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression
3865      *           | Expression
3866      */
3867     protected JCTree resource() {
3868         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3869             JCModifiers mods = optFinal(0);
3870             JCExpression t = parseType(true);
3871             return variableDeclaratorRest(token.pos, mods, t, identOrUnderscore(), true, null, true, false);
3872         }
3873         JCExpression t = term(EXPR | TYPE);
3874         if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3875             JCModifiers mods = F.Modifiers(0);
3876             return variableDeclaratorRest(token.pos, mods, t, identOrUnderscore(), true, null, true, false);
3877         } else {
3878             checkSourceLevel(Feature.EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES);
3879             if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
3880                 log.error(t.pos(), Errors.TryWithResourcesExprNeedsVar);
3881             }
3882 
3883             return t;
3884         }
3885     }
3886 
3887     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
3888      */
3889     public JCTree.JCCompilationUnit parseCompilationUnit() {
3890         Token firstToken = token;
3891         JCModifiers mods = null;
3892         boolean consumedToplevelDoc = false;
3893         boolean seenImport = false;
3894         boolean seenPackage = false;
3895         ListBuffer<JCTree> defs = new ListBuffer<>();
3896         if (token.kind == MONKEYS_AT)
3897             mods = modifiersOpt();
3898 
3899         if (token.kind == PACKAGE) {
3900             int packagePos = token.pos;
3901             List<JCAnnotation> annotations = List.nil();
3902             seenPackage = true;
3903             if (mods != null) {
3904                 checkNoMods(mods.flags & ~Flags.DEPRECATED);
3905                 annotations = mods.annotations;
3906                 mods = null;
3907             }
3908             nextToken();
3909             JCExpression pid = qualident(false);
3910             accept(SEMI);
3911             JCPackageDecl pd = toP(F.at(packagePos).PackageDecl(annotations, pid));
3912             attach(pd, firstToken.comment(CommentStyle.JAVADOC));
3913             consumedToplevelDoc = true;
3914             defs.append(pd);
3915         }
3916 
3917         boolean firstTypeDecl = true;   // have we see a class, enum, or interface declaration yet?
3918         boolean isUnnamedClass = false;
3919         while (token.kind != EOF) {
3920             if (token.pos <= endPosTable.errorEndPos) {
3921                 // error recovery
3922                 skip(firstTypeDecl, false, false, false);
3923                 if (token.kind == EOF)
3924                     break;
3925             }
3926             // JLS 7.3 doesn't allow extra semicolons after package or import declarations,
3927             // but here we try to provide a more helpful error message if we encounter any.
3928             // Do that by slurping in as many semicolons as possible, and then seeing what
3929             // comes after before deciding how best to handle them.
3930             ListBuffer<JCTree> semiList = new ListBuffer<>();
3931             while (firstTypeDecl && mods == null && token.kind == SEMI) {
3932                 semiList.append(toP(F.at(token.pos).Skip()));
3933                 nextToken();
3934             }
3935             if (firstTypeDecl && mods == null && token.kind == IMPORT) {
3936                 if (!semiList.isEmpty()) {
3937                     if (source.compareTo(Source.JDK21) >= 0)
3938                         reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
3939                     else
3940                         log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
3941                 }
3942                 seenImport = true;
3943                 defs.append(importDeclaration());
3944             } else {
3945                 Comment docComment = token.comment(CommentStyle.JAVADOC);
3946                 if (firstTypeDecl && !seenImport && !seenPackage) {
3947                     docComment = firstToken.comment(CommentStyle.JAVADOC);
3948                     consumedToplevelDoc = true;
3949                 }
3950                 if (mods != null || token.kind != SEMI)
3951                     mods = modifiersOpt(mods);
3952                 if (firstTypeDecl && token.kind == IDENTIFIER) {
3953                     if (!semiList.isEmpty()) {
3954                         if (source.compareTo(Source.JDK21) >= 0)
3955                             reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
3956                         else
3957                             log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
3958                     }
3959                     ModuleKind kind = ModuleKind.STRONG;
3960                     if (token.name() == names.open) {
3961                         kind = ModuleKind.OPEN;
3962                         nextToken();
3963                     }
3964                     if (token.kind == IDENTIFIER && token.name() == names.module) {
3965                         if (mods != null) {
3966                             checkNoMods(mods.flags & ~Flags.DEPRECATED);
3967                         }
3968                         defs.append(moduleDecl(mods, kind, docComment));
3969                         consumedToplevelDoc = true;
3970                         break;
3971                     } else if (kind != ModuleKind.STRONG) {
3972                         reportSyntaxError(token.pos, Errors.ExpectedModule);
3973                     }
3974                 }
3975 
3976                 defs.appendList(semiList.toList());
3977                 boolean isTopLevelMethodOrField = false;
3978 
3979                 // Do to a significant number of existing negative tests
3980                 // this code speculatively tests to see if a top level method
3981                 // or field can parse. If the method or field can parse then
3982                 // it is parsed. Otherwise, parsing continues as though
3983                 // unnamed classes did not exist and error reporting
3984                 // is the same as in the past.
3985                 if (Feature.UNNAMED_CLASSES.allowedInSource(source) && !isDeclaration()) {
3986                     final JCModifiers finalMods = mods;
3987                     JavacParser speculative = new VirtualParser(this);
3988                     List<JCTree> speculativeResult =
3989                             speculative.topLevelMethodOrFieldDeclaration(finalMods);
3990                     if (speculativeResult.head.hasTag(METHODDEF) ||
3991                         speculativeResult.head.hasTag(VARDEF)) {
3992                         isTopLevelMethodOrField = true;
3993                     }
3994                 }
3995 
3996                 if (isTopLevelMethodOrField) {
3997                     checkSourceLevel(token.pos, Feature.UNNAMED_CLASSES);
3998                     defs.appendList(topLevelMethodOrFieldDeclaration(mods));
3999                     isUnnamedClass = true;
4000                 } else if (token.kind != EOF) {
4001                     JCTree def = typeDeclaration(mods, docComment);
4002                     if (def instanceof JCExpressionStatement statement)
4003                         def = statement.expr;
4004                     defs.append(def);
4005                 }
4006 
4007                 mods = null;
4008                 firstTypeDecl = false;
4009             }
4010         }
4011         List<JCTree> topLevelDefs = isUnnamedClass ?  constructUnnamedClass(defs.toList()) : defs.toList();
4012         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(topLevelDefs);
4013         if (!consumedToplevelDoc)
4014             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
4015         if (defs.isEmpty())
4016             storeEnd(toplevel, S.prevToken().endPos);
4017         if (keepDocComments)
4018             toplevel.docComments = docComments;
4019         if (keepLineMap)
4020             toplevel.lineMap = S.getLineMap();
4021         this.endPosTable.setParser(null); // remove reference to parser
4022         toplevel.endPositions = this.endPosTable;
4023         return toplevel;
4024     }
4025 
4026     // Restructure top level to be an unnamed class.
4027     private List<JCTree> constructUnnamedClass(List<JCTree> origDefs) {
4028         ListBuffer<JCTree> topDefs = new ListBuffer<>();
4029         ListBuffer<JCTree> defs = new ListBuffer<>();
4030 
4031         for (JCTree def : origDefs) {
4032             if (def.hasTag(Tag.PACKAGEDEF)) {
4033                 log.error(def.pos(), Errors.UnnamedClassShouldNotHavePackageDeclaration);
4034             } else if (def.hasTag(Tag.IMPORT)) {
4035                 topDefs.append(def);
4036             } else if (!def.hasTag(Tag.SKIP)) {
4037                 defs.append(def);
4038             }
4039         }
4040 
4041         int primaryPos = getStartPos(defs.first());
4042         String simplename = PathFileObject.getSimpleName(log.currentSourceFile());
4043 
4044         if (simplename.endsWith(".java")) {
4045             simplename = simplename.substring(0, simplename.length() - ".java".length());
4046         }
4047         if (!SourceVersion.isIdentifier(simplename) || SourceVersion.isKeyword(simplename)) {
4048             log.error(primaryPos, Errors.BadFileName(simplename));
4049         }
4050 
4051         Name name = names.fromString(simplename);
4052         JCModifiers unnamedMods = F.at(Position.NOPOS)
4053                 .Modifiers(Flags.FINAL|Flags.SYNTHETIC|Flags.UNNAMED_CLASS, List.nil());
4054         JCClassDecl unnamed = F.at(primaryPos).ClassDef(
4055                 unnamedMods, name, List.nil(), null, List.nil(), List.nil(),
4056                 defs.toList());
4057         topDefs.append(unnamed);
4058         return topDefs.toList();
4059     }
4060 
4061     JCModuleDecl moduleDecl(JCModifiers mods, ModuleKind kind, Comment dc) {
4062         int pos = token.pos;
4063         checkSourceLevel(Feature.MODULES);
4064 
4065         nextToken();
4066         JCExpression name = qualident(false);
4067         List<JCDirective> directives = null;
4068 
4069         accept(LBRACE);
4070         directives = moduleDirectiveList();
4071         accept(RBRACE);
4072         accept(EOF);
4073 
4074         JCModuleDecl result = toP(F.at(pos).ModuleDef(mods, kind, name, directives));
4075         attach(result, dc);
4076         return result;
4077     }
4078 
4079     List<JCDirective> moduleDirectiveList() {
4080         ListBuffer<JCDirective> defs = new ListBuffer<>();
4081         while (token.kind == IDENTIFIER) {
4082             int pos = token.pos;
4083             if (token.name() == names.requires) {
4084                 nextToken();
4085                 boolean isTransitive = false;
4086                 boolean isStaticPhase = false;
4087             loop:
4088                 while (true) {
4089                     switch (token.kind) {
4090                         case IDENTIFIER:
4091                             if (token.name() == names.transitive && !isTransitive) {
4092                                 Token t1 = S.token(1);
4093                                 if (t1.kind == SEMI || t1.kind == DOT) {
4094                                     break loop;
4095                                 }
4096                                 isTransitive = true;
4097                                 break;
4098                             } else {
4099                                 break loop;
4100                             }
4101                         case STATIC:
4102                             if (isStaticPhase) {
4103                                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
4104                             }
4105                             isStaticPhase = true;
4106                             break;
4107                         default:
4108                             break loop;
4109                     }
4110                     nextToken();
4111                 }
4112                 JCExpression moduleName = qualident(false);
4113                 accept(SEMI);
4114                 defs.append(toP(F.at(pos).Requires(isTransitive, isStaticPhase, moduleName)));
4115             } else if (token.name() == names.exports || token.name() == names.opens) {
4116                 boolean exports = token.name() == names.exports;
4117                 nextToken();
4118                 JCExpression pkgName = qualident(false);
4119                 List<JCExpression> moduleNames = null;
4120                 if (token.kind == IDENTIFIER && token.name() == names.to) {
4121                     nextToken();
4122                     moduleNames = qualidentList(false);
4123                 }
4124                 accept(SEMI);
4125                 JCDirective d;
4126                 if (exports) {
4127                     d = F.at(pos).Exports(pkgName, moduleNames);
4128                 } else {
4129                     d = F.at(pos).Opens(pkgName, moduleNames);
4130                 }
4131                 defs.append(toP(d));
4132             } else if (token.name() == names.provides) {
4133                 nextToken();
4134                 JCExpression serviceName = qualident(false);
4135                 List<JCExpression> implNames;
4136                 if (token.kind == IDENTIFIER && token.name() == names.with) {
4137                     nextToken();
4138                     implNames = qualidentList(false);
4139                 } else {
4140                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ExpectedStr("'" + names.with + "'"));
4141                     implNames = List.nil();
4142                 }
4143                 accept(SEMI);
4144                 defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
4145             } else if (token.name() == names.uses) {
4146                 nextToken();
4147                 JCExpression service = qualident(false);
4148                 accept(SEMI);
4149                 defs.append(toP(F.at(pos).Uses(service)));
4150             } else {
4151                 setErrorEndPos(pos);
4152                 reportSyntaxError(pos, Errors.InvalidModuleDirective);
4153                 break;
4154             }
4155         }
4156         return defs.toList();
4157     }
4158 
4159     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
4160      */
4161     protected JCTree importDeclaration() {
4162         int pos = token.pos;
4163         nextToken();
4164         boolean importStatic = false;
4165         if (token.kind == STATIC) {
4166             importStatic = true;
4167             nextToken();
4168         }
4169         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
4170         do {
4171             int pos1 = token.pos;
4172             accept(DOT);
4173             if (token.kind == STAR) {
4174                 pid = to(F.at(pos1).Select(pid, names.asterisk));
4175                 nextToken();
4176                 break;
4177             } else {
4178                 pid = toP(F.at(pos1).Select(pid, ident()));
4179             }
4180         } while (token.kind == DOT);
4181         accept(SEMI);
4182         return toP(F.at(pos).Import((JCFieldAccess)pid, importStatic));
4183     }
4184 
4185     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
4186      *                  | ";"
4187      */
4188     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
4189         int pos = token.pos;
4190         if (mods == null && token.kind == SEMI) {
4191             nextToken();
4192             return toP(F.at(pos).Skip());
4193         } else {
4194             return classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
4195         }
4196     }
4197 
4198     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
4199      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
4200      *  @param mods     Any modifiers starting the class or interface declaration
4201      *  @param dc       The documentation comment for the class, or null.
4202      */
4203     protected JCStatement classOrRecordOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
4204         if (token.kind == CLASS) {
4205             return classDeclaration(mods, dc);
4206         } if (isRecordStart()) {
4207             return recordDeclaration(mods, dc);
4208         } else if (token.kind == INTERFACE) {
4209             return interfaceDeclaration(mods, dc);
4210         } else if (token.kind == ENUM) {
4211             return enumDeclaration(mods, dc);
4212         } else {
4213             int pos = token.pos;
4214             List<JCTree> errs;
4215             if (LAX_IDENTIFIER.test(token.kind)) {
4216                 errs = List.of(mods, toP(F.at(pos).Ident(ident())));
4217                 setErrorEndPos(token.pos);
4218             } else {
4219                 errs = List.of(mods);
4220             }
4221 
4222             JCDiagnostic.Error error;
4223             if (parseModuleInfo) {
4224                 error = Errors.ExpectedModuleOrOpen;
4225             } else if (allowRecords) {
4226                 error = Errors.Expected4(CLASS, INTERFACE, ENUM, "record");
4227             } else {
4228                 error = Errors.Expected3(CLASS, INTERFACE, ENUM);
4229             }
4230             return toP(F.Exec(syntaxError(pos, errs, error)));
4231 
4232         }
4233     }
4234 
4235     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
4236      *                     [IMPLEMENTS TypeList] ClassBody
4237      *  @param mods    The modifiers starting the class declaration
4238      *  @param dc       The documentation comment for the class, or null.
4239      */
4240     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
4241         int pos = token.pos;
4242         accept(CLASS);
4243         Name name = typeName();
4244 
4245         List<JCTypeParameter> typarams = typeParametersOpt();
4246 
4247         JCExpression extending = null;
4248         if (token.kind == EXTENDS) {
4249             nextToken();
4250             extending = parseType();
4251         }
4252         List<JCExpression> implementing = List.nil();
4253         if (token.kind == IMPLEMENTS) {
4254             nextToken();
4255             implementing = typeList();
4256         }
4257         List<JCExpression> permitting = permitsClause(mods, "class");
4258         List<JCTree> defs = classInterfaceOrRecordBody(name, false, false);
4259         JCClassDecl result = toP(F.at(pos).ClassDef(
4260             mods, name, typarams, extending, implementing, permitting, defs));
4261         attach(result, dc);
4262         return result;
4263     }
4264 
4265     protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) {
4266         int pos = token.pos;
4267         nextToken();
4268         mods.flags |= Flags.RECORD;
4269         Name name = typeName();
4270 
4271         List<JCTypeParameter> typarams = typeParametersOpt();
4272 
4273         List<JCVariableDecl> headerFields = formalParameters(false, true);
4274 
4275         List<JCExpression> implementing = List.nil();
4276         if (token.kind == IMPLEMENTS) {
4277             nextToken();
4278             implementing = typeList();
4279         }
4280         List<JCTree> defs = classInterfaceOrRecordBody(name, false, true);
4281         java.util.List<JCVariableDecl> fields = new ArrayList<>();
4282         for (JCVariableDecl field : headerFields) {
4283             fields.add(field);
4284         }
4285         for (JCTree def : defs) {
4286             if (def.hasTag(METHODDEF)) {
4287                 JCMethodDecl methDef = (JCMethodDecl) def;
4288                 if (methDef.name == names.init && methDef.params.isEmpty() && (methDef.mods.flags & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0) {
4289                     ListBuffer<JCVariableDecl> tmpParams = new ListBuffer<>();
4290                     for (JCVariableDecl param : headerFields) {
4291                         tmpParams.add(F.at(param)
4292                                 // we will get flags plus annotations from the record component
4293                                 .VarDef(F.Modifiers(Flags.PARAMETER | Flags.GENERATED_MEMBER | Flags.MANDATED | param.mods.flags & Flags.VARARGS,
4294                                         param.mods.annotations),
4295                                 param.name, param.vartype, null));
4296                     }
4297                     methDef.params = tmpParams.toList();
4298                 }
4299             }
4300         }
4301         for (int i = fields.size() - 1; i >= 0; i--) {
4302             JCVariableDecl field = fields.get(i);
4303             defs = defs.prepend(field);
4304         }
4305         JCClassDecl result = toP(F.at(pos).ClassDef(mods, name, typarams, null, implementing, defs));
4306         attach(result, dc);
4307         return result;
4308     }
4309 
4310     Name typeName() {
4311         int pos = token.pos;
4312         Name name = ident();
4313         Source source = restrictedTypeNameStartingAtSource(name, pos, true);
4314         if (source != null) {
4315             reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, source));
4316         }
4317         return name;
4318     }
4319 
4320     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
4321      *                         [EXTENDS TypeList] InterfaceBody
4322      *  @param mods    The modifiers starting the interface declaration
4323      *  @param dc       The documentation comment for the interface, or null.
4324      */
4325     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
4326         int pos = token.pos;
4327         accept(INTERFACE);
4328 
4329         Name name = typeName();
4330 
4331         List<JCTypeParameter> typarams = typeParametersOpt();
4332 
4333         List<JCExpression> extending = List.nil();
4334         if (token.kind == EXTENDS) {
4335             nextToken();
4336             extending = typeList();
4337         }
4338         List<JCExpression> permitting = permitsClause(mods, "interface");
4339         List<JCTree> defs;
4340         defs = classInterfaceOrRecordBody(name, true, false);
4341         JCClassDecl result = toP(F.at(pos).ClassDef(
4342             mods, name, typarams, null, extending, permitting, defs));
4343         attach(result, dc);
4344         return result;
4345     }
4346 
4347     List<JCExpression> permitsClause(JCModifiers mods, String classOrInterface) {
4348         if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
4349             checkSourceLevel(Feature.SEALED_CLASSES);
4350             if ((mods.flags & Flags.SEALED) == 0) {
4351                 log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed(classOrInterface)));
4352             }
4353             nextToken();
4354             return qualidentList(false);
4355         }
4356         return List.nil();
4357     }
4358 
4359     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
4360      *  @param mods    The modifiers starting the enum declaration
4361      *  @param dc       The documentation comment for the enum, or null.
4362      */
4363     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
4364         int pos = token.pos;
4365         accept(ENUM);
4366 
4367         Name name = typeName();
4368 
4369         int typeNamePos = token.pos;
4370         List<JCTypeParameter> typarams = typeParametersOpt(true);
4371         if (typarams == null || !typarams.isEmpty()) {
4372             int errorPosition = typarams == null
4373                     ? typeNamePos
4374                     : typarams.head.pos;
4375             log.error(DiagnosticFlag.SYNTAX, errorPosition, Errors.EnumCantBeGeneric);
4376         }
4377 
4378         List<JCExpression> implementing = List.nil();
4379         if (token.kind == IMPLEMENTS) {
4380             nextToken();
4381             implementing = typeList();
4382         }
4383 
4384         List<JCTree> defs = enumBody(name);
4385         mods.flags |= Flags.ENUM;
4386         JCClassDecl result = toP(F.at(pos).
4387             ClassDef(mods, name, List.nil(),
4388                      null, implementing, defs));
4389         attach(result, dc);
4390         return result;
4391     }
4392 
4393     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
4394      *                  [ ";" {ClassBodyDeclaration} ] "}"
4395      */
4396     List<JCTree> enumBody(Name enumName) {
4397         accept(LBRACE);
4398         ListBuffer<JCTree> defs = new ListBuffer<>();
4399         boolean wasSemi = false;
4400         boolean hasStructuralErrors = false;
4401         boolean wasError = false;
4402         if (token.kind == COMMA) {
4403             nextToken();
4404             if (token.kind == SEMI) {
4405                 wasSemi = true;
4406                 nextToken();
4407             } else if (token.kind != RBRACE) {
4408                 reportSyntaxError(S.prevToken().endPos,
4409                                   Errors.Expected2(RBRACE, SEMI));
4410                 wasError = true;
4411             }
4412         }
4413         while (token.kind != RBRACE && token.kind != EOF) {
4414             if (token.kind == SEMI) {
4415                 accept(SEMI);
4416                 wasSemi = true;
4417                 if (token.kind == RBRACE || token.kind == EOF) break;
4418             }
4419             EnumeratorEstimate memberType = estimateEnumeratorOrMember(enumName);
4420             if (memberType == EnumeratorEstimate.UNKNOWN) {
4421                 memberType = wasSemi ? EnumeratorEstimate.MEMBER
4422                                      : EnumeratorEstimate.ENUMERATOR;
4423             }
4424             if (memberType == EnumeratorEstimate.ENUMERATOR) {
4425                 wasError = false;
4426                 if (wasSemi && !hasStructuralErrors) {
4427                     reportSyntaxError(token.pos, Errors.EnumConstantNotExpected);
4428                     hasStructuralErrors = true;
4429                 }
4430                 defs.append(enumeratorDeclaration(enumName));
4431                 if (token.pos <= endPosTable.errorEndPos) {
4432                     // error recovery
4433                    skip(false, true, true, false);
4434                 } else {
4435                     if (token.kind != RBRACE && token.kind != SEMI && token.kind != EOF) {
4436                         if (token.kind == COMMA) {
4437                             nextToken();
4438                         } else {
4439                             setErrorEndPos(token.pos);
4440                             reportSyntaxError(S.prevToken().endPos,
4441                                               Errors.Expected3(COMMA, RBRACE, SEMI));
4442                             wasError = true;
4443                         }
4444                     }
4445                 }
4446             } else {
4447                 if (!wasSemi && !hasStructuralErrors && !wasError) {
4448                     reportSyntaxError(token.pos, Errors.EnumConstantExpected);
4449                     hasStructuralErrors = true;
4450                 }
4451                 wasError = false;
4452                 defs.appendList(classOrInterfaceOrRecordBodyDeclaration(null, enumName,
4453                                                                 false, false));
4454                 if (token.pos <= endPosTable.errorEndPos) {
4455                     // error recovery
4456                    skip(false, true, true, false);
4457                 }
4458             }
4459         }
4460         accept(RBRACE);
4461         return defs.toList();
4462     }
4463 
4464     @SuppressWarnings("fallthrough")
4465     private EnumeratorEstimate estimateEnumeratorOrMember(Name enumName) {
4466         // if we are seeing a record declaration inside of an enum we want the same error message as expected for a
4467         // let's say an interface declaration inside an enum
4468         boolean ident = token.kind == TokenKind.IDENTIFIER ||
4469                         token.kind == TokenKind.UNDERSCORE;
4470         if (ident && token.name() != enumName &&
4471                 (!allowRecords || !isRecordStart())) {
4472             Token next = S.token(1);
4473             switch (next.kind) {
4474                 case LPAREN: case LBRACE: case COMMA: case SEMI:
4475                     return EnumeratorEstimate.ENUMERATOR;
4476             }
4477         }
4478         switch (token.kind) {
4479             case IDENTIFIER:
4480                 if (allowRecords && isRecordStart()) {
4481                     return EnumeratorEstimate.MEMBER;
4482                 }
4483             case MONKEYS_AT: case LT: case UNDERSCORE:
4484                 return EnumeratorEstimate.UNKNOWN;
4485             default:
4486                 return EnumeratorEstimate.MEMBER;
4487         }
4488     }
4489 
4490     private enum EnumeratorEstimate {
4491         ENUMERATOR,
4492         MEMBER,
4493         UNKNOWN;
4494     }
4495 
4496     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
4497      */
4498     JCTree enumeratorDeclaration(Name enumName) {
4499         Comment dc = token.comment(CommentStyle.JAVADOC);
4500         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
4501         if (token.deprecatedFlag()) {
4502             flags |= Flags.DEPRECATED;
4503         }
4504         int pos = token.pos;
4505         List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
4506         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
4507         List<JCExpression> typeArgs = typeArgumentsOpt();
4508         int identPos = token.pos;
4509         Name name = ident();
4510         int createPos = token.pos;
4511         List<JCExpression> args = (token.kind == LPAREN)
4512             ? arguments() : List.nil();
4513         JCClassDecl body = null;
4514         if (token.kind == LBRACE) {
4515             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM);
4516             List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
4517             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
4518         }
4519         if (args.isEmpty() && body == null)
4520             createPos = identPos;
4521         JCIdent ident = F.at(identPos).Ident(enumName);
4522         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
4523         if (createPos != identPos)
4524             storeEnd(create, S.prevToken().endPos);
4525         ident = F.at(identPos).Ident(enumName);
4526         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
4527         attach(result, dc);
4528         return result;
4529     }
4530 
4531     /** TypeList = Type {"," Type}
4532      */
4533     List<JCExpression> typeList() {
4534         ListBuffer<JCExpression> ts = new ListBuffer<>();
4535         ts.append(parseType());
4536         while (token.kind == COMMA) {
4537             nextToken();
4538             ts.append(parseType());
4539         }
4540         return ts.toList();
4541     }
4542 
4543     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
4544      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
4545      */
4546     List<JCTree> classInterfaceOrRecordBody(Name className, boolean isInterface, boolean isRecord) {
4547         accept(LBRACE);
4548         if (token.pos <= endPosTable.errorEndPos) {
4549             // error recovery
4550             skip(false, true, false, false);
4551             if (token.kind == LBRACE)
4552                 nextToken();
4553             else
4554                 return List.nil();
4555         }
4556         ListBuffer<JCTree> defs = new ListBuffer<>();
4557         while (token.kind != RBRACE && token.kind != EOF) {
4558             defs.appendList(classOrInterfaceOrRecordBodyDeclaration(null, className, isInterface, isRecord));
4559             if (token.pos <= endPosTable.errorEndPos) {
4560                // error recovery
4561                skip(false, true, true, false);
4562             }
4563         }
4564         accept(RBRACE);
4565         return defs.toList();
4566     }
4567 
4568     /** ClassBodyDeclaration =
4569      *      ";"
4570      *    | [STATIC] Block
4571      *    | ModifiersOpt
4572      *      ( Type Ident
4573      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
4574      *      | VOID Ident VoidMethodDeclaratorRest
4575      *      | TypeParameters [Annotations]
4576      *        ( Type Ident MethodDeclaratorRest
4577      *        | VOID Ident VoidMethodDeclaratorRest
4578      *        )
4579      *      | Ident ConstructorDeclaratorRest
4580      *      | TypeParameters Ident ConstructorDeclaratorRest
4581      *      | ClassOrInterfaceOrEnumDeclaration
4582      *      )
4583      *  InterfaceBodyDeclaration =
4584      *      ";"
4585      *    | ModifiersOpt
4586      *      ( Type Ident
4587      *        ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
4588      *      | VOID Ident MethodDeclaratorRest
4589      *      | TypeParameters [Annotations]
4590      *        ( Type Ident MethodDeclaratorRest
4591      *        | VOID Ident VoidMethodDeclaratorRest
4592      *        )
4593      *      | ClassOrInterfaceOrEnumDeclaration
4594      *      )
4595      *
4596      */
4597     protected List<JCTree> classOrInterfaceOrRecordBodyDeclaration(JCModifiers mods, Name className,
4598                                                                    boolean isInterface,
4599                                                                    boolean isRecord) {
4600         if (token.kind == SEMI) {
4601             nextToken();
4602             return List.nil();
4603         } else {
4604             Comment dc = token.comment(CommentStyle.JAVADOC);
4605             int pos = token.pos;
4606             mods = modifiersOpt(mods);
4607             if (isDeclaration()) {
4608                 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
4609             } else if (token.kind == LBRACE &&
4610                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
4611                        mods.annotations.isEmpty()) {
4612                 if (isInterface) {
4613                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InitializerNotAllowed);
4614                 } else if (isRecord && (mods.flags & Flags.STATIC) == 0) {
4615                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InstanceInitializerNotAllowedInRecords);
4616                 }
4617                 return List.of(block(pos, mods.flags));
4618             } else {
4619                 return constructorOrMethodOrFieldDeclaration(mods, className, isInterface, isRecord, dc);
4620             }
4621         }
4622     }
4623 
4624     private List<JCTree> constructorOrMethodOrFieldDeclaration(JCModifiers mods, Name className,
4625                                                                boolean isInterface,
4626                                                                boolean isRecord, Comment dc) {
4627         int pos;
4628         pos = token.pos;
4629         List<JCTypeParameter> typarams = typeParametersOpt();
4630         // if there are type parameters but no modifiers, save the start
4631         // position of the method in the modifiers.
4632         if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4633             mods.pos = pos;
4634             storeEnd(mods, pos);
4635         }
4636         List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4637 
4638         if (annosAfterParams.nonEmpty()) {
4639             mods.annotations = mods.annotations.appendList(annosAfterParams);
4640             if (mods.pos == Position.NOPOS)
4641                 mods.pos = mods.annotations.head.pos;
4642         }
4643 
4644         Token tk = token;
4645         pos = token.pos;
4646         JCExpression type;
4647         boolean isVoid = token.kind == VOID;
4648 
4649         if (isVoid) {
4650             type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4651             nextToken();
4652         } else {
4653             // method returns types are un-annotated types
4654             type = unannotatedType(false);
4655         }
4656 
4657         // Constructor
4658         if ((token.kind == LPAREN && !isInterface ||
4659                 isRecord && token.kind == LBRACE) && type.hasTag(IDENT)) {
4660             if (isInterface || tk.name() != className) {
4661                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq);
4662             } else if (annosAfterParams.nonEmpty()) {
4663                 illegal(annosAfterParams.head.pos);
4664             }
4665 
4666             if (isRecord && token.kind == LBRACE) {
4667                 mods.flags |= Flags.COMPACT_RECORD_CONSTRUCTOR;
4668             }
4669 
4670             return List.of(methodDeclaratorRest(
4671                     pos, mods, null, names.init, typarams,
4672                     isInterface, true, isRecord, dc));
4673         }
4674 
4675         // Record constructor
4676         if (isRecord && type.hasTag(IDENT) && token.kind == THROWS) {
4677             // trying to define a compact constructor with a throws clause
4678             log.error(DiagnosticFlag.SYNTAX, token.pos,
4679                     Errors.InvalidCanonicalConstructorInRecord(
4680                             Fragments.Compact,
4681                             className,
4682                             Fragments.ThrowsClauseNotAllowedForCanonicalConstructor(Fragments.Compact)));
4683             skip(false, true, false, false);
4684             return List.of(methodDeclaratorRest(
4685                     pos, mods, null, names.init, typarams,
4686                     isInterface, true, isRecord, dc));
4687         }
4688 
4689         pos = token.pos;
4690         Name name = ident();
4691 
4692         // Method
4693         if (token.kind == LPAREN) {
4694             return List.of(methodDeclaratorRest(
4695                     pos, mods, type, name, typarams,
4696                     isInterface, isVoid, false, dc));
4697         }
4698 
4699         // Field
4700         if (!isVoid && typarams.isEmpty()) {
4701             if (!isRecord || (isRecord && (mods.flags & Flags.STATIC) != 0)) {
4702                 List<JCTree> defs =
4703                     variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4704                                             new ListBuffer<JCTree>(), false).toList();
4705                 accept(SEMI);
4706                 storeEnd(defs.last(), S.prevToken().endPos);
4707                 return defs;
4708             }
4709 
4710             int errPos = pos;
4711             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4712                     new ListBuffer<JCTree>(), false).toList();
4713             accept(SEMI);
4714             return List.of(syntaxError(errPos, null, Errors.RecordCannotDeclareInstanceFields));
4715          }
4716 
4717          pos = token.pos;
4718          List<JCTree> err;
4719 
4720          // Error recovery
4721          if (isVoid || typarams.nonEmpty()) {
4722              JCMethodDecl m =
4723                      toP(F.at(pos).MethodDef(mods, name, type, typarams,
4724                                              List.nil(), List.nil(), null, null));
4725              attach(m, dc);
4726              err = List.of(m);
4727          } else {
4728              err = List.nil();
4729          }
4730 
4731          return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
4732     }
4733 
4734     private List<JCTree> topLevelMethodOrFieldDeclaration(JCModifiers mods) throws AssertionError {
4735         int topPos = token.pos;
4736         int pos = token.pos;
4737         Comment dc = token.comment(CommentStyle.JAVADOC);
4738         List<JCTypeParameter> typarams = typeParametersOpt();
4739 
4740         // if there are type parameters but no modifiers, save the start
4741         // position of the method in the modifiers.
4742         if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4743             mods.pos = pos;
4744             storeEnd(mods, pos);
4745         }
4746 
4747         List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4748 
4749         if (annosAfterParams.nonEmpty()) {
4750             mods.annotations = mods.annotations.appendList(annosAfterParams);
4751             if (mods.pos == Position.NOPOS)
4752                 mods.pos = mods.annotations.head.pos;
4753         }
4754 
4755         pos = token.pos;
4756         JCExpression type;
4757         boolean isVoid = token.kind == VOID;
4758 
4759         if (isVoid) {
4760             type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4761             nextToken();
4762         } else {
4763             type = unannotatedType(false);
4764         }
4765 
4766         if (token.kind == IDENTIFIER) {
4767             pos = token.pos;
4768             Name name = ident();
4769 
4770             // Method
4771             if (token.kind == LPAREN) {
4772                 return List.of(methodDeclaratorRest(pos, mods, type, name, typarams,
4773                         false, isVoid, false, dc));
4774             }
4775 
4776             // Field
4777             if (!isVoid && typarams.isEmpty() && (token.kind == EQ || token.kind == SEMI)) {
4778                 List<JCTree> defs =
4779                         variableDeclaratorsRest(pos, mods, type, name, false, dc,
4780                                 new ListBuffer<JCTree>(), false).toList();
4781                 accept(SEMI);
4782                 storeEnd(defs.last(), S.prevToken().endPos);
4783 
4784                 return defs;
4785             }
4786         }
4787 
4788         return List.of(F.Erroneous());
4789     }
4790 
4791     protected boolean isDeclaration() {
4792         return token.kind == CLASS ||
4793                token.kind == INTERFACE ||
4794                token.kind == ENUM ||
4795                isRecordStart() && allowRecords;
4796         }
4797 
4798     protected boolean isRecordStart() {
4799         if (token.kind == IDENTIFIER && token.name() == names.record && peekToken(TokenKind.IDENTIFIER)) {
4800             checkSourceLevel(Feature.RECORDS);
4801             return true;
4802         } else {
4803             return false;
4804         }
4805     }
4806 
4807     protected boolean isNonSealedClassStart(boolean local) {
4808         if (isNonSealedIdentifier(token, 0)) {
4809             Token next = S.token(3);
4810             return allowedAfterSealedOrNonSealed(next, local, true);
4811         }
4812         return false;
4813     }
4814 
4815     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4816         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4817             Token tokenSub = S.token(lookAheadOffset + 1);
4818             Token tokenSealed = S.token(lookAheadOffset + 2);
4819             if (someToken.endPos == tokenSub.pos &&
4820                     tokenSub.endPos == tokenSealed.pos &&
4821                     tokenSealed.name() == names.sealed) {
4822                 checkSourceLevel(Feature.SEALED_CLASSES);
4823                 return true;
4824             }
4825         }
4826         return false;
4827     }
4828 
4829     protected boolean isSealedClassStart(boolean local) {
4830         if (token.name() == names.sealed) {
4831             Token next = S.token(1);
4832             if (allowedAfterSealedOrNonSealed(next, local, false)) {
4833                 checkSourceLevel(Feature.SEALED_CLASSES);
4834                 return true;
4835             }
4836         }
4837         return false;
4838     }
4839 
4840     private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
4841         return local ?
4842             switch (next.kind) {
4843                 case MONKEYS_AT -> {
4844                     Token afterNext = S.token(2);
4845                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
4846                 }
4847                 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4848                 default -> false;
4849             } :
4850             switch (next.kind) {
4851                 case MONKEYS_AT -> {
4852                     Token afterNext = S.token(2);
4853                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
4854                 }
4855                 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4856                 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
4857                 default -> false;
4858             };
4859     }
4860 
4861     /** MethodDeclaratorRest =
4862      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4863      *  VoidMethodDeclaratorRest =
4864      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
4865      *  ConstructorDeclaratorRest =
4866      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4867      */
4868     protected JCTree methodDeclaratorRest(int pos,
4869                               JCModifiers mods,
4870                               JCExpression type,
4871                               Name name,
4872                               List<JCTypeParameter> typarams,
4873                               boolean isInterface, boolean isVoid,
4874                               boolean isRecord,
4875                               Comment dc) {
4876         if (isInterface) {
4877             if ((mods.flags & Flags.PRIVATE) != 0) {
4878                 checkSourceLevel(Feature.PRIVATE_INTERFACE_METHODS);
4879             }
4880         }
4881         JCVariableDecl prevReceiverParam = this.receiverParam;
4882         try {
4883             this.receiverParam = null;
4884             // Parsing formalParameters sets the receiverParam, if present
4885             List<JCVariableDecl> params = List.nil();
4886             List<JCExpression> thrown = List.nil();
4887             if (!isRecord || name != names.init || token.kind == LPAREN) {
4888                 params = formalParameters();
4889                 if (!isVoid) type = bracketsOpt(type);
4890                 if (token.kind == THROWS) {
4891                     nextToken();
4892                     thrown = qualidentList(true);
4893                 }
4894             }
4895             JCBlock body = null;
4896             JCExpression defaultValue;
4897             if (token.kind == LBRACE) {
4898                 body = block();
4899                 defaultValue = null;
4900             } else {
4901                 if (token.kind == DEFAULT) {
4902                     accept(DEFAULT);
4903                     defaultValue = annotationValue();
4904                 } else {
4905                     defaultValue = null;
4906                 }
4907                 accept(SEMI);
4908                 if (token.pos <= endPosTable.errorEndPos) {
4909                     // error recovery
4910                     skip(false, true, false, false);
4911                     if (token.kind == LBRACE) {
4912                         body = block();
4913                     }
4914                 }
4915             }
4916 
4917             JCMethodDecl result =
4918                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
4919                                             receiverParam, params, thrown,
4920                                             body, defaultValue));
4921             attach(result, dc);
4922             return result;
4923         } finally {
4924             this.receiverParam = prevReceiverParam;
4925         }
4926     }
4927 
4928     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
4929      */
4930     List<JCExpression> qualidentList(boolean allowAnnos) {
4931         ListBuffer<JCExpression> ts = new ListBuffer<>();
4932 
4933         List<JCAnnotation> typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
4934         JCExpression qi = qualident(allowAnnos);
4935         if (!typeAnnos.isEmpty()) {
4936             JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
4937             ts.append(at);
4938         } else {
4939             ts.append(qi);
4940         }
4941         while (token.kind == COMMA) {
4942             nextToken();
4943 
4944             typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
4945             qi = qualident(allowAnnos);
4946             if (!typeAnnos.isEmpty()) {
4947                 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
4948                 ts.append(at);
4949             } else {
4950                 ts.append(qi);
4951             }
4952         }
4953         return ts.toList();
4954     }
4955 
4956     /**
4957      *  {@literal
4958      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
4959      *  }
4960      */
4961     protected List<JCTypeParameter> typeParametersOpt() {
4962         return typeParametersOpt(false);
4963     }
4964     /** Parses a potentially empty type parameter list if needed with `allowEmpty`.
4965      *  The caller is free to choose the desirable error message in this (erroneous) case.
4966      */
4967     protected List<JCTypeParameter> typeParametersOpt(boolean parseEmpty) {
4968         if (token.kind == LT) {
4969             ListBuffer<JCTypeParameter> typarams = new ListBuffer<>();
4970             nextToken();
4971 
4972             if (parseEmpty && token.kind == GT) {
4973                 accept(GT);
4974                 return null;
4975             }
4976 
4977             typarams.append(typeParameter());
4978             while (token.kind == COMMA) {
4979                 nextToken();
4980                 typarams.append(typeParameter());
4981             }
4982             accept(GT);
4983             return typarams.toList();
4984         } else {
4985             return List.nil();
4986         }
4987     }
4988 
4989     /**
4990      *  {@literal
4991      *  TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
4992      *  TypeParameterBound = EXTENDS Type {"&" Type}
4993      *  TypeVariable = Ident
4994      *  }
4995      */
4996     JCTypeParameter typeParameter() {
4997         int pos = token.pos;
4998         List<JCAnnotation> annos = typeAnnotationsOpt();
4999         Name name = typeName();
5000         ListBuffer<JCExpression> bounds = new ListBuffer<>();
5001         if (token.kind == EXTENDS) {
5002             nextToken();
5003             bounds.append(parseType());
5004             while (token.kind == AMP) {
5005                 nextToken();
5006                 bounds.append(parseType());
5007             }
5008         }
5009         return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
5010     }
5011 
5012     /** FormalParameters = "(" [ FormalParameterList ] ")"
5013      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
5014      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
5015      */
5016     List<JCVariableDecl> formalParameters() {
5017         return formalParameters(false, false);
5018     }
5019     List<JCVariableDecl> formalParameters(boolean lambdaParameters, boolean recordComponents) {
5020         ListBuffer<JCVariableDecl> params = new ListBuffer<>();
5021         JCVariableDecl lastParam;
5022         accept(LPAREN);
5023         if (token.kind != RPAREN) {
5024             this.allowThisIdent = !lambdaParameters && !recordComponents;
5025             lastParam = formalParameter(lambdaParameters, recordComponents);
5026             if (lastParam.nameexpr != null) {
5027                 this.receiverParam = lastParam;
5028             } else {
5029                 params.append(lastParam);
5030             }
5031             this.allowThisIdent = false;
5032             while (token.kind == COMMA) {
5033                 if ((lastParam.mods.flags & Flags.VARARGS) != 0) {
5034                     log.error(DiagnosticFlag.SYNTAX, lastParam, Errors.VarargsMustBeLast);
5035                 }
5036                 nextToken();
5037                 params.append(lastParam = formalParameter(lambdaParameters, recordComponents));
5038             }
5039         }
5040         if (token.kind == RPAREN) {
5041             nextToken();
5042         } else {
5043             setErrorEndPos(token.pos);
5044             reportSyntaxError(S.prevToken().endPos, Errors.Expected3(COMMA, RPAREN, LBRACKET));
5045         }
5046         return params.toList();
5047     }
5048 
5049     List<JCVariableDecl> implicitParameters(boolean hasParens) {
5050         if (hasParens) {
5051             accept(LPAREN);
5052         }
5053         ListBuffer<JCVariableDecl> params = new ListBuffer<>();
5054         if (token.kind != RPAREN && token.kind != ARROW) {
5055             params.append(implicitParameter());
5056             while (token.kind == COMMA) {
5057                 nextToken();
5058                 params.append(implicitParameter());
5059             }
5060         }
5061         if (hasParens) {
5062             accept(RPAREN);
5063         }
5064         return params.toList();
5065     }
5066 
5067     JCModifiers optFinal(long flags) {
5068         JCModifiers mods = modifiersOpt();
5069         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
5070         mods.flags |= flags;
5071         return mods;
5072     }
5073 
5074     /**
5075      * Inserts the annotations (and possibly a new array level)
5076      * to the left-most type in an array or nested type.
5077      *
5078      * When parsing a type like {@code @B Outer.Inner @A []}, the
5079      * {@code @A} annotation should target the array itself, while
5080      * {@code @B} targets the nested type {@code Outer}.
5081      *
5082      * Currently the parser parses the annotation first, then
5083      * the array, and then inserts the annotation to the left-most
5084      * nested type.
5085      *
5086      * When {@code createNewLevel} is true, then a new array
5087      * level is inserted as the most inner type, and have the
5088      * annotations target it.  This is useful in the case of
5089      * varargs, e.g. {@code String @A [] @B ...}, as the parser
5090      * first parses the type {@code String @A []} then inserts
5091      * a new array level with {@code @B} annotation.
5092      */
5093     private JCExpression insertAnnotationsToMostInner(
5094             JCExpression type, List<JCAnnotation> annos,
5095             boolean createNewLevel) {
5096         int origEndPos = getEndPos(type);
5097         JCExpression mostInnerType = type;
5098         JCArrayTypeTree mostInnerArrayType = null;
5099         while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) {
5100             mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType);
5101             mostInnerType = mostInnerArrayType.elemtype;
5102         }
5103 
5104         if (createNewLevel) {
5105             mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType));
5106             origEndPos = getEndPos(mostInnerType);
5107         }
5108 
5109         JCExpression mostInnerTypeToReturn = mostInnerType;
5110         if (annos.nonEmpty()) {
5111             JCExpression lastToModify = mostInnerType;
5112 
5113             while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) ||
5114                     TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
5115                 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) {
5116                     lastToModify = mostInnerType;
5117                     mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression();
5118                 }
5119                 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
5120                     lastToModify = mostInnerType;
5121                     mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz;
5122                 }
5123             }
5124 
5125             mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType);
5126 
5127             if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) {
5128                 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType;
5129             } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) {
5130                 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType;
5131             } else {
5132                 // We never saw a SELECT or TYPEAPPLY, return the annotated type.
5133                 mostInnerTypeToReturn = mostInnerType;
5134             }
5135         }
5136 
5137         if (mostInnerArrayType == null) {
5138             return mostInnerTypeToReturn;
5139         } else {
5140             mostInnerArrayType.elemtype = mostInnerTypeToReturn;
5141             storeEnd(type, origEndPos);
5142             return type;
5143         }
5144     }
5145 
5146     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
5147      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
5148      */
5149     protected JCVariableDecl formalParameter(boolean lambdaParameter, boolean recordComponent) {
5150         JCModifiers mods = !recordComponent ? optFinal(Flags.PARAMETER) : modifiersOpt();
5151         if (recordComponent && mods.flags != 0) {
5152             log.error(mods.pos, Errors.RecordCantDeclareFieldModifiers);
5153         }
5154         if (recordComponent) {
5155             mods.flags |= Flags.RECORD | Flags.FINAL | Flags.PRIVATE | Flags.GENERATED_MEMBER;
5156         }
5157         // need to distinguish between vararg annos and array annos
5158         // look at typeAnnotationsPushedBack comment
5159         this.permitTypeAnnotationsPushBack = true;
5160         JCExpression type = parseType(lambdaParameter);
5161         this.permitTypeAnnotationsPushBack = false;
5162 
5163         if (token.kind == ELLIPSIS) {
5164             List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack;
5165             typeAnnotationsPushedBack = List.nil();
5166             mods.flags |= Flags.VARARGS;
5167             // insert var arg type annotations
5168             type = insertAnnotationsToMostInner(type, varargsAnnos, true);
5169             nextToken();
5170         } else {
5171             // if not a var arg, then typeAnnotationsPushedBack should be null
5172             if (typeAnnotationsPushedBack.nonEmpty()) {
5173                 reportSyntaxError(typeAnnotationsPushedBack.head.pos, Errors.IllegalStartOfType);
5174             }
5175             typeAnnotationsPushedBack = List.nil();
5176         }
5177         return variableDeclaratorId(mods, type, false, lambdaParameter, recordComponent);
5178     }
5179 
5180     protected JCVariableDecl implicitParameter() {
5181         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
5182         return variableDeclaratorId(mods, null, false, true, false);
5183     }
5184 
5185 /* ---------- auxiliary methods -------------- */
5186     /** Check that given tree is a legal expression statement.
5187      */
5188     protected JCExpression checkExprStat(JCExpression t) {
5189         if (!TreeInfo.isExpressionStatement(t)) {
5190             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
5191             log.error(DiagnosticFlag.SYNTAX, ret, Errors.NotStmt);
5192             return ret;
5193         } else {
5194             return t;
5195         }
5196     }
5197 
5198     /** Return precedence of operator represented by token,
5199      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
5200      */
5201     static int prec(TokenKind token) {
5202         JCTree.Tag oc = optag(token);
5203         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
5204     }
5205 
5206     /**
5207      * Return the lesser of two positions, making allowance for either one
5208      * being unset.
5209      */
5210     static int earlier(int pos1, int pos2) {
5211         if (pos1 == Position.NOPOS)
5212             return pos2;
5213         if (pos2 == Position.NOPOS)
5214             return pos1;
5215         return (pos1 < pos2 ? pos1 : pos2);
5216     }
5217 
5218     /** Return operation tag of binary operator represented by token,
5219      *  No_TAG if token is not a binary operator.
5220      */
5221     static JCTree.Tag optag(TokenKind token) {
5222         switch (token) {
5223         case BARBAR:
5224             return OR;
5225         case AMPAMP:
5226             return AND;
5227         case BAR:
5228             return BITOR;
5229         case BAREQ:
5230             return BITOR_ASG;
5231         case CARET:
5232             return BITXOR;
5233         case CARETEQ:
5234             return BITXOR_ASG;
5235         case AMP:
5236             return BITAND;
5237         case AMPEQ:
5238             return BITAND_ASG;
5239         case EQEQ:
5240             return JCTree.Tag.EQ;
5241         case BANGEQ:
5242             return NE;
5243         case LT:
5244             return JCTree.Tag.LT;
5245         case GT:
5246             return JCTree.Tag.GT;
5247         case LTEQ:
5248             return LE;
5249         case GTEQ:
5250             return GE;
5251         case LTLT:
5252             return SL;
5253         case LTLTEQ:
5254             return SL_ASG;
5255         case GTGT:
5256             return SR;
5257         case GTGTEQ:
5258             return SR_ASG;
5259         case GTGTGT:
5260             return USR;
5261         case GTGTGTEQ:
5262             return USR_ASG;
5263         case PLUS:
5264             return JCTree.Tag.PLUS;
5265         case PLUSEQ:
5266             return PLUS_ASG;
5267         case SUB:
5268             return MINUS;
5269         case SUBEQ:
5270             return MINUS_ASG;
5271         case STAR:
5272             return MUL;
5273         case STAREQ:
5274             return MUL_ASG;
5275         case SLASH:
5276             return DIV;
5277         case SLASHEQ:
5278             return DIV_ASG;
5279         case PERCENT:
5280             return MOD;
5281         case PERCENTEQ:
5282             return MOD_ASG;
5283         case INSTANCEOF:
5284             return TYPETEST;
5285         default:
5286             return NO_TAG;
5287         }
5288     }
5289 
5290     /** Return operation tag of unary operator represented by token,
5291      *  No_TAG if token is not a binary operator.
5292      */
5293     static JCTree.Tag unoptag(TokenKind token) {
5294         switch (token) {
5295         case PLUS:
5296             return POS;
5297         case SUB:
5298             return NEG;
5299         case BANG:
5300             return NOT;
5301         case TILDE:
5302             return COMPL;
5303         case PLUSPLUS:
5304             return PREINC;
5305         case SUBSUB:
5306             return PREDEC;
5307         default:
5308             return NO_TAG;
5309         }
5310     }
5311 
5312     /** Return type tag of basic type represented by token,
5313      *  NONE if token is not a basic type identifier.
5314      */
5315     static TypeTag typetag(TokenKind token) {
5316         switch (token) {
5317         case BYTE:
5318             return TypeTag.BYTE;
5319         case CHAR:
5320             return TypeTag.CHAR;
5321         case SHORT:
5322             return TypeTag.SHORT;
5323         case INT:
5324             return TypeTag.INT;
5325         case LONG:
5326             return TypeTag.LONG;
5327         case FLOAT:
5328             return TypeTag.FLOAT;
5329         case DOUBLE:
5330             return TypeTag.DOUBLE;
5331         case BOOLEAN:
5332             return TypeTag.BOOLEAN;
5333         default:
5334             return TypeTag.NONE;
5335         }
5336     }
5337 
5338     void checkSourceLevel(Feature feature) {
5339         checkSourceLevel(token.pos, feature);
5340     }
5341 
5342     protected void checkSourceLevel(int pos, Feature feature) {
5343         if (preview.isPreview(feature) && !preview.isEnabled()) {
5344             //preview feature without --preview flag, error
5345             log.error(DiagnosticFlag.SOURCE_LEVEL, pos, preview.disabledError(feature));
5346         } else if (!feature.allowedInSource(source)) {
5347             //incompatible source level, error
5348             log.error(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name));
5349         } else if (preview.isPreview(feature)) {
5350             //use of preview feature, warn
5351             preview.warnPreview(pos, feature);
5352         }
5353     }
5354 
5355     /*
5356      * a functional source tree and end position mappings
5357      */
5358     protected static class SimpleEndPosTable extends AbstractEndPosTable {
5359 
5360         private final IntHashTable endPosMap;
5361 
5362         SimpleEndPosTable(JavacParser parser) {
5363             super(parser);
5364             endPosMap = new IntHashTable();
5365         }
5366 
5367         public void storeEnd(JCTree tree, int endpos) {
5368             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
5369         }
5370 
5371         protected <T extends JCTree> T to(T t) {
5372             storeEnd(t, parser.token.endPos);
5373             return t;
5374         }
5375 
5376         protected <T extends JCTree> T toP(T t) {
5377             storeEnd(t, parser.S.prevToken().endPos);
5378             return t;
5379         }
5380 
5381         public int getEndPos(JCTree tree) {
5382             int value = endPosMap.get(tree);
5383             // As long as Position.NOPOS==-1, this just returns value.
5384             return (value == -1) ? Position.NOPOS : value;
5385         }
5386 
5387         public int replaceTree(JCTree oldTree, JCTree newTree) {
5388             int pos = endPosMap.remove(oldTree);
5389             if (pos != -1) {
5390                 storeEnd(newTree, pos);
5391                 return pos;
5392             }
5393             return Position.NOPOS;
5394         }
5395     }
5396 
5397     /*
5398      * a default skeletal implementation without any mapping overhead.
5399      */
5400     protected static class EmptyEndPosTable extends AbstractEndPosTable {
5401 
5402         EmptyEndPosTable(JavacParser parser) {
5403             super(parser);
5404         }
5405 
5406         public void storeEnd(JCTree tree, int endpos) { /* empty */ }
5407 
5408         protected <T extends JCTree> T to(T t) {
5409             return t;
5410         }
5411 
5412         protected <T extends JCTree> T toP(T t) {
5413             return t;
5414         }
5415 
5416         public int getEndPos(JCTree tree) {
5417             return Position.NOPOS;
5418         }
5419 
5420         public int replaceTree(JCTree oldTree, JCTree newTree) {
5421             return Position.NOPOS;
5422         }
5423 
5424     }
5425 
5426     protected abstract static class AbstractEndPosTable implements EndPosTable {
5427         /**
5428          * The current parser.
5429          */
5430         protected JavacParser parser;
5431 
5432         /**
5433          * Store the last error position.
5434          */
5435         public int errorEndPos = Position.NOPOS;
5436 
5437         public AbstractEndPosTable(JavacParser parser) {
5438             this.parser = parser;
5439         }
5440 
5441         /**
5442          * Store current token's ending position for a tree, the value of which
5443          * will be the greater of last error position and the ending position of
5444          * the current token.
5445          * @param t The tree.
5446          */
5447         protected abstract <T extends JCTree> T to(T t);
5448 
5449         /**
5450          * Store current token's ending position for a tree, the value of which
5451          * will be the greater of last error position and the ending position of
5452          * the previous token.
5453          * @param t The tree.
5454          */
5455         protected abstract <T extends JCTree> T toP(T t);
5456 
5457         /**
5458          * Set the error position during the parsing phases, the value of which
5459          * will be set only if it is greater than the last stored error position.
5460          * @param errPos The error position
5461          */
5462         public void setErrorEndPos(int errPos) {
5463             if (errPos > errorEndPos) {
5464                 errorEndPos = errPos;
5465             }
5466         }
5467 
5468         public void setParser(JavacParser parser) {
5469             this.parser = parser;
5470         }
5471     }
5472 }