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