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