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