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