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