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