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