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