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