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