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