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