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