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