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