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