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