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