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