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 = parser.keepDocComments;
 216         this.parseModuleInfo = false;
 217         this.docComments = parser.docComments;
 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                 case FINAL:
3389                     if (parenDepth > 0) return PatternResult.PATTERN;
3390                 default: return pendingResult;
3391             }
3392             lookahead++;
3393         }
3394     }
3395 
3396     private enum PatternResult {
3397         EXPRESSION,
3398         PATTERN;
3399     }
3400 
3401     /** MoreStatementExpressions = { COMMA StatementExpression }
3402      */
3403     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
3404                                                                     JCExpression first,
3405                                                                     T stats) {
3406         // This Exec is a "StatementExpression"; it subsumes no terminating token
3407         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
3408         while (token.kind == COMMA) {
3409             nextToken();
3410             pos = token.pos;
3411             JCExpression t = parseExpression();
3412             // This Exec is a "StatementExpression"; it subsumes no terminating token
3413             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
3414         }
3415         return stats;
3416     }
3417 
3418     /** ForInit = StatementExpression MoreStatementExpressions
3419      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
3420      */
3421     List<JCStatement> forInit() {
3422         ListBuffer<JCStatement> stats = new ListBuffer<>();
3423         int pos = token.pos;
3424         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3425             return variableDeclarators(optFinal(0), parseType(true), stats, true).toList();
3426         } else {
3427             JCExpression t = term(EXPR | TYPE);
3428             if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3429                 pos = token.pos;
3430                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3431                 F.at(pos);
3432                 return variableDeclarators(mods, t, stats, true).toList();
3433             } else if (wasTypeMode() && token.kind == COLON) {
3434                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.BadInitializer("for-loop"));
3435                 return List.of((JCStatement)F.at(pos).VarDef(modifiersOpt(), names.error, t, null));
3436             } else {
3437                 return moreStatementExpressions(pos, t, stats).toList();
3438             }
3439         }
3440     }
3441 
3442     /** ForUpdate = StatementExpression MoreStatementExpressions
3443      */
3444     List<JCExpressionStatement> forUpdate() {
3445         return moreStatementExpressions(token.pos,
3446                                         parseExpression(),
3447                                         new ListBuffer<JCExpressionStatement>()).toList();
3448     }
3449 
3450     /** AnnotationsOpt = { '@' Annotation }
3451      *
3452      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3453      */
3454     protected List<JCAnnotation> annotationsOpt(Tag kind) {
3455         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
3456         ListBuffer<JCAnnotation> buf = new ListBuffer<>();
3457         int prevmode = mode;
3458         while (token.kind == MONKEYS_AT) {
3459             int pos = token.pos;
3460             nextToken();
3461             buf.append(annotation(pos, kind));
3462         }
3463         setLastMode(mode);
3464         setMode(prevmode);
3465         List<JCAnnotation> annotations = buf.toList();
3466 
3467         return annotations;
3468     }
3469 
3470     List<JCAnnotation> typeAnnotationsOpt() {
3471         List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION);
3472         return annotations;
3473     }
3474 
3475     /** ModifiersOpt = { Modifier }
3476      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
3477      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
3478      *           | "@" Annotation
3479      */
3480     protected JCModifiers modifiersOpt() {
3481         return modifiersOpt(null);
3482     }
3483     protected JCModifiers modifiersOpt(JCModifiers partial) {
3484         long flags;
3485         ListBuffer<JCAnnotation> annotations = new ListBuffer<>();
3486         int pos;
3487         if (partial == null) {
3488             flags = 0;
3489             pos = token.pos;
3490         } else {
3491             flags = partial.flags;
3492             annotations.appendList(partial.annotations);
3493             pos = partial.pos;
3494         }
3495         if (token.deprecatedFlag()) {
3496             flags |= Flags.DEPRECATED;
3497         }
3498         int lastPos;
3499     loop:
3500         while (true) {
3501             long flag;
3502             switch (token.kind) {
3503             case PRIVATE     : flag = Flags.PRIVATE; break;
3504             case PROTECTED   : flag = Flags.PROTECTED; break;
3505             case PUBLIC      : flag = Flags.PUBLIC; break;
3506             case STATIC      : flag = Flags.STATIC; break;
3507             case TRANSIENT   : flag = Flags.TRANSIENT; break;
3508             case FINAL       : flag = Flags.FINAL; break;
3509             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3510             case NATIVE      : flag = Flags.NATIVE; break;
3511             case VOLATILE    : flag = Flags.VOLATILE; break;
3512             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3513             case STRICTFP    : flag = Flags.STRICTFP; break;
3514             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3515             case DEFAULT     : flag = Flags.DEFAULT; break;
3516             case ERROR       : flag = 0; nextToken(); break;
3517             case IDENTIFIER  : {
3518                 if (isNonSealedClassStart(false)) {
3519                     flag = Flags.NON_SEALED;
3520                     nextToken();
3521                     nextToken();
3522                     break;
3523                 }
3524                 if (isSealedClassStart(false)) {
3525                     checkSourceLevel(Feature.SEALED_CLASSES);
3526                     flag = Flags.SEALED;
3527                     break;
3528                 }
3529                 if (isValueModifier()) {
3530                     checkSourceLevel(Feature.VALUE_CLASSES);
3531                     flag = Flags.VALUE_CLASS;
3532                     break;
3533                 }
3534                 break loop;
3535             }
3536             default: break loop;
3537             }
3538             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3539             lastPos = token.pos;
3540             nextToken();
3541             if (flag == Flags.ANNOTATION) {
3542                 if (token.kind != INTERFACE) {
3543                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3544                     // if first modifier is an annotation, set pos to annotation's.
3545                     if (flags == 0 && annotations.isEmpty())
3546                         pos = ann.pos;
3547                     annotations.append(ann);
3548                     flag = 0;
3549                 }
3550             }
3551             flags |= flag;
3552         }
3553         switch (token.kind) {
3554         case ENUM: flags |= Flags.ENUM; break;
3555         case INTERFACE: flags |= Flags.INTERFACE; break;
3556         default: break;
3557         }
3558 
3559         /* A modifiers tree with no modifier tokens or annotations
3560          * has no text position. */
3561         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
3562             pos = Position.NOPOS;
3563 
3564         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
3565         if (pos != Position.NOPOS)
3566             storeEnd(mods, S.prevToken().endPos);
3567         return mods;
3568     }
3569 
3570     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
3571      *
3572      * @param pos position of "@" token
3573      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3574      */
3575     JCAnnotation annotation(int pos, Tag kind) {
3576         // accept(AT); // AT consumed by caller
3577         JCTree ident = qualident(false);
3578         List<JCExpression> fieldValues = annotationFieldValuesOpt();
3579         JCAnnotation ann;
3580         if (kind == Tag.ANNOTATION) {
3581             ann = F.at(pos).Annotation(ident, fieldValues);
3582         } else if (kind == Tag.TYPE_ANNOTATION) {
3583             ann = F.at(pos).TypeAnnotation(ident, fieldValues);
3584         } else {
3585             throw new AssertionError("Unhandled annotation kind: " + kind);
3586         }
3587 
3588         storeEnd(ann, S.prevToken().endPos);
3589         return ann;
3590     }
3591 
3592     List<JCExpression> annotationFieldValuesOpt() {
3593         return (token.kind == LPAREN) ? annotationFieldValues() : List.nil();
3594     }
3595 
3596     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
3597     List<JCExpression> annotationFieldValues() {
3598         accept(LPAREN);
3599         ListBuffer<JCExpression> buf = new ListBuffer<>();
3600         if (token.kind != RPAREN) {
3601             buf.append(annotationFieldValue());
3602             while (token.kind == COMMA) {
3603                 nextToken();
3604                 buf.append(annotationFieldValue());
3605             }
3606         }
3607         accept(RPAREN);
3608         return buf.toList();
3609     }
3610 
3611     /** AnnotationFieldValue    = AnnotationValue
3612      *                          | Identifier "=" AnnotationValue
3613      */
3614     JCExpression annotationFieldValue() {
3615         if (LAX_IDENTIFIER.test(token.kind)) {
3616             selectExprMode();
3617             JCExpression t1 = term1();
3618             if (t1.hasTag(IDENT) && token.kind == EQ) {
3619                 int pos = token.pos;
3620                 accept(EQ);
3621                 JCExpression v = annotationValue();
3622                 return toP(F.at(pos).Assign(t1, v));
3623             } else {
3624                 return t1;
3625             }
3626         }
3627         return annotationValue();
3628     }
3629 
3630     /* AnnotationValue          = ConditionalExpression
3631      *                          | Annotation
3632      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
3633      */
3634     JCExpression annotationValue() {
3635         int pos;
3636         switch (token.kind) {
3637         case MONKEYS_AT:
3638             pos = token.pos;
3639             nextToken();
3640             return annotation(pos, Tag.ANNOTATION);
3641         case LBRACE:
3642             pos = token.pos;
3643             accept(LBRACE);
3644             ListBuffer<JCExpression> buf = new ListBuffer<>();
3645             if (token.kind == COMMA) {
3646                 nextToken();
3647             } else if (token.kind != RBRACE) {
3648                 buf.append(annotationValue());
3649                 while (token.kind == COMMA) {
3650                     nextToken();
3651                     if (token.kind == RBRACE) break;
3652                     buf.append(annotationValue());
3653                 }
3654             }
3655             accept(RBRACE, tk -> Errors.AnnotationMissingElementValue);
3656             return toP(F.at(pos).NewArray(null, List.nil(), buf.toList()));
3657         default:
3658             selectExprMode();
3659             return term1();
3660         }
3661     }
3662 
3663     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
3664      */
3665     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
3666                                                                          JCExpression type,
3667                                                                          T vdefs,
3668                                                                          boolean localDecl)
3669     {
3670         return variableDeclaratorsRest(token.pos, mods, type, identOrUnderscore(), false, null, vdefs, localDecl);
3671     }
3672 
3673     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
3674      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
3675      *
3676      *  @param reqInit  Is an initializer always required?
3677      *  @param dc       The documentation comment for the variable declarations, or null.
3678      */
3679     protected <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
3680                                                                      JCModifiers mods,
3681                                                                      JCExpression type,
3682                                                                      Name name,
3683                                                                      boolean reqInit,
3684                                                                      Comment dc,
3685                                                                      T vdefs,
3686                                                                      boolean localDecl)
3687     {
3688         JCVariableDecl head = variableDeclaratorRest(pos, mods, type, name, reqInit, dc, localDecl, false);
3689         vdefs.append(head);
3690         while (token.kind == COMMA) {
3691             // All but last of multiple declarators subsume a comma
3692             storeEnd((JCTree)vdefs.last(), token.endPos);
3693             nextToken();
3694             vdefs.append(variableDeclarator(mods, type, reqInit, dc, localDecl));
3695         }
3696         return vdefs;
3697     }
3698 
3699     /** VariableDeclarator = Ident VariableDeclaratorRest
3700      *  ConstantDeclarator = Ident ConstantDeclaratorRest
3701      */
3702     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc, boolean localDecl) {
3703         return variableDeclaratorRest(token.pos, mods, type, identOrUnderscore(), reqInit, dc, localDecl, true);
3704     }
3705 
3706     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
3707      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
3708      *
3709      *  @param reqInit  Is an initializer always required?
3710      *  @param dc       The documentation comment for the variable declarations, or null.
3711      */
3712     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
3713                                   boolean reqInit, Comment dc, boolean localDecl, boolean compound) {
3714         boolean declaredUsingVar = false;
3715         JCExpression init = null;
3716         type = bracketsOpt(type);
3717 
3718         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
3719             if (!localDecl) {
3720                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.UseOfUnderscoreNotAllowed);
3721             }
3722             name = names.empty;
3723         }
3724 
3725         if (token.kind == EQ) {
3726             nextToken();
3727             init = variableInitializer();
3728         }
3729         else if (reqInit) syntaxError(token.pos, Errors.Expected(EQ));
3730 
3731         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.empty
3732                 && localDecl
3733                 && init == null
3734                 && token.kind != COLON) { // if its unnamed local variable, it needs to have an init unless in enhanced-for
3735             syntaxError(token.pos, Errors.Expected(EQ));
3736         }
3737 
3738         int startPos = Position.NOPOS;
3739         JCTree elemType = TreeInfo.innermostType(type, true);
3740         if (elemType.hasTag(IDENT)) {
3741             Name typeName = ((JCIdent) elemType).name;
3742             if (restrictedTypeNameStartingAtSource(typeName, pos, !compound && localDecl) != null) {
3743                 if (typeName != names.var) {
3744                     reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedHere(typeName));
3745                 } else if (type.hasTag(TYPEARRAY) && !compound) {
3746                     //error - 'var' and arrays
3747                     reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedArray(typeName));
3748                 } else {
3749                     declaredUsingVar = true;
3750                     if (compound)
3751                         //error - 'var' in compound local var decl
3752                         reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
3753                     startPos = TreeInfo.getStartPos(mods);
3754                     if (startPos == Position.NOPOS)
3755                         startPos = TreeInfo.getStartPos(type);
3756                     //implicit type
3757                     type = null;
3758                 }
3759             }
3760         }
3761         JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init, declaredUsingVar));
3762         attach(result, dc);
3763         result.startPos = startPos;
3764         return result;
3765     }
3766 
3767     Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
3768         switch (e.getTag()) {
3769             case IDENT:
3770                 return restrictedTypeNameStartingAtSource(((JCIdent)e).name, e.pos, shouldWarn) != null ? ((JCIdent)e).name : null;
3771             case TYPEARRAY:
3772                 return restrictedTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
3773             default:
3774                 return null;
3775         }
3776     }
3777 
3778     Source restrictedTypeNameStartingAtSource(Name name, int pos, boolean shouldWarn) {
3779         if (name == names.var) {
3780             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3781                 return Source.JDK10;
3782             } else if (shouldWarn) {
3783                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3784             }
3785         }
3786         if (name == names.yield) {
3787             if (allowYieldStatement) {
3788                 return Source.JDK14;
3789             } else if (shouldWarn) {
3790                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3791             }
3792         }
3793         if (name == names.record) {
3794             if (allowRecords) {
3795                 return Source.JDK14;
3796             } else if (shouldWarn) {
3797                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3798             }
3799         }
3800         if (name == names.value) {
3801             if (allowValueClasses) {
3802                 return Source.JDK22;
3803             } else if (shouldWarn) {
3804                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK22));
3805             }
3806         }
3807         if (name == names.sealed) {
3808             if (allowSealedTypes) {
3809                 return Source.JDK15;
3810             } else if (shouldWarn) {
3811                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3812             }
3813         }
3814         if (name == names.permits) {
3815             if (allowSealedTypes) {
3816                 return Source.JDK15;
3817             } else if (shouldWarn) {
3818                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3819             }
3820         }
3821         return null;
3822     }
3823 
3824     /** VariableDeclaratorId = Ident BracketsOpt
3825      */
3826     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
3827         int pos = token.pos;
3828         Name name;
3829         if (allowThisIdent ||
3830             !lambdaParameter ||
3831             LAX_IDENTIFIER.test(token.kind) ||
3832             mods.flags != Flags.PARAMETER ||
3833             mods.annotations.nonEmpty()) {
3834             JCExpression pn;
3835             if (token.kind == UNDERSCORE && (catchParameter || lambdaParameter)) {
3836                 pn = toP(F.at(token.pos).Ident(identOrUnderscore()));
3837             } else {
3838                 pn = qualident(false);
3839             }
3840             if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
3841                 name = ((JCIdent)pn).name;
3842             } else if (lambdaParameter && type == null) {
3843                 // we have a lambda parameter that is not an identifier this is a syntax error
3844                 type = pn;
3845                 name = names.empty;
3846                 reportSyntaxError(pos, Errors.Expected(IDENTIFIER));
3847             } else {
3848                 if (allowThisIdent) {
3849                     if ((mods.flags & Flags.VARARGS) != 0) {
3850                         log.error(token.pos, Errors.VarargsAndReceiver);
3851                     }
3852                     if (token.kind == LBRACKET) {
3853                         log.error(token.pos, Errors.ArrayAndReceiver);
3854                     }
3855                     if (pn.hasTag(Tag.SELECT) && ((JCFieldAccess)pn).name != names._this) {
3856                         log.error(token.pos, Errors.WrongReceiver);
3857                     }
3858                 }
3859                 return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
3860             }
3861         } else {
3862             /** if it is a lambda parameter and the token kind is not an identifier,
3863              *  and there are no modifiers or annotations, then this means that the compiler
3864              *  supposed the lambda to be explicit but it can contain a mix of implicit,
3865              *  var or explicit parameters. So we assign the error name to the parameter name
3866              *  instead of issuing an error and analyze the lambda parameters as a whole at
3867              *  a higher level.
3868              */
3869             name = names.error;
3870         }
3871         if ((mods.flags & Flags.VARARGS) != 0 &&
3872                 token.kind == LBRACKET) {
3873             log.error(token.pos, Errors.VarargsAndOldArraySyntax);
3874         }
3875         if (recordComponent && token.kind == LBRACKET) {
3876             log.error(token.pos, Errors.RecordComponentAndOldArraySyntax);
3877         }
3878         type = bracketsOpt(type);
3879 
3880         if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
3881             name = names.empty;
3882         }
3883 
3884         return toP(F.at(pos).VarDef(mods, name, type, null,
3885                 type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var));
3886     }
3887 
3888     /** Resources = Resource { ";" Resources }
3889      */
3890     List<JCTree> resources() {
3891         ListBuffer<JCTree> defs = new ListBuffer<>();
3892         defs.append(resource());
3893         while (token.kind == SEMI) {
3894             // All but last of multiple declarators must subsume a semicolon
3895             storeEnd(defs.last(), token.endPos);
3896             int semiColonPos = token.pos;
3897             nextToken();
3898             if (token.kind == RPAREN) { // Optional trailing semicolon
3899                                        // after last resource
3900                 break;
3901             }
3902             defs.append(resource());
3903         }
3904         return defs.toList();
3905     }
3906 
3907     /** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression
3908      *           | Expression
3909      */
3910     protected JCTree resource() {
3911         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3912             JCModifiers mods = optFinal(0);
3913             JCExpression t = parseType(true);
3914             return variableDeclaratorRest(token.pos, mods, t, identOrUnderscore(), true, null, true, false);
3915         }
3916         JCExpression t = term(EXPR | TYPE);
3917         if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3918             JCModifiers mods = F.Modifiers(0);
3919             return variableDeclaratorRest(token.pos, mods, t, identOrUnderscore(), true, null, true, false);
3920         } else {
3921             checkSourceLevel(Feature.EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES);
3922             if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
3923                 log.error(t.pos(), Errors.TryWithResourcesExprNeedsVar);
3924             }
3925 
3926             return t;
3927         }
3928     }
3929 
3930     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
3931      */
3932     public JCTree.JCCompilationUnit parseCompilationUnit() {
3933         Token firstToken = token;
3934         JCModifiers mods = null;
3935         boolean consumedToplevelDoc = false;
3936         boolean seenImport = false;
3937         boolean seenPackage = false;
3938         ListBuffer<JCTree> defs = new ListBuffer<>();
3939         if (token.kind == MONKEYS_AT)
3940             mods = modifiersOpt();
3941 
3942         if (token.kind == PACKAGE) {
3943             int packagePos = token.pos;
3944             List<JCAnnotation> annotations = List.nil();
3945             seenPackage = true;
3946             if (mods != null) {
3947                 checkNoMods(mods.flags & ~Flags.DEPRECATED);
3948                 annotations = mods.annotations;
3949                 mods = null;
3950             }
3951             nextToken();
3952             JCExpression pid = qualident(false);
3953             accept(SEMI);
3954             JCPackageDecl pd = toP(F.at(packagePos).PackageDecl(annotations, pid));
3955             attach(pd, firstToken.docComment());
3956             consumedToplevelDoc = true;
3957             defs.append(pd);
3958         }
3959 
3960         boolean firstTypeDecl = true;   // have we seen a class, enum, or interface declaration yet?
3961         boolean isImplicitClass = false;
3962         OUTER: while (token.kind != EOF) {
3963             if (token.pos <= endPosTable.errorEndPos) {
3964                 // error recovery
3965                 skip(firstTypeDecl, false, false, false);
3966                 if (token.kind == EOF)
3967                     break;
3968             }
3969             // JLS 7.3 doesn't allow extra semicolons after package or import declarations,
3970             // but here we try to provide a more helpful error message if we encounter any.
3971             // Do that by slurping in as many semicolons as possible, and then seeing what
3972             // comes after before deciding how best to handle them.
3973             ListBuffer<JCTree> semiList = new ListBuffer<>();
3974             while (firstTypeDecl && mods == null && token.kind == SEMI) {
3975                 semiList.append(toP(F.at(token.pos).Skip()));
3976                 nextToken();
3977                 if (token.kind == EOF)
3978                     break OUTER;
3979             }
3980             if (firstTypeDecl && mods == null && token.kind == IMPORT) {
3981                 if (!semiList.isEmpty()) {
3982                     if (source.compareTo(Source.JDK21) >= 0)
3983                         reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
3984                     else
3985                         log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
3986                 }
3987                 seenImport = true;
3988                 defs.append(importDeclaration());
3989             } else {
3990                 Comment docComment = token.docComment();
3991                 if (firstTypeDecl && !seenImport && !seenPackage) {
3992                     docComment = firstToken.docComment();
3993                     consumedToplevelDoc = true;
3994                 }
3995                 if (mods != null || token.kind != SEMI)
3996                     mods = modifiersOpt(mods);
3997                 if (firstTypeDecl && token.kind == IDENTIFIER) {
3998                     if (!semiList.isEmpty()) {
3999                         if (source.compareTo(Source.JDK21) >= 0)
4000                             reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
4001                         else
4002                             log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
4003                     }
4004                     ModuleKind kind = ModuleKind.STRONG;
4005                     if (token.name() == names.open) {
4006                         kind = ModuleKind.OPEN;
4007                         nextToken();
4008                     }
4009                     if (token.kind == IDENTIFIER && token.name() == names.module) {
4010                         if (mods != null) {
4011                             checkNoMods(mods.flags & ~Flags.DEPRECATED);
4012                         }
4013                         defs.append(moduleDecl(mods, kind, docComment));
4014                         consumedToplevelDoc = true;
4015                         break;
4016                     } else if (kind != ModuleKind.STRONG) {
4017                         reportSyntaxError(token.pos, Errors.ExpectedModule);
4018                     }
4019                 }
4020 
4021                 defs.appendList(semiList.toList());
4022                 boolean isTopLevelMethodOrField = false;
4023 
4024                 // Due to a significant number of existing negative tests
4025                 // this code speculatively tests to see if a top level method
4026                 // or field can parse. If the method or field can parse then
4027                 // it is parsed. Otherwise, parsing continues as though
4028                 // implicitly declared classes did not exist and error reporting
4029                 // is the same as in the past.
4030                 if (Feature.IMPLICIT_CLASSES.allowedInSource(source) && !isDeclaration()) {
4031                     final JCModifiers finalMods = mods;
4032                     JavacParser speculative = new VirtualParser(this);
4033                     List<JCTree> speculativeResult =
4034                             speculative.topLevelMethodOrFieldDeclaration(finalMods, null);
4035                     if (speculativeResult.head.hasTag(METHODDEF) ||
4036                         speculativeResult.head.hasTag(VARDEF)) {
4037                         isTopLevelMethodOrField = true;
4038                     }
4039                 }
4040 
4041                 if (isTopLevelMethodOrField) {
4042                     checkSourceLevel(token.pos, Feature.IMPLICIT_CLASSES);
4043                     defs.appendList(topLevelMethodOrFieldDeclaration(mods, docComment));
4044                     isImplicitClass = true;
4045                 } else {
4046                     JCTree def = typeDeclaration(mods, docComment);
4047                     if (def instanceof JCExpressionStatement statement)
4048                         def = statement.expr;
4049                     defs.append(def);
4050                 }
4051 
4052                 mods = null;
4053                 firstTypeDecl = false;
4054             }
4055         }
4056         List<JCTree> topLevelDefs = isImplicitClass ?  constructImplicitClass(defs.toList()) : defs.toList();
4057         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(topLevelDefs);
4058         if (!consumedToplevelDoc)
4059             attach(toplevel, firstToken.docComment());
4060         if (defs.isEmpty())
4061             storeEnd(toplevel, S.prevToken().endPos);
4062         if (keepDocComments)
4063             toplevel.docComments = docComments;
4064         if (keepLineMap)
4065             toplevel.lineMap = S.getLineMap();
4066         this.endPosTable.setParser(null); // remove reference to parser
4067         toplevel.endPositions = this.endPosTable;
4068         return toplevel;
4069     }
4070 
4071     // Restructure top level to be an implicitly declared class.
4072     private List<JCTree> constructImplicitClass(List<JCTree> origDefs) {
4073         ListBuffer<JCTree> topDefs = new ListBuffer<>();
4074         ListBuffer<JCTree> defs = new ListBuffer<>();
4075 
4076         for (JCTree def : origDefs) {
4077             if (def.hasTag(Tag.PACKAGEDEF)) {
4078                 log.error(def.pos(), Errors.ImplicitClassShouldNotHavePackageDeclaration);
4079             } else if (def.hasTag(Tag.IMPORT)) {
4080                 topDefs.append(def);
4081             } else if (!def.hasTag(Tag.SKIP)) {
4082                 defs.append(def);
4083             }
4084         }
4085 
4086         int primaryPos = getStartPos(defs.first());
4087         String simplename = PathFileObject.getSimpleName(log.currentSourceFile());
4088 
4089         if (simplename.endsWith(".java")) {
4090             simplename = simplename.substring(0, simplename.length() - ".java".length());
4091         }
4092         if (!SourceVersion.isIdentifier(simplename) || SourceVersion.isKeyword(simplename)) {
4093             log.error(primaryPos, Errors.BadFileName(simplename));
4094         }
4095 
4096         Name name = names.fromString(simplename);
4097         JCModifiers implicitMods = F.at(Position.NOPOS)
4098                 .Modifiers(Flags.FINAL|Flags.IMPLICIT_CLASS, List.nil());
4099         JCClassDecl implicit = F.at(primaryPos).ClassDef(
4100                 implicitMods, name, List.nil(), null, List.nil(), List.nil(),
4101                 defs.toList());
4102         topDefs.append(implicit);
4103         return topDefs.toList();
4104     }
4105 
4106     JCModuleDecl moduleDecl(JCModifiers mods, ModuleKind kind, Comment dc) {
4107         int pos = token.pos;
4108         checkSourceLevel(Feature.MODULES);
4109 
4110         nextToken();
4111         JCExpression name = qualident(false);
4112         List<JCDirective> directives = null;
4113 
4114         accept(LBRACE);
4115         directives = moduleDirectiveList();
4116         accept(RBRACE);
4117         accept(EOF);
4118 
4119         JCModuleDecl result = toP(F.at(pos).ModuleDef(mods, kind, name, directives));
4120         attach(result, dc);
4121         return result;
4122     }
4123 
4124     List<JCDirective> moduleDirectiveList() {
4125         ListBuffer<JCDirective> defs = new ListBuffer<>();
4126         while (token.kind == IDENTIFIER) {
4127             int pos = token.pos;
4128             if (token.name() == names.requires) {
4129                 nextToken();
4130                 boolean isTransitive = false;
4131                 boolean isStaticPhase = false;
4132             loop:
4133                 while (true) {
4134                     switch (token.kind) {
4135                         case IDENTIFIER:
4136                             if (token.name() == names.transitive && !isTransitive) {
4137                                 Token t1 = S.token(1);
4138                                 if (t1.kind == SEMI || t1.kind == DOT) {
4139                                     break loop;
4140                                 }
4141                                 isTransitive = true;
4142                                 break;
4143                             } else {
4144                                 break loop;
4145                             }
4146                         case STATIC:
4147                             if (isStaticPhase) {
4148                                 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
4149                             }
4150                             isStaticPhase = true;
4151                             break;
4152                         default:
4153                             break loop;
4154                     }
4155                     nextToken();
4156                 }
4157                 JCExpression moduleName = qualident(false);
4158                 accept(SEMI);
4159                 defs.append(toP(F.at(pos).Requires(isTransitive, isStaticPhase, moduleName)));
4160             } else if (token.name() == names.exports || token.name() == names.opens) {
4161                 boolean exports = token.name() == names.exports;
4162                 nextToken();
4163                 JCExpression pkgName = qualident(false);
4164                 List<JCExpression> moduleNames = null;
4165                 if (token.kind == IDENTIFIER && token.name() == names.to) {
4166                     nextToken();
4167                     moduleNames = qualidentList(false);
4168                 }
4169                 accept(SEMI);
4170                 JCDirective d;
4171                 if (exports) {
4172                     d = F.at(pos).Exports(pkgName, moduleNames);
4173                 } else {
4174                     d = F.at(pos).Opens(pkgName, moduleNames);
4175                 }
4176                 defs.append(toP(d));
4177             } else if (token.name() == names.provides) {
4178                 nextToken();
4179                 JCExpression serviceName = qualident(false);
4180                 List<JCExpression> implNames;
4181                 if (token.kind == IDENTIFIER && token.name() == names.with) {
4182                     nextToken();
4183                     implNames = qualidentList(false);
4184                 } else {
4185                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ExpectedStr("'" + names.with + "'"));
4186                     implNames = List.nil();
4187                 }
4188                 accept(SEMI);
4189                 defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
4190             } else if (token.name() == names.uses) {
4191                 nextToken();
4192                 JCExpression service = qualident(false);
4193                 accept(SEMI);
4194                 defs.append(toP(F.at(pos).Uses(service)));
4195             } else {
4196                 setErrorEndPos(pos);
4197                 reportSyntaxError(pos, Errors.InvalidModuleDirective);
4198                 break;
4199             }
4200         }
4201         return defs.toList();
4202     }
4203 
4204     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
4205      */
4206     protected JCTree importDeclaration() {
4207         int pos = token.pos;
4208         nextToken();
4209         boolean importStatic = false;
4210         if (token.kind == STATIC) {
4211             importStatic = true;
4212             nextToken();
4213         }
4214         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
4215         do {
4216             int pos1 = token.pos;
4217             accept(DOT);
4218             if (token.kind == STAR) {
4219                 pid = to(F.at(pos1).Select(pid, names.asterisk));
4220                 nextToken();
4221                 break;
4222             } else {
4223                 pid = toP(F.at(pos1).Select(pid, ident()));
4224             }
4225         } while (token.kind == DOT);
4226         accept(SEMI);
4227         return toP(F.at(pos).Import((JCFieldAccess)pid, importStatic));
4228     }
4229 
4230     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
4231      *                  | ";"
4232      */
4233     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
4234         int pos = token.pos;
4235         if (mods == null && token.kind == SEMI) {
4236             nextToken();
4237             return toP(F.at(pos).Skip());
4238         } else {
4239             return classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
4240         }
4241     }
4242 
4243     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
4244      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
4245      *  @param mods     Any modifiers starting the class or interface declaration
4246      *  @param dc       The documentation comment for the class, or null.
4247      */
4248     protected JCStatement classOrRecordOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
4249         if (token.kind == CLASS) {
4250             return classDeclaration(mods, dc);
4251         } if (isRecordStart()) {
4252             return recordDeclaration(mods, dc);
4253         } else if (token.kind == INTERFACE) {
4254             return interfaceDeclaration(mods, dc);
4255         } else if (token.kind == ENUM) {
4256             return enumDeclaration(mods, dc);
4257         } else {
4258             int pos = token.pos;
4259             List<JCTree> errs;
4260             if (LAX_IDENTIFIER.test(token.kind)) {
4261                 errs = List.of(mods, toP(F.at(pos).Ident(ident())));
4262                 setErrorEndPos(token.pos);
4263             } else {
4264                 errs = List.of(mods);
4265             }
4266 
4267             JCDiagnostic.Error error;
4268             if (parseModuleInfo) {
4269                 error = Errors.ExpectedModuleOrOpen;
4270             } else if (allowRecords) {
4271                 error = Errors.Expected4(CLASS, INTERFACE, ENUM, "record");
4272             } else {
4273                 error = Errors.Expected3(CLASS, INTERFACE, ENUM);
4274             }
4275             return toP(F.Exec(syntaxError(pos, errs, error)));
4276 
4277         }
4278     }
4279 
4280     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
4281      *                     [IMPLEMENTS TypeList] ClassBody
4282      *  @param mods    The modifiers starting the class declaration
4283      *  @param dc       The documentation comment for the class, or null.
4284      */
4285     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
4286         int pos = token.pos;
4287         accept(CLASS);
4288         Name name = typeName();
4289 
4290         List<JCTypeParameter> typarams = typeParametersOpt();
4291 
4292         JCExpression extending = null;
4293         if (token.kind == EXTENDS) {
4294             nextToken();
4295             extending = parseType();
4296         }
4297         List<JCExpression> implementing = List.nil();
4298         if (token.kind == IMPLEMENTS) {
4299             nextToken();
4300             implementing = typeList();
4301         }
4302         List<JCExpression> permitting = permitsClause(mods, "class");
4303         List<JCTree> defs = classInterfaceOrRecordBody(name, false, false);
4304         JCClassDecl result = toP(F.at(pos).ClassDef(
4305             mods, name, typarams, extending, implementing, permitting, defs));
4306         attach(result, dc);
4307         return result;
4308     }
4309 
4310     protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) {
4311         int pos = token.pos;
4312         nextToken();
4313         mods.flags |= Flags.RECORD;
4314         Name name = typeName();
4315 
4316         List<JCTypeParameter> typarams = typeParametersOpt();
4317 
4318         List<JCVariableDecl> headerFields = formalParameters(false, true);
4319 
4320         List<JCExpression> implementing = List.nil();
4321         if (token.kind == IMPLEMENTS) {
4322             nextToken();
4323             implementing = typeList();
4324         }
4325         List<JCTree> defs = classInterfaceOrRecordBody(name, false, true);
4326         java.util.List<JCVariableDecl> fields = new ArrayList<>();
4327         for (JCVariableDecl field : headerFields) {
4328             fields.add(field);
4329         }
4330         for (JCTree def : defs) {
4331             if (def.hasTag(METHODDEF)) {
4332                 JCMethodDecl methDef = (JCMethodDecl) def;
4333                 if (methDef.name == names.init && methDef.params.isEmpty() && (methDef.mods.flags & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0) {
4334                     ListBuffer<JCVariableDecl> tmpParams = new ListBuffer<>();
4335                     for (JCVariableDecl param : headerFields) {
4336                         tmpParams.add(F.at(param)
4337                                 // we will get flags plus annotations from the record component
4338                                 .VarDef(F.Modifiers(Flags.PARAMETER | Flags.GENERATED_MEMBER | Flags.MANDATED | param.mods.flags & Flags.VARARGS,
4339                                         param.mods.annotations),
4340                                 param.name, param.vartype, null));
4341                     }
4342                     methDef.params = tmpParams.toList();
4343                 }
4344             }
4345         }
4346         for (int i = fields.size() - 1; i >= 0; i--) {
4347             JCVariableDecl field = fields.get(i);
4348             defs = defs.prepend(field);
4349         }
4350         JCClassDecl result = toP(F.at(pos).ClassDef(mods, name, typarams, null, implementing, defs));
4351         attach(result, dc);
4352         return result;
4353     }
4354 
4355     Name typeName() {
4356         int pos = token.pos;
4357         Name name = ident();
4358         Source source = restrictedTypeNameStartingAtSource(name, pos, true);
4359         if (source != null) {
4360             reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, source));
4361         }
4362         return name;
4363     }
4364 
4365     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
4366      *                         [EXTENDS TypeList] InterfaceBody
4367      *  @param mods    The modifiers starting the interface declaration
4368      *  @param dc       The documentation comment for the interface, or null.
4369      */
4370     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
4371         int pos = token.pos;
4372         accept(INTERFACE);
4373 
4374         Name name = typeName();
4375 
4376         List<JCTypeParameter> typarams = typeParametersOpt();
4377 
4378         List<JCExpression> extending = List.nil();
4379         if (token.kind == EXTENDS) {
4380             nextToken();
4381             extending = typeList();
4382         }
4383         List<JCExpression> permitting = permitsClause(mods, "interface");
4384         List<JCTree> defs;
4385         defs = classInterfaceOrRecordBody(name, true, false);
4386         JCClassDecl result = toP(F.at(pos).ClassDef(
4387             mods, name, typarams, null, extending, permitting, defs));
4388         attach(result, dc);
4389         return result;
4390     }
4391 
4392     List<JCExpression> permitsClause(JCModifiers mods, String classOrInterface) {
4393         if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
4394             checkSourceLevel(Feature.SEALED_CLASSES);
4395             if ((mods.flags & Flags.SEALED) == 0) {
4396                 log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed(classOrInterface)));
4397             }
4398             nextToken();
4399             return qualidentList(false);
4400         }
4401         return List.nil();
4402     }
4403 
4404     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
4405      *  @param mods    The modifiers starting the enum declaration
4406      *  @param dc       The documentation comment for the enum, or null.
4407      */
4408     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
4409         int pos = token.pos;
4410         accept(ENUM);
4411 
4412         Name name = typeName();
4413 
4414         int typeNamePos = token.pos;
4415         List<JCTypeParameter> typarams = typeParametersOpt(true);
4416         if (typarams == null || !typarams.isEmpty()) {
4417             int errorPosition = typarams == null
4418                     ? typeNamePos
4419                     : typarams.head.pos;
4420             log.error(DiagnosticFlag.SYNTAX, errorPosition, Errors.EnumCantBeGeneric);
4421         }
4422 
4423         List<JCExpression> implementing = List.nil();
4424         if (token.kind == IMPLEMENTS) {
4425             nextToken();
4426             implementing = typeList();
4427         }
4428 
4429         List<JCTree> defs = enumBody(name);
4430         mods.flags |= Flags.ENUM;
4431         JCClassDecl result = toP(F.at(pos).
4432             ClassDef(mods, name, List.nil(),
4433                      null, implementing, defs));
4434         attach(result, dc);
4435         return result;
4436     }
4437 
4438     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
4439      *                  [ ";" {ClassBodyDeclaration} ] "}"
4440      */
4441     List<JCTree> enumBody(Name enumName) {
4442         accept(LBRACE);
4443         ListBuffer<JCTree> defs = new ListBuffer<>();
4444         boolean wasSemi = false;
4445         boolean hasStructuralErrors = false;
4446         boolean wasError = false;
4447         if (token.kind == COMMA) {
4448             nextToken();
4449             if (token.kind == SEMI) {
4450                 wasSemi = true;
4451                 nextToken();
4452             } else if (token.kind != RBRACE) {
4453                 reportSyntaxError(S.prevToken().endPos,
4454                                   Errors.Expected2(RBRACE, SEMI));
4455                 wasError = true;
4456             }
4457         }
4458         while (token.kind != RBRACE && token.kind != EOF) {
4459             if (token.kind == SEMI) {
4460                 accept(SEMI);
4461                 wasSemi = true;
4462                 if (token.kind == RBRACE || token.kind == EOF) break;
4463             }
4464             EnumeratorEstimate memberType = estimateEnumeratorOrMember(enumName);
4465             if (memberType == EnumeratorEstimate.UNKNOWN) {
4466                 memberType = wasSemi ? EnumeratorEstimate.MEMBER
4467                                      : EnumeratorEstimate.ENUMERATOR;
4468             }
4469             if (memberType == EnumeratorEstimate.ENUMERATOR) {
4470                 wasError = false;
4471                 if (wasSemi && !hasStructuralErrors) {
4472                     reportSyntaxError(token.pos, Errors.EnumConstantNotExpected);
4473                     hasStructuralErrors = true;
4474                 }
4475                 defs.append(enumeratorDeclaration(enumName));
4476                 if (token.pos <= endPosTable.errorEndPos) {
4477                     // error recovery
4478                    skip(false, true, true, false);
4479                 } else {
4480                     if (token.kind != RBRACE && token.kind != SEMI && token.kind != EOF) {
4481                         if (token.kind == COMMA) {
4482                             nextToken();
4483                         } else {
4484                             setErrorEndPos(token.pos);
4485                             reportSyntaxError(S.prevToken().endPos,
4486                                               Errors.Expected3(COMMA, RBRACE, SEMI));
4487                             wasError = true;
4488                         }
4489                     }
4490                 }
4491             } else {
4492                 if (!wasSemi && !hasStructuralErrors && !wasError) {
4493                     reportSyntaxError(token.pos, Errors.EnumConstantExpected);
4494                     hasStructuralErrors = true;
4495                 }
4496                 wasError = false;
4497                 defs.appendList(classOrInterfaceOrRecordBodyDeclaration(null, enumName,
4498                                                                 false, false));
4499                 if (token.pos <= endPosTable.errorEndPos) {
4500                     // error recovery
4501                    skip(false, true, true, false);
4502                 }
4503             }
4504         }
4505         accept(RBRACE);
4506         return defs.toList();
4507     }
4508 
4509     @SuppressWarnings("fallthrough")
4510     private EnumeratorEstimate estimateEnumeratorOrMember(Name enumName) {
4511         // if we are seeing a record declaration inside of an enum we want the same error message as expected for a
4512         // let's say an interface declaration inside an enum
4513         boolean ident = token.kind == TokenKind.IDENTIFIER ||
4514                         token.kind == TokenKind.UNDERSCORE;
4515         if (ident && token.name() != enumName &&
4516                 (!allowRecords || !isRecordStart())) {
4517             Token next = S.token(1);
4518             switch (next.kind) {
4519                 case LPAREN: case LBRACE: case COMMA: case SEMI:
4520                     return EnumeratorEstimate.ENUMERATOR;
4521             }
4522         }
4523         switch (token.kind) {
4524             case IDENTIFIER:
4525                 if (allowRecords && isRecordStart()) {
4526                     return EnumeratorEstimate.MEMBER;
4527                 }
4528             case MONKEYS_AT: case LT: case UNDERSCORE:
4529                 return EnumeratorEstimate.UNKNOWN;
4530             default:
4531                 return EnumeratorEstimate.MEMBER;
4532         }
4533     }
4534 
4535     private enum EnumeratorEstimate {
4536         ENUMERATOR,
4537         MEMBER,
4538         UNKNOWN;
4539     }
4540 
4541     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
4542      */
4543     JCTree enumeratorDeclaration(Name enumName) {
4544         Comment dc = token.docComment();
4545         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
4546         if (token.deprecatedFlag()) {
4547             flags |= Flags.DEPRECATED;
4548         }
4549         int pos = token.pos;
4550         List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
4551         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
4552         List<JCExpression> typeArgs = typeArgumentsOpt();
4553         int identPos = token.pos;
4554         Name name = ident();
4555         int createPos = token.pos;
4556         List<JCExpression> args = (token.kind == LPAREN)
4557             ? arguments() : List.nil();
4558         JCClassDecl body = null;
4559         if (token.kind == LBRACE) {
4560             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM);
4561             List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
4562             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
4563         }
4564         if (args.isEmpty() && body == null)
4565             createPos = identPos;
4566         JCIdent ident = F.at(identPos).Ident(enumName);
4567         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
4568         if (createPos != identPos)
4569             storeEnd(create, S.prevToken().endPos);
4570         ident = F.at(identPos).Ident(enumName);
4571         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
4572         attach(result, dc);
4573         return result;
4574     }
4575 
4576     /** TypeList = Type {"," Type}
4577      */
4578     List<JCExpression> typeList() {
4579         ListBuffer<JCExpression> ts = new ListBuffer<>();
4580         ts.append(parseType());
4581         while (token.kind == COMMA) {
4582             nextToken();
4583             ts.append(parseType());
4584         }
4585         return ts.toList();
4586     }
4587 
4588     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
4589      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
4590      */
4591     List<JCTree> classInterfaceOrRecordBody(Name className, boolean isInterface, boolean isRecord) {
4592         accept(LBRACE);
4593         if (token.pos <= endPosTable.errorEndPos) {
4594             // error recovery
4595             skip(false, true, false, false);
4596             if (token.kind == LBRACE)
4597                 nextToken();
4598             else
4599                 return List.nil();
4600         }
4601         ListBuffer<JCTree> defs = new ListBuffer<>();
4602         while (token.kind != RBRACE && token.kind != EOF) {
4603             defs.appendList(classOrInterfaceOrRecordBodyDeclaration(null, className, isInterface, isRecord));
4604             if (token.pos <= endPosTable.errorEndPos) {
4605                // error recovery
4606                skip(false, true, true, false);
4607             }
4608         }
4609         accept(RBRACE);
4610         return defs.toList();
4611     }
4612 
4613     /** ClassBodyDeclaration =
4614      *      ";"
4615      *    | [STATIC] Block
4616      *    | ModifiersOpt
4617      *      ( Type Ident
4618      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
4619      *      | VOID Ident VoidMethodDeclaratorRest
4620      *      | TypeParameters [Annotations]
4621      *        ( Type Ident MethodDeclaratorRest
4622      *        | VOID Ident VoidMethodDeclaratorRest
4623      *        )
4624      *      | Ident ConstructorDeclaratorRest
4625      *      | TypeParameters Ident ConstructorDeclaratorRest
4626      *      | ClassOrInterfaceOrEnumDeclaration
4627      *      )
4628      *  InterfaceBodyDeclaration =
4629      *      ";"
4630      *    | ModifiersOpt
4631      *      ( Type Ident
4632      *        ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
4633      *      | VOID Ident MethodDeclaratorRest
4634      *      | TypeParameters [Annotations]
4635      *        ( Type Ident MethodDeclaratorRest
4636      *        | VOID Ident VoidMethodDeclaratorRest
4637      *        )
4638      *      | ClassOrInterfaceOrEnumDeclaration
4639      *      )
4640      *
4641      */
4642     protected List<JCTree> classOrInterfaceOrRecordBodyDeclaration(JCModifiers mods, Name className,
4643                                                                    boolean isInterface,
4644                                                                    boolean isRecord) {
4645         if (token.kind == SEMI) {
4646             nextToken();
4647             return List.nil();
4648         } else {
4649             Comment dc = token.docComment();
4650             int pos = token.pos;
4651             mods = modifiersOpt(mods);
4652             if (isDeclaration()) {
4653                 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
4654             } else if (token.kind == LBRACE &&
4655                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
4656                        mods.annotations.isEmpty()) {
4657                 if (isInterface) {
4658                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InitializerNotAllowed);
4659                 } else if (isRecord && (mods.flags & Flags.STATIC) == 0) {
4660                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InstanceInitializerNotAllowedInRecords);
4661                 }
4662                 return List.of(block(pos, mods.flags));
4663             } else {
4664                 return constructorOrMethodOrFieldDeclaration(mods, className, isInterface, isRecord, dc);
4665             }
4666         }
4667     }
4668 
4669     private List<JCTree> constructorOrMethodOrFieldDeclaration(JCModifiers mods, Name className,
4670                                                                boolean isInterface,
4671                                                                boolean isRecord, Comment dc) {
4672         int pos;
4673         pos = token.pos;
4674         List<JCTypeParameter> typarams = typeParametersOpt();
4675         // if there are type parameters but no modifiers, save the start
4676         // position of the method in the modifiers.
4677         if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4678             mods.pos = pos;
4679             storeEnd(mods, pos);
4680         }
4681         List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4682 
4683         if (annosAfterParams.nonEmpty()) {
4684             mods.annotations = mods.annotations.appendList(annosAfterParams);
4685             if (mods.pos == Position.NOPOS)
4686                 mods.pos = mods.annotations.head.pos;
4687         }
4688 
4689         Token tk = token;
4690         pos = token.pos;
4691         JCExpression type;
4692         boolean isVoid = token.kind == VOID;
4693 
4694         if (isVoid) {
4695             type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4696             nextToken();
4697         } else {
4698             // method returns types are un-annotated types
4699             type = unannotatedType(false);
4700         }
4701 
4702         // Constructor
4703         if ((token.kind == LPAREN && !isInterface ||
4704                 isRecord && token.kind == LBRACE) && type.hasTag(IDENT)) {
4705             if (isInterface || tk.name() != className) {
4706                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq);
4707             } else if (annosAfterParams.nonEmpty()) {
4708                 illegal(annosAfterParams.head.pos);
4709             }
4710 
4711             if (isRecord && token.kind == LBRACE) {
4712                 mods.flags |= Flags.COMPACT_RECORD_CONSTRUCTOR;
4713             }
4714 
4715             return List.of(methodDeclaratorRest(
4716                     pos, mods, null, names.init, typarams,
4717                     isInterface, true, isRecord, dc));
4718         }
4719 
4720         // Record constructor
4721         if (isRecord && type.hasTag(IDENT) && token.kind == THROWS) {
4722             // trying to define a compact constructor with a throws clause
4723             log.error(DiagnosticFlag.SYNTAX, token.pos,
4724                     Errors.InvalidCanonicalConstructorInRecord(
4725                             Fragments.Compact,
4726                             className,
4727                             Fragments.ThrowsClauseNotAllowedForCanonicalConstructor(Fragments.Compact)));
4728             skip(false, true, false, false);
4729             return List.of(methodDeclaratorRest(
4730                     pos, mods, null, names.init, typarams,
4731                     isInterface, true, isRecord, dc));
4732         }
4733 
4734         pos = token.pos;
4735         Name name = ident();
4736 
4737         // Method
4738         if (token.kind == LPAREN) {
4739             return List.of(methodDeclaratorRest(
4740                     pos, mods, type, name, typarams,
4741                     isInterface, isVoid, false, dc));
4742         }
4743 
4744         // Field
4745         if (!isVoid && typarams.isEmpty()) {
4746             if (!isRecord || (isRecord && (mods.flags & Flags.STATIC) != 0)) {
4747                 List<JCTree> defs =
4748                     variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4749                                             new ListBuffer<JCTree>(), false).toList();
4750                 accept(SEMI);
4751                 storeEnd(defs.last(), S.prevToken().endPos);
4752                 return defs;
4753             }
4754 
4755             int errPos = pos;
4756             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4757                     new ListBuffer<JCTree>(), false).toList();
4758             accept(SEMI);
4759             return List.of(syntaxError(errPos, null, Errors.RecordCannotDeclareInstanceFields));
4760          }
4761 
4762          pos = token.pos;
4763          List<JCTree> err;
4764 
4765          // Error recovery
4766          if (isVoid || typarams.nonEmpty()) {
4767              JCMethodDecl m =
4768                      toP(F.at(pos).MethodDef(mods, name, type, typarams,
4769                                              List.nil(), List.nil(), null, null));
4770              attach(m, dc);
4771              err = List.of(m);
4772          } else {
4773              err = List.nil();
4774          }
4775 
4776          return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
4777     }
4778 
4779     private List<JCTree> topLevelMethodOrFieldDeclaration(JCModifiers mods, Comment dc) throws AssertionError {
4780         int pos = token.pos;
4781         dc = dc == null ? token.docComment() : dc;
4782         List<JCTypeParameter> typarams = typeParametersOpt();
4783 
4784         // if there are type parameters but no modifiers, save the start
4785         // position of the method in the modifiers.
4786         if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4787             mods.pos = pos;
4788             storeEnd(mods, pos);
4789         }
4790 
4791         List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4792 
4793         if (annosAfterParams.nonEmpty()) {
4794             mods.annotations = mods.annotations.appendList(annosAfterParams);
4795             if (mods.pos == Position.NOPOS)
4796                 mods.pos = mods.annotations.head.pos;
4797         }
4798 
4799         pos = token.pos;
4800         JCExpression type;
4801         boolean isVoid = token.kind == VOID;
4802 
4803         if (isVoid) {
4804             type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4805             nextToken();
4806         } else {
4807             type = unannotatedType(false);
4808         }
4809 
4810         if (token.kind == IDENTIFIER) {
4811             pos = token.pos;
4812             Name name = ident();
4813 
4814             // Method
4815             if (token.kind == LPAREN) {
4816                 return List.of(methodDeclaratorRest(pos, mods, type, name, typarams,
4817                         false, isVoid, false, dc));
4818             }
4819 
4820             // Field
4821             if (!isVoid && typarams.isEmpty() && (token.kind == EQ || token.kind == SEMI)) {
4822                 List<JCTree> defs =
4823                         variableDeclaratorsRest(pos, mods, type, name, false, dc,
4824                                 new ListBuffer<JCTree>(), false).toList();
4825                 accept(SEMI);
4826                 storeEnd(defs.last(), S.prevToken().endPos);
4827 
4828                 return defs;
4829             }
4830         }
4831 
4832         return List.of(F.Erroneous());
4833     }
4834 
4835     protected boolean isDeclaration() {
4836         return token.kind == CLASS ||
4837                token.kind == INTERFACE ||
4838                token.kind == ENUM ||
4839                isRecordStart() && allowRecords;
4840         }
4841 
4842     protected boolean isRecordStart() {
4843         if (token.kind == IDENTIFIER && token.name() == names.record && peekToken(TokenKind.IDENTIFIER)) {
4844             checkSourceLevel(Feature.RECORDS);
4845             return true;
4846         } else {
4847             return false;
4848         }
4849     }
4850 
4851     protected boolean isNonSealedClassStart(boolean local) {
4852         if (isNonSealedIdentifier(token, 0)) {
4853             Token next = S.token(3);
4854             return allowedAfterSealedOrNonSealed(next, local, true);
4855         }
4856         return false;
4857     }
4858 
4859     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4860         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4861             Token tokenSub = S.token(lookAheadOffset + 1);
4862             Token tokenSealed = S.token(lookAheadOffset + 2);
4863             if (someToken.endPos == tokenSub.pos &&
4864                     tokenSub.endPos == tokenSealed.pos &&
4865                     tokenSealed.name() == names.sealed) {
4866                 checkSourceLevel(Feature.SEALED_CLASSES);
4867                 return true;
4868             }
4869         }
4870         return false;
4871     }
4872 
4873     protected boolean isValueModifier() {
4874         if (token.kind == IDENTIFIER && token.name() == names.value) {
4875             boolean isValueModifier = false;
4876             Token next = S.token(1);
4877             switch (next.kind) {
4878                 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
4879                 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
4880                 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
4881                 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
4882                 case CLASS: case INTERFACE: case ENUM:
4883                     isValueModifier = true;
4884                     break;
4885                 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
4886                     if (next.name() == names.record || next.name() == names.value
4887                             || (mode & EXPR) != 0)
4888                         isValueModifier = true;
4889                     break;
4890             }
4891             if (isValueModifier) {
4892                 checkSourceLevel(Feature.VALUE_CLASSES);
4893                 return true;
4894             }
4895         }
4896         return false;
4897     }
4898 
4899     protected boolean isSealedClassStart(boolean local) {
4900         if (token.name() == names.sealed) {
4901             Token next = S.token(1);
4902             if (allowedAfterSealedOrNonSealed(next, local, false)) {
4903                 checkSourceLevel(Feature.SEALED_CLASSES);
4904                 return true;
4905             }
4906         }
4907         return false;
4908     }
4909 
4910     private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
4911         return local ?
4912             switch (next.kind) {
4913                 case MONKEYS_AT -> {
4914                     Token afterNext = S.token(2);
4915                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
4916                 }
4917                 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4918                 default -> false;
4919             } :
4920             switch (next.kind) {
4921                 case MONKEYS_AT -> {
4922                     Token afterNext = S.token(2);
4923                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
4924                 }
4925                 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4926                 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
4927                         next.name() == names.sealed ||
4928                         allowValueClasses && next.name() == names.value;
4929                 default -> false;
4930             };
4931     }
4932 
4933     /** MethodDeclaratorRest =
4934      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4935      *  VoidMethodDeclaratorRest =
4936      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
4937      *  ConstructorDeclaratorRest =
4938      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4939      */
4940     protected JCTree methodDeclaratorRest(int pos,
4941                               JCModifiers mods,
4942                               JCExpression type,
4943                               Name name,
4944                               List<JCTypeParameter> typarams,
4945                               boolean isInterface, boolean isVoid,
4946                               boolean isRecord,
4947                               Comment dc) {
4948         if (isInterface) {
4949             if ((mods.flags & Flags.PRIVATE) != 0) {
4950                 checkSourceLevel(Feature.PRIVATE_INTERFACE_METHODS);
4951             }
4952         }
4953         JCVariableDecl prevReceiverParam = this.receiverParam;
4954         try {
4955             this.receiverParam = null;
4956             // Parsing formalParameters sets the receiverParam, if present
4957             List<JCVariableDecl> params = List.nil();
4958             List<JCExpression> thrown = List.nil();
4959             if (!isRecord || name != names.init || token.kind == LPAREN) {
4960                 params = formalParameters();
4961                 if (!isVoid) type = bracketsOpt(type);
4962                 if (token.kind == THROWS) {
4963                     nextToken();
4964                     thrown = qualidentList(true);
4965                 }
4966             }
4967             JCBlock body = null;
4968             JCExpression defaultValue;
4969             if (token.kind == LBRACE) {
4970                 body = block();
4971                 defaultValue = null;
4972             } else {
4973                 if (token.kind == DEFAULT) {
4974                     accept(DEFAULT);
4975                     defaultValue = annotationValue();
4976                 } else {
4977                     defaultValue = null;
4978                 }
4979                 accept(SEMI);
4980                 if (token.pos <= endPosTable.errorEndPos) {
4981                     // error recovery
4982                     skip(false, true, false, false);
4983                     if (token.kind == LBRACE) {
4984                         body = block();
4985                     }
4986                 }
4987             }
4988 
4989             JCMethodDecl result =
4990                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
4991                                             receiverParam, params, thrown,
4992                                             body, defaultValue));
4993             attach(result, dc);
4994             return result;
4995         } finally {
4996             this.receiverParam = prevReceiverParam;
4997         }
4998     }
4999 
5000     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
5001      */
5002     List<JCExpression> qualidentList(boolean allowAnnos) {
5003         ListBuffer<JCExpression> ts = new ListBuffer<>();
5004 
5005         List<JCAnnotation> typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
5006         JCExpression qi = qualident(allowAnnos);
5007         if (!typeAnnos.isEmpty()) {
5008             JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
5009             ts.append(at);
5010         } else {
5011             ts.append(qi);
5012         }
5013         while (token.kind == COMMA) {
5014             nextToken();
5015 
5016             typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
5017             qi = qualident(allowAnnos);
5018             if (!typeAnnos.isEmpty()) {
5019                 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
5020                 ts.append(at);
5021             } else {
5022                 ts.append(qi);
5023             }
5024         }
5025         return ts.toList();
5026     }
5027 
5028     /**
5029      *  {@literal
5030      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
5031      *  }
5032      */
5033     protected List<JCTypeParameter> typeParametersOpt() {
5034         return typeParametersOpt(false);
5035     }
5036     /** Parses a potentially empty type parameter list if needed with `allowEmpty`.
5037      *  The caller is free to choose the desirable error message in this (erroneous) case.
5038      */
5039     protected List<JCTypeParameter> typeParametersOpt(boolean parseEmpty) {
5040         if (token.kind == LT) {
5041             ListBuffer<JCTypeParameter> typarams = new ListBuffer<>();
5042             nextToken();
5043 
5044             if (parseEmpty && token.kind == GT) {
5045                 accept(GT);
5046                 return null;
5047             }
5048 
5049             typarams.append(typeParameter());
5050             while (token.kind == COMMA) {
5051                 nextToken();
5052                 typarams.append(typeParameter());
5053             }
5054             accept(GT);
5055             return typarams.toList();
5056         } else {
5057             return List.nil();
5058         }
5059     }
5060 
5061     /**
5062      *  {@literal
5063      *  TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
5064      *  TypeParameterBound = EXTENDS Type {"&" Type}
5065      *  TypeVariable = Ident
5066      *  }
5067      */
5068     JCTypeParameter typeParameter() {
5069         int pos = token.pos;
5070         List<JCAnnotation> annos = typeAnnotationsOpt();
5071         Name name = typeName();
5072         ListBuffer<JCExpression> bounds = new ListBuffer<>();
5073         if (token.kind == EXTENDS) {
5074             nextToken();
5075             bounds.append(parseType());
5076             while (token.kind == AMP) {
5077                 nextToken();
5078                 bounds.append(parseType());
5079             }
5080         }
5081         return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
5082     }
5083 
5084     /** FormalParameters = "(" [ FormalParameterList ] ")"
5085      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
5086      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
5087      */
5088     List<JCVariableDecl> formalParameters() {
5089         return formalParameters(false, false);
5090     }
5091     List<JCVariableDecl> formalParameters(boolean lambdaParameters, boolean recordComponents) {
5092         ListBuffer<JCVariableDecl> params = new ListBuffer<>();
5093         JCVariableDecl lastParam;
5094         accept(LPAREN);
5095         if (token.kind != RPAREN) {
5096             this.allowThisIdent = !lambdaParameters && !recordComponents;
5097             lastParam = formalParameter(lambdaParameters, recordComponents);
5098             if (lastParam.nameexpr != null) {
5099                 this.receiverParam = lastParam;
5100             } else {
5101                 params.append(lastParam);
5102             }
5103             this.allowThisIdent = false;
5104             while (token.kind == COMMA) {
5105                 if ((lastParam.mods.flags & Flags.VARARGS) != 0) {
5106                     log.error(DiagnosticFlag.SYNTAX, lastParam, Errors.VarargsMustBeLast);
5107                 }
5108                 nextToken();
5109                 params.append(lastParam = formalParameter(lambdaParameters, recordComponents));
5110             }
5111         }
5112         if (token.kind == RPAREN) {
5113             nextToken();
5114         } else {
5115             setErrorEndPos(token.pos);
5116             reportSyntaxError(S.prevToken().endPos, Errors.Expected3(COMMA, RPAREN, LBRACKET));
5117         }
5118         return params.toList();
5119     }
5120 
5121     List<JCVariableDecl> implicitParameters(boolean hasParens) {
5122         if (hasParens) {
5123             accept(LPAREN);
5124         }
5125         ListBuffer<JCVariableDecl> params = new ListBuffer<>();
5126         if (token.kind != RPAREN && token.kind != ARROW) {
5127             params.append(implicitParameter());
5128             while (token.kind == COMMA) {
5129                 nextToken();
5130                 params.append(implicitParameter());
5131             }
5132         }
5133         if (hasParens) {
5134             accept(RPAREN);
5135         }
5136         return params.toList();
5137     }
5138 
5139     JCModifiers optFinal(long flags) {
5140         JCModifiers mods = modifiersOpt();
5141         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
5142         mods.flags |= flags;
5143         return mods;
5144     }
5145 
5146     /**
5147      * Inserts the annotations (and possibly a new array level)
5148      * to the left-most type in an array or nested type.
5149      *
5150      * When parsing a type like {@code @B Outer.Inner @A []}, the
5151      * {@code @A} annotation should target the array itself, while
5152      * {@code @B} targets the nested type {@code Outer}.
5153      *
5154      * Currently the parser parses the annotation first, then
5155      * the array, and then inserts the annotation to the left-most
5156      * nested type.
5157      *
5158      * When {@code createNewLevel} is true, then a new array
5159      * level is inserted as the most inner type, and have the
5160      * annotations target it.  This is useful in the case of
5161      * varargs, e.g. {@code String @A [] @B ...}, as the parser
5162      * first parses the type {@code String @A []} then inserts
5163      * a new array level with {@code @B} annotation.
5164      */
5165     private JCExpression insertAnnotationsToMostInner(
5166             JCExpression type, List<JCAnnotation> annos,
5167             boolean createNewLevel) {
5168         int origEndPos = getEndPos(type);
5169         JCExpression mostInnerType = type;
5170         JCArrayTypeTree mostInnerArrayType = null;
5171         while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) {
5172             mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType);
5173             mostInnerType = mostInnerArrayType.elemtype;
5174         }
5175 
5176         if (createNewLevel) {
5177             mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType));
5178             origEndPos = getEndPos(mostInnerType);
5179         }
5180 
5181         JCExpression mostInnerTypeToReturn = mostInnerType;
5182         if (annos.nonEmpty()) {
5183             JCExpression lastToModify = mostInnerType;
5184 
5185             while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) ||
5186                     TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
5187                 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) {
5188                     lastToModify = mostInnerType;
5189                     mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression();
5190                 }
5191                 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
5192                     lastToModify = mostInnerType;
5193                     mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz;
5194                 }
5195             }
5196 
5197             mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType);
5198 
5199             if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) {
5200                 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType;
5201             } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) {
5202                 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType;
5203             } else {
5204                 // We never saw a SELECT or TYPEAPPLY, return the annotated type.
5205                 mostInnerTypeToReturn = mostInnerType;
5206             }
5207         }
5208 
5209         if (mostInnerArrayType == null) {
5210             return mostInnerTypeToReturn;
5211         } else {
5212             mostInnerArrayType.elemtype = mostInnerTypeToReturn;
5213             storeEnd(type, origEndPos);
5214             return type;
5215         }
5216     }
5217 
5218     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
5219      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
5220      */
5221     protected JCVariableDecl formalParameter(boolean lambdaParameter, boolean recordComponent) {
5222         JCModifiers mods = !recordComponent ? optFinal(Flags.PARAMETER) : modifiersOpt();
5223         if (recordComponent && mods.flags != 0) {
5224             log.error(mods.pos, Errors.RecordCantDeclareFieldModifiers);
5225         }
5226         if (recordComponent) {
5227             mods.flags |= Flags.RECORD | Flags.FINAL | Flags.PRIVATE | Flags.GENERATED_MEMBER;
5228         }
5229         // need to distinguish between vararg annos and array annos
5230         // look at typeAnnotationsPushedBack comment
5231         this.permitTypeAnnotationsPushBack = true;
5232         JCExpression type = parseType(lambdaParameter);
5233         this.permitTypeAnnotationsPushBack = false;
5234 
5235         if (token.kind == ELLIPSIS) {
5236             List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack;
5237             typeAnnotationsPushedBack = List.nil();
5238             mods.flags |= Flags.VARARGS;
5239             // insert var arg type annotations
5240             type = insertAnnotationsToMostInner(type, varargsAnnos, true);
5241             nextToken();
5242         } else {
5243             // if not a var arg, then typeAnnotationsPushedBack should be null
5244             if (typeAnnotationsPushedBack.nonEmpty()) {
5245                 reportSyntaxError(typeAnnotationsPushedBack.head.pos, Errors.IllegalStartOfType);
5246             }
5247             typeAnnotationsPushedBack = List.nil();
5248         }
5249         return variableDeclaratorId(mods, type, false, lambdaParameter, recordComponent);
5250     }
5251 
5252     protected JCVariableDecl implicitParameter() {
5253         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
5254         return variableDeclaratorId(mods, null, false, true, false);
5255     }
5256 
5257 /* ---------- auxiliary methods -------------- */
5258     /** Check that given tree is a legal expression statement.
5259      */
5260     protected JCExpression checkExprStat(JCExpression t) {
5261         if (!TreeInfo.isExpressionStatement(t)) {
5262             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
5263             log.error(DiagnosticFlag.SYNTAX, ret, Errors.NotStmt);
5264             return ret;
5265         } else {
5266             return t;
5267         }
5268     }
5269 
5270     /** Return precedence of operator represented by token,
5271      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
5272      */
5273     static int prec(TokenKind token) {
5274         JCTree.Tag oc = optag(token);
5275         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
5276     }
5277 
5278     /**
5279      * Return the lesser of two positions, making allowance for either one
5280      * being unset.
5281      */
5282     static int earlier(int pos1, int pos2) {
5283         if (pos1 == Position.NOPOS)
5284             return pos2;
5285         if (pos2 == Position.NOPOS)
5286             return pos1;
5287         return (pos1 < pos2 ? pos1 : pos2);
5288     }
5289 
5290     /** Return operation tag of binary operator represented by token,
5291      *  No_TAG if token is not a binary operator.
5292      */
5293     static JCTree.Tag optag(TokenKind token) {
5294         switch (token) {
5295         case BARBAR:
5296             return OR;
5297         case AMPAMP:
5298             return AND;
5299         case BAR:
5300             return BITOR;
5301         case BAREQ:
5302             return BITOR_ASG;
5303         case CARET:
5304             return BITXOR;
5305         case CARETEQ:
5306             return BITXOR_ASG;
5307         case AMP:
5308             return BITAND;
5309         case AMPEQ:
5310             return BITAND_ASG;
5311         case EQEQ:
5312             return JCTree.Tag.EQ;
5313         case BANGEQ:
5314             return NE;
5315         case LT:
5316             return JCTree.Tag.LT;
5317         case GT:
5318             return JCTree.Tag.GT;
5319         case LTEQ:
5320             return LE;
5321         case GTEQ:
5322             return GE;
5323         case LTLT:
5324             return SL;
5325         case LTLTEQ:
5326             return SL_ASG;
5327         case GTGT:
5328             return SR;
5329         case GTGTEQ:
5330             return SR_ASG;
5331         case GTGTGT:
5332             return USR;
5333         case GTGTGTEQ:
5334             return USR_ASG;
5335         case PLUS:
5336             return JCTree.Tag.PLUS;
5337         case PLUSEQ:
5338             return PLUS_ASG;
5339         case SUB:
5340             return MINUS;
5341         case SUBEQ:
5342             return MINUS_ASG;
5343         case STAR:
5344             return MUL;
5345         case STAREQ:
5346             return MUL_ASG;
5347         case SLASH:
5348             return DIV;
5349         case SLASHEQ:
5350             return DIV_ASG;
5351         case PERCENT:
5352             return MOD;
5353         case PERCENTEQ:
5354             return MOD_ASG;
5355         case INSTANCEOF:
5356             return TYPETEST;
5357         default:
5358             return NO_TAG;
5359         }
5360     }
5361 
5362     /** Return operation tag of unary operator represented by token,
5363      *  No_TAG if token is not a binary operator.
5364      */
5365     static JCTree.Tag unoptag(TokenKind token) {
5366         switch (token) {
5367         case PLUS:
5368             return POS;
5369         case SUB:
5370             return NEG;
5371         case BANG:
5372             return NOT;
5373         case TILDE:
5374             return COMPL;
5375         case PLUSPLUS:
5376             return PREINC;
5377         case SUBSUB:
5378             return PREDEC;
5379         default:
5380             return NO_TAG;
5381         }
5382     }
5383 
5384     /** Return type tag of basic type represented by token,
5385      *  NONE if token is not a basic type identifier.
5386      */
5387     static TypeTag typetag(TokenKind token) {
5388         switch (token) {
5389         case BYTE:
5390             return TypeTag.BYTE;
5391         case CHAR:
5392             return TypeTag.CHAR;
5393         case SHORT:
5394             return TypeTag.SHORT;
5395         case INT:
5396             return TypeTag.INT;
5397         case LONG:
5398             return TypeTag.LONG;
5399         case FLOAT:
5400             return TypeTag.FLOAT;
5401         case DOUBLE:
5402             return TypeTag.DOUBLE;
5403         case BOOLEAN:
5404             return TypeTag.BOOLEAN;
5405         default:
5406             return TypeTag.NONE;
5407         }
5408     }
5409 
5410     void checkSourceLevel(Feature feature) {
5411         checkSourceLevel(token.pos, feature);
5412     }
5413 
5414     protected void checkSourceLevel(int pos, Feature feature) {
5415         if (preview.isPreview(feature) && !preview.isEnabled()) {
5416             //preview feature without --preview flag, error
5417             log.error(DiagnosticFlag.SOURCE_LEVEL, pos, preview.disabledError(feature));
5418         } else if (!feature.allowedInSource(source)) {
5419             //incompatible source level, error
5420             log.error(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name));
5421         } else if (preview.isPreview(feature)) {
5422             //use of preview feature, warn
5423             preview.warnPreview(pos, feature);
5424         }
5425     }
5426 
5427     /*
5428      * a functional source tree and end position mappings
5429      */
5430     protected static class SimpleEndPosTable extends AbstractEndPosTable {
5431 
5432         private final IntHashTable endPosMap;
5433 
5434         SimpleEndPosTable(JavacParser parser) {
5435             super(parser);
5436             endPosMap = new IntHashTable();
5437         }
5438 
5439         public void storeEnd(JCTree tree, int endpos) {
5440             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
5441         }
5442 
5443         protected <T extends JCTree> T to(T t) {
5444             storeEnd(t, parser.token.endPos);
5445             return t;
5446         }
5447 
5448         protected <T extends JCTree> T toP(T t) {
5449             storeEnd(t, parser.S.prevToken().endPos);
5450             return t;
5451         }
5452 
5453         public int getEndPos(JCTree tree) {
5454             int value = endPosMap.get(tree);
5455             // As long as Position.NOPOS==-1, this just returns value.
5456             return (value == -1) ? Position.NOPOS : value;
5457         }
5458 
5459         public int replaceTree(JCTree oldTree, JCTree newTree) {
5460             int pos = endPosMap.remove(oldTree);
5461             if (pos != -1) {
5462                 storeEnd(newTree, pos);
5463                 return pos;
5464             }
5465             return Position.NOPOS;
5466         }
5467     }
5468 
5469     /*
5470      * a default skeletal implementation without any mapping overhead.
5471      */
5472     protected static class EmptyEndPosTable extends AbstractEndPosTable {
5473 
5474         EmptyEndPosTable(JavacParser parser) {
5475             super(parser);
5476         }
5477 
5478         public void storeEnd(JCTree tree, int endpos) { /* empty */ }
5479 
5480         protected <T extends JCTree> T to(T t) {
5481             return t;
5482         }
5483 
5484         protected <T extends JCTree> T toP(T t) {
5485             return t;
5486         }
5487 
5488         public int getEndPos(JCTree tree) {
5489             return Position.NOPOS;
5490         }
5491 
5492         public int replaceTree(JCTree oldTree, JCTree newTree) {
5493             return Position.NOPOS;
5494         }
5495 
5496     }
5497 
5498     protected abstract static class AbstractEndPosTable implements EndPosTable {
5499         /**
5500          * The current parser.
5501          */
5502         protected JavacParser parser;
5503 
5504         /**
5505          * Store the last error position.
5506          */
5507         public int errorEndPos = Position.NOPOS;
5508 
5509         public AbstractEndPosTable(JavacParser parser) {
5510             this.parser = parser;
5511         }
5512 
5513         /**
5514          * Store current token's ending position for a tree, the value of which
5515          * will be the greater of last error position and the ending position of
5516          * the current token.
5517          * @param t The tree.
5518          */
5519         protected abstract <T extends JCTree> T to(T t);
5520 
5521         /**
5522          * Store current token's ending position for a tree, the value of which
5523          * will be the greater of last error position and the ending position of
5524          * the previous token.
5525          * @param t The tree.
5526          */
5527         protected abstract <T extends JCTree> T toP(T t);
5528 
5529         /**
5530          * Set the error position during the parsing phases, the value of which
5531          * will be set only if it is greater than the last stored error position.
5532          * @param errPos The error position
5533          */
5534         public void setErrorEndPos(int errPos) {
5535             if (errPos > errorEndPos) {
5536                 errorEndPos = errPos;
5537             }
5538         }
5539 
5540         public void setParser(JavacParser parser) {
5541             this.parser = parser;
5542         }
5543     }
5544 }