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