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