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