1 /* 2 * Copyright (c) 1999, 2011, 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.tools.javac.code.*; 31 import com.sun.tools.javac.parser.Tokens.*; 32 import com.sun.tools.javac.tree.*; 33 import com.sun.tools.javac.tree.JCTree.*; 34 import com.sun.tools.javac.util.*; 35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 36 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 37 import com.sun.tools.javac.util.List; 38 39 import static com.sun.tools.javac.util.ListBuffer.lb; 40 import static com.sun.tools.javac.parser.Tokens.TokenKind.*; 41 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT; 42 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ; 43 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT; 44 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT; 45 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE; 46 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH; 47 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT; 48 import static com.sun.tools.javac.tree.JCTree.Tag.*; 49 50 /** The parser maps a token sequence into an abstract syntax 51 * tree. It operates by recursive descent, with code derived 52 * systematically from an LL(1) grammar. For efficiency reasons, an 53 * operator precedence scheme is used for parsing binary operation 54 * expressions. 55 * 56 * <p><b>This is NOT part of any supported API. 57 * If you write code that depends on this, you do so at your own risk. 58 * This code and its internal interfaces are subject to change or 59 * deletion without notice.</b> 60 */ 61 public class JavacParser implements Parser { 62 63 /** The number of precedence levels of infix operators. 64 */ 65 private static final int infixPrecedenceLevels = 10; 66 67 /** The scanner used for lexical analysis. 68 */ 69 protected Lexer S; 70 71 /** The factory to be used for abstract syntax tree construction. 72 */ 73 protected TreeMaker F; 74 75 /** The log to be used for error diagnostics. 76 */ 77 private Log log; 78 79 /** The Source language setting. */ 80 private Source source; 81 82 /** The name table. */ 83 private Names names; 84 85 /** Construct a parser from a given scanner, tree factory and log. 86 */ 87 protected JavacParser(ParserFactory fac, 88 Lexer S, 89 boolean keepDocComments, 90 boolean keepLineMap) { 91 this.S = S; 92 nextToken(); // prime the pump 93 this.F = fac.F; 94 this.log = fac.log; 95 this.names = fac.names; 96 this.source = fac.source; 97 this.allowGenerics = source.allowGenerics(); 98 this.allowVarargs = source.allowVarargs(); 99 this.allowAsserts = source.allowAsserts(); 100 this.allowEnums = source.allowEnums(); 101 this.allowForeach = source.allowForeach(); 102 this.allowStaticImport = source.allowStaticImport(); 103 this.allowAnnotations = source.allowAnnotations(); 104 this.allowTWR = source.allowTryWithResources(); 105 this.allowDiamond = source.allowDiamond(); 106 this.allowMulticatch = source.allowMulticatch(); 107 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true); 108 this.keepDocComments = keepDocComments; 109 docComments = keepDocComments ? new HashMap<JCTree,String>() : null; 110 this.keepLineMap = keepLineMap; 111 this.errorTree = F.Erroneous(); 112 } 113 114 /** Switch: Should generics be recognized? 115 */ 116 boolean allowGenerics; 117 118 /** Switch: Should diamond operator be recognized? 119 */ 120 boolean allowDiamond; 121 122 /** Switch: Should multicatch clause be accepted? 123 */ 124 boolean allowMulticatch; 125 126 /** Switch: Should varargs be recognized? 127 */ 128 boolean allowVarargs; 129 130 /** Switch: should we recognize assert statements, or just give a warning? 131 */ 132 boolean allowAsserts; 133 134 /** Switch: should we recognize enums, or just give a warning? 135 */ 136 boolean allowEnums; 137 138 /** Switch: should we recognize foreach? 139 */ 140 boolean allowForeach; 141 142 /** Switch: should we recognize foreach? 143 */ 144 boolean allowStaticImport; 145 146 /** Switch: should we recognize annotations? 147 */ 148 boolean allowAnnotations; 149 150 /** Switch: should we recognize try-with-resources? 151 */ 152 boolean allowTWR; 153 154 /** Switch: should we fold strings? 155 */ 156 boolean allowStringFolding; 157 158 /** Switch: should we keep docComments? 159 */ 160 boolean keepDocComments; 161 162 /** Switch: should we keep line table? 163 */ 164 boolean keepLineMap; 165 166 /** When terms are parsed, the mode determines which is expected: 167 * mode = EXPR : an expression 168 * mode = TYPE : a type 169 * mode = NOPARAMS : no parameters allowed for type 170 * mode = TYPEARG : type argument 171 */ 172 static final int EXPR = 0x1; 173 static final int TYPE = 0x2; 174 static final int NOPARAMS = 0x4; 175 static final int TYPEARG = 0x8; 176 static final int DIAMOND = 0x10; 177 178 /** The current mode. 179 */ 180 private int mode = 0; 181 182 /** The mode of the term that was parsed last. 183 */ 184 private int lastmode = 0; 185 186 /* ---------- token management -------------- */ 187 188 protected Token token; 189 190 protected void nextToken() { 191 S.nextToken(); 192 token = S.token(); 193 } 194 195 /* ---------- error recovery -------------- */ 196 197 private JCErroneous errorTree; 198 199 /** Skip forward until a suitable stop token is found. 200 */ 201 private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { 202 while (true) { 203 switch (token.kind) { 204 case SEMI: 205 nextToken(); 206 return; 207 case PUBLIC: 208 case FINAL: 209 case ABSTRACT: 210 case MONKEYS_AT: 211 case EOF: 212 case CLASS: 213 case INTERFACE: 214 case ENUM: 215 return; 216 case IMPORT: 217 if (stopAtImport) 218 return; 219 break; 220 case LBRACE: 221 case RBRACE: 222 case PRIVATE: 223 case PROTECTED: 224 case STATIC: 225 case TRANSIENT: 226 case NATIVE: 227 case VOLATILE: 228 case SYNCHRONIZED: 229 case STRICTFP: 230 case LT: 231 case BYTE: 232 case SHORT: 233 case CHAR: 234 case INT: 235 case LONG: 236 case FLOAT: 237 case DOUBLE: 238 case BOOLEAN: 239 case VOID: 240 if (stopAtMemberDecl) 241 return; 242 break; 243 case IDENTIFIER: 244 if (stopAtIdentifier) 245 return; 246 break; 247 case CASE: 248 case DEFAULT: 249 case IF: 250 case FOR: 251 case WHILE: 252 case DO: 253 case TRY: 254 case SWITCH: 255 case RETURN: 256 case THROW: 257 case BREAK: 258 case CONTINUE: 259 case ELSE: 260 case FINALLY: 261 case CATCH: 262 if (stopAtStatement) 263 return; 264 break; 265 } 266 nextToken(); 267 } 268 } 269 270 private JCErroneous syntaxError(int pos, String key, TokenKind... args) { 271 return syntaxError(pos, List.<JCTree>nil(), key, args); 272 } 273 274 private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) { 275 setErrorEndPos(pos); 276 JCErroneous err = F.at(pos).Erroneous(errs); 277 reportSyntaxError(err, key, (Object[])args); 278 if (errs != null) { 279 JCTree last = errs.last(); 280 if (last != null) 281 storeEnd(last, pos); 282 } 283 return toP(err); 284 } 285 286 private int errorPos = Position.NOPOS; 287 288 /** 289 * Report a syntax using the given the position parameter and arguments, 290 * unless one was already reported at the same position. 291 */ 292 private void reportSyntaxError(int pos, String key, Object... args) { 293 JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos); 294 reportSyntaxError(diag, key, args); 295 } 296 297 /** 298 * Report a syntax error using the given DiagnosticPosition object and 299 * arguments, unless one was already reported at the same position. 300 */ 301 private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) { 302 int pos = diagPos.getPreferredPosition(); 303 if (pos > S.errPos() || pos == Position.NOPOS) { 304 if (token.kind == EOF) { 305 error(diagPos, "premature.eof"); 306 } else { 307 error(diagPos, key, args); 308 } 309 } 310 S.errPos(pos); 311 if (token.pos == errorPos) 312 nextToken(); // guarantee progress 313 errorPos = token.pos; 314 } 315 316 317 /** Generate a syntax error at current position unless one was already 318 * reported at the same position. 319 */ 320 private JCErroneous syntaxError(String key) { 321 return syntaxError(token.pos, key); 322 } 323 324 /** Generate a syntax error at current position unless one was 325 * already reported at the same position. 326 */ 327 private JCErroneous syntaxError(String key, TokenKind arg) { 328 return syntaxError(token.pos, key, arg); 329 } 330 331 /** If next input token matches given token, skip it, otherwise report 332 * an error. 333 */ 334 public void accept(TokenKind tk) { 335 if (token.kind == tk) { 336 nextToken(); 337 } else { 338 setErrorEndPos(token.pos); 339 reportSyntaxError(S.prevToken().endPos, "expected", tk); 340 } 341 } 342 343 /** Report an illegal start of expression/type error at given position. 344 */ 345 JCExpression illegal(int pos) { 346 setErrorEndPos(pos); 347 if ((mode & EXPR) != 0) 348 return syntaxError(pos, "illegal.start.of.expr"); 349 else 350 return syntaxError(pos, "illegal.start.of.type"); 351 352 } 353 354 /** Report an illegal start of expression/type error at current position. 355 */ 356 JCExpression illegal() { 357 return illegal(token.pos); 358 } 359 360 /** Diagnose a modifier flag from the set, if any. */ 361 void checkNoMods(long mods) { 362 if (mods != 0) { 363 long lowestMod = mods & -mods; 364 error(token.pos, "mod.not.allowed.here", 365 Flags.asFlagSet(lowestMod)); 366 } 367 } 368 369 /* ---------- doc comments --------- */ 370 371 /** A hashtable to store all documentation comments 372 * indexed by the tree nodes they refer to. 373 * defined only if option flag keepDocComment is set. 374 */ 375 private final Map<JCTree, String> docComments; 376 377 /** Make an entry into docComments hashtable, 378 * provided flag keepDocComments is set and given doc comment is non-null. 379 * @param tree The tree to be used as index in the hashtable 380 * @param dc The doc comment to associate with the tree, or null. 381 */ 382 void attach(JCTree tree, String dc) { 383 if (keepDocComments && dc != null) { 384 // System.out.println("doc comment = ");System.out.println(dc);//DEBUG 385 docComments.put(tree, dc); 386 } 387 } 388 389 /* -------- source positions ------- */ 390 391 private int errorEndPos = -1; 392 393 private void setErrorEndPos(int errPos) { 394 if (errPos > errorEndPos) 395 errorEndPos = errPos; 396 } 397 398 protected int getErrorEndPos() { 399 return errorEndPos; 400 } 401 402 /** 403 * Store ending position for a tree. 404 * @param tree The tree. 405 * @param endpos The ending position to associate with the tree. 406 */ 407 protected void storeEnd(JCTree tree, int endpos) {} 408 409 /** 410 * Store ending position for a tree. The ending position should 411 * be the ending position of the current token. 412 * @param t The tree. 413 */ 414 protected <T extends JCTree> T to(T t) { return t; } 415 416 /** 417 * Store ending position for a tree. The ending position should 418 * be greater of the ending position of the previous token and errorEndPos. 419 * @param t The tree. 420 */ 421 protected <T extends JCTree> T toP(T t) { return t; } 422 423 /** Get the start position for a tree node. The start position is 424 * defined to be the position of the first character of the first 425 * token of the node's source text. 426 * @param tree The tree node 427 */ 428 public int getStartPos(JCTree tree) { 429 return TreeInfo.getStartPos(tree); 430 } 431 432 /** 433 * Get the end position for a tree node. The end position is 434 * defined to be the position of the last character of the last 435 * token of the node's source text. Returns Position.NOPOS if end 436 * positions are not generated or the position is otherwise not 437 * found. 438 * @param tree The tree node 439 */ 440 public int getEndPos(JCTree tree) { 441 return Position.NOPOS; 442 } 443 444 445 446 /* ---------- parsing -------------- */ 447 448 /** 449 * Ident = IDENTIFIER 450 */ 451 Name ident() { 452 if (token.kind == IDENTIFIER) { 453 Name name = token.name(); 454 nextToken(); 455 return name; 456 } else if (token.kind == ASSERT) { 457 if (allowAsserts) { 458 error(token.pos, "assert.as.identifier"); 459 nextToken(); 460 return names.error; 461 } else { 462 warning(token.pos, "assert.as.identifier"); 463 Name name = token.name(); 464 nextToken(); 465 return name; 466 } 467 } else if (token.kind == ENUM) { 468 if (allowEnums) { 469 error(token.pos, "enum.as.identifier"); 470 nextToken(); 471 return names.error; 472 } else { 473 warning(token.pos, "enum.as.identifier"); 474 Name name = token.name(); 475 nextToken(); 476 return name; 477 } 478 } else { 479 accept(IDENTIFIER); 480 return names.error; 481 } 482 } 483 484 /** 485 * Qualident = Ident { DOT Ident } 486 */ 487 public JCExpression qualident() { 488 JCExpression t = toP(F.at(token.pos).Ident(ident())); 489 while (token.kind == DOT) { 490 int pos = token.pos; 491 nextToken(); 492 t = toP(F.at(pos).Select(t, ident())); 493 } 494 return t; 495 } 496 497 JCExpression literal(Name prefix) { 498 return literal(prefix, token.pos); 499 } 500 501 /** 502 * Literal = 503 * INTLITERAL 504 * | LONGLITERAL 505 * | FLOATLITERAL 506 * | DOUBLELITERAL 507 * | CHARLITERAL 508 * | STRINGLITERAL 509 * | TRUE 510 * | FALSE 511 * | NULL 512 */ 513 JCExpression literal(Name prefix, int pos) { 514 JCExpression t = errorTree; 515 switch (token.kind) { 516 case INTLITERAL: 517 try { 518 t = F.at(pos).Literal( 519 TypeTags.INT, 520 Convert.string2int(strval(prefix), token.radix())); 521 } catch (NumberFormatException ex) { 522 error(token.pos, "int.number.too.large", strval(prefix)); 523 } 524 break; 525 case LONGLITERAL: 526 try { 527 t = F.at(pos).Literal( 528 TypeTags.LONG, 529 new Long(Convert.string2long(strval(prefix), token.radix()))); 530 } catch (NumberFormatException ex) { 531 error(token.pos, "int.number.too.large", strval(prefix)); 532 } 533 break; 534 case FLOATLITERAL: { 535 String proper = token.radix() == 16 ? 536 ("0x"+ token.stringVal()) : 537 token.stringVal(); 538 Float n; 539 try { 540 n = Float.valueOf(proper); 541 } catch (NumberFormatException ex) { 542 // error already reported in scanner 543 n = Float.NaN; 544 } 545 if (n.floatValue() == 0.0f && !isZero(proper)) 546 error(token.pos, "fp.number.too.small"); 547 else if (n.floatValue() == Float.POSITIVE_INFINITY) 548 error(token.pos, "fp.number.too.large"); 549 else 550 t = F.at(pos).Literal(TypeTags.FLOAT, n); 551 break; 552 } 553 case DOUBLELITERAL: { 554 String proper = token.radix() == 16 ? 555 ("0x"+ token.stringVal()) : 556 token.stringVal(); 557 Double n; 558 try { 559 n = Double.valueOf(proper); 560 } catch (NumberFormatException ex) { 561 // error already reported in scanner 562 n = Double.NaN; 563 } 564 if (n.doubleValue() == 0.0d && !isZero(proper)) 565 error(token.pos, "fp.number.too.small"); 566 else if (n.doubleValue() == Double.POSITIVE_INFINITY) 567 error(token.pos, "fp.number.too.large"); 568 else 569 t = F.at(pos).Literal(TypeTags.DOUBLE, n); 570 break; 571 } 572 case CHARLITERAL: 573 t = F.at(pos).Literal( 574 TypeTags.CHAR, 575 token.stringVal().charAt(0) + 0); 576 break; 577 case STRINGLITERAL: 578 t = F.at(pos).Literal( 579 TypeTags.CLASS, 580 token.stringVal()); 581 break; 582 case TRUE: case FALSE: 583 t = F.at(pos).Literal( 584 TypeTags.BOOLEAN, 585 (token.kind == TRUE ? 1 : 0)); 586 break; 587 case NULL: 588 t = F.at(pos).Literal( 589 TypeTags.BOT, 590 null); 591 break; 592 default: 593 Assert.error(); 594 } 595 if (t == errorTree) 596 t = F.at(pos).Erroneous(); 597 storeEnd(t, token.endPos); 598 nextToken(); 599 return t; 600 } 601 //where 602 boolean isZero(String s) { 603 char[] cs = s.toCharArray(); 604 int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10); 605 int i = ((base==16) ? 2 : 0); 606 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++; 607 return !(i < cs.length && (Character.digit(cs[i], base) > 0)); 608 } 609 610 String strval(Name prefix) { 611 String s = token.stringVal(); 612 return prefix.isEmpty() ? s : prefix + s; 613 } 614 615 /** terms can be either expressions or types. 616 */ 617 public JCExpression parseExpression() { 618 return term(EXPR); 619 } 620 621 public JCExpression parseType() { 622 return term(TYPE); 623 } 624 625 JCExpression term(int newmode) { 626 int prevmode = mode; 627 mode = newmode; 628 JCExpression t = term(); 629 lastmode = mode; 630 mode = prevmode; 631 return t; 632 } 633 634 /** 635 * Expression = Expression1 [ExpressionRest] 636 * ExpressionRest = [AssignmentOperator Expression1] 637 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | 638 * "&=" | "|=" | "^=" | 639 * "%=" | "<<=" | ">>=" | ">>>=" 640 * Type = Type1 641 * TypeNoParams = TypeNoParams1 642 * StatementExpression = Expression 643 * ConstantExpression = Expression 644 */ 645 JCExpression term() { 646 JCExpression t = term1(); 647 if ((mode & EXPR) != 0 && 648 token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0) 649 return termRest(t); 650 else 651 return t; 652 } 653 654 JCExpression termRest(JCExpression t) { 655 switch (token.kind) { 656 case EQ: { 657 int pos = token.pos; 658 nextToken(); 659 mode = EXPR; 660 JCExpression t1 = term(); 661 return toP(F.at(pos).Assign(t, t1)); 662 } 663 case PLUSEQ: 664 case SUBEQ: 665 case STAREQ: 666 case SLASHEQ: 667 case PERCENTEQ: 668 case AMPEQ: 669 case BAREQ: 670 case CARETEQ: 671 case LTLTEQ: 672 case GTGTEQ: 673 case GTGTGTEQ: 674 int pos = token.pos; 675 TokenKind tk = token.kind; 676 nextToken(); 677 mode = EXPR; 678 JCExpression t1 = term(); 679 return F.at(pos).Assignop(optag(tk), t, t1); 680 default: 681 return t; 682 } 683 } 684 685 /** Expression1 = Expression2 [Expression1Rest] 686 * Type1 = Type2 687 * TypeNoParams1 = TypeNoParams2 688 */ 689 JCExpression term1() { 690 JCExpression t = term2(); 691 if ((mode & EXPR) != 0 && token.kind == QUES) { 692 mode = EXPR; 693 return term1Rest(t); 694 } else { 695 return t; 696 } 697 } 698 699 /** Expression1Rest = ["?" Expression ":" Expression1] 700 */ 701 JCExpression term1Rest(JCExpression t) { 702 if (token.kind == QUES) { 703 int pos = token.pos; 704 nextToken(); 705 JCExpression t1 = term(); 706 accept(COLON); 707 JCExpression t2 = term1(); 708 return F.at(pos).Conditional(t, t1, t2); 709 } else { 710 return t; 711 } 712 } 713 714 /** Expression2 = Expression3 [Expression2Rest] 715 * Type2 = Type3 716 * TypeNoParams2 = TypeNoParams3 717 */ 718 JCExpression term2() { 719 JCExpression t = term3(); 720 if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) { 721 mode = EXPR; 722 return term2Rest(t, TreeInfo.orPrec); 723 } else { 724 return t; 725 } 726 } 727 728 /* Expression2Rest = {infixop Expression3} 729 * | Expression3 instanceof Type 730 * infixop = "||" 731 * | "&&" 732 * | "|" 733 * | "^" 734 * | "&" 735 * | "==" | "!=" 736 * | "<" | ">" | "<=" | ">=" 737 * | "<<" | ">>" | ">>>" 738 * | "+" | "-" 739 * | "*" | "/" | "%" 740 */ 741 JCExpression term2Rest(JCExpression t, int minprec) { 742 List<JCExpression[]> savedOd = odStackSupply.elems; 743 JCExpression[] odStack = newOdStack(); 744 List<Token[]> savedOp = opStackSupply.elems; 745 Token[] opStack = newOpStack(); 746 747 // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; 748 int top = 0; 749 odStack[0] = t; 750 int startPos = token.pos; 751 Token topOp = Tokens.DUMMY; 752 while (prec(token.kind) >= minprec) { 753 opStack[top] = topOp; 754 top++; 755 topOp = token; 756 nextToken(); 757 odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3(); 758 while (top > 0 && prec(topOp.kind) >= prec(token.kind)) { 759 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1], 760 odStack[top]); 761 top--; 762 topOp = opStack[top]; 763 } 764 } 765 Assert.check(top == 0); 766 t = odStack[0]; 767 768 if (t.hasTag(JCTree.Tag.PLUS)) { 769 StringBuffer buf = foldStrings(t); 770 if (buf != null) { 771 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString())); 772 } 773 } 774 775 odStackSupply.elems = savedOd; // optimization 776 opStackSupply.elems = savedOp; // optimization 777 return t; 778 } 779 //where 780 /** Construct a binary or type test node. 781 */ 782 private JCExpression makeOp(int pos, 783 TokenKind topOp, 784 JCExpression od1, 785 JCExpression od2) 786 { 787 if (topOp == INSTANCEOF) { 788 return F.at(pos).TypeTest(od1, od2); 789 } else { 790 return F.at(pos).Binary(optag(topOp), od1, od2); 791 } 792 } 793 /** If tree is a concatenation of string literals, replace it 794 * by a single literal representing the concatenated string. 795 */ 796 protected StringBuffer foldStrings(JCTree tree) { 797 if (!allowStringFolding) 798 return null; 799 List<String> buf = List.nil(); 800 while (true) { 801 if (tree.hasTag(LITERAL)) { 802 JCLiteral lit = (JCLiteral) tree; 803 if (lit.typetag == TypeTags.CLASS) { 804 StringBuffer sbuf = 805 new StringBuffer((String)lit.value); 806 while (buf.nonEmpty()) { 807 sbuf.append(buf.head); 808 buf = buf.tail; 809 } 810 return sbuf; 811 } 812 } else if (tree.hasTag(JCTree.Tag.PLUS)) { 813 JCBinary op = (JCBinary)tree; 814 if (op.rhs.hasTag(LITERAL)) { 815 JCLiteral lit = (JCLiteral) op.rhs; 816 if (lit.typetag == TypeTags.CLASS) { 817 buf = buf.prepend((String) lit.value); 818 tree = op.lhs; 819 continue; 820 } 821 } 822 } 823 return null; 824 } 825 } 826 827 /** optimization: To save allocating a new operand/operator stack 828 * for every binary operation, we use supplys. 829 */ 830 ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>(); 831 ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>(); 832 833 private JCExpression[] newOdStack() { 834 if (odStackSupply.elems == odStackSupply.last) 835 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]); 836 JCExpression[] odStack = odStackSupply.elems.head; 837 odStackSupply.elems = odStackSupply.elems.tail; 838 return odStack; 839 } 840 841 private Token[] newOpStack() { 842 if (opStackSupply.elems == opStackSupply.last) 843 opStackSupply.append(new Token[infixPrecedenceLevels + 1]); 844 Token[] opStack = opStackSupply.elems.head; 845 opStackSupply.elems = opStackSupply.elems.tail; 846 return opStack; 847 } 848 849 /** Expression3 = PrefixOp Expression3 850 * | "(" Expr | TypeNoParams ")" Expression3 851 * | Primary {Selector} {PostfixOp} 852 * Primary = "(" Expression ")" 853 * | Literal 854 * | [TypeArguments] THIS [Arguments] 855 * | [TypeArguments] SUPER SuperSuffix 856 * | NEW [TypeArguments] Creator 857 * | Ident { "." Ident } 858 * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) 859 * | Arguments 860 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) 861 * ] 862 * | BasicType BracketsOpt "." CLASS 863 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-" 864 * PostfixOp = "++" | "--" 865 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt 866 * | BasicType 867 * TypeNoParams3 = Ident { "." Ident } BracketsOpt 868 * Selector = "." [TypeArguments] Ident [Arguments] 869 * | "." THIS 870 * | "." [TypeArguments] SUPER SuperSuffix 871 * | "." NEW [TypeArguments] InnerCreator 872 * | "[" Expression "]" 873 * TypeSelector = "." Ident [TypeArguments] 874 * SuperSuffix = Arguments | "." Ident [Arguments] 875 */ 876 protected JCExpression term3() { 877 int pos = token.pos; 878 JCExpression t; 879 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR); 880 switch (token.kind) { 881 case QUES: 882 if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) { 883 mode = TYPE; 884 return typeArgument(); 885 } else 886 return illegal(); 887 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB: 888 if (typeArgs == null && (mode & EXPR) != 0) { 889 TokenKind tk = token.kind; 890 nextToken(); 891 mode = EXPR; 892 if (tk == SUB && 893 (token.kind == INTLITERAL || token.kind == LONGLITERAL) && 894 token.radix() == 10) { 895 mode = EXPR; 896 t = literal(names.hyphen, pos); 897 } else { 898 t = term3(); 899 return F.at(pos).Unary(unoptag(tk), t); 900 } 901 } else return illegal(); 902 break; 903 case LPAREN: 904 if (typeArgs == null && (mode & EXPR) != 0) { 905 nextToken(); 906 mode = EXPR | TYPE | NOPARAMS; 907 t = term3(); 908 if ((mode & TYPE) != 0 && token.kind == LT) { 909 // Could be a cast to a parameterized type 910 JCTree.Tag op = JCTree.Tag.LT; 911 int pos1 = token.pos; 912 nextToken(); 913 mode &= (EXPR | TYPE); 914 mode |= TYPEARG; 915 JCExpression t1 = term3(); 916 if ((mode & TYPE) != 0 && 917 (token.kind == COMMA || token.kind == GT)) { 918 mode = TYPE; 919 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); 920 args.append(t1); 921 while (token.kind == COMMA) { 922 nextToken(); 923 args.append(typeArgument()); 924 } 925 accept(GT); 926 t = toP(F.at(pos1).TypeApply(t, args.toList())); 927 checkGenerics(); 928 while (token.kind == DOT) { 929 nextToken(); 930 mode = TYPE; 931 t = toP(F.at(token.pos).Select(t, ident())); 932 t = typeArgumentsOpt(t); 933 } 934 t = bracketsOpt(toP(t)); 935 } else if ((mode & EXPR) != 0) { 936 mode = EXPR; 937 JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); 938 t = F.at(pos1).Binary(op, t, e); 939 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); 940 } else { 941 accept(GT); 942 } 943 } 944 else { 945 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); 946 } 947 accept(RPAREN); 948 lastmode = mode; 949 mode = EXPR; 950 if ((lastmode & EXPR) == 0) { 951 JCExpression t1 = term3(); 952 return F.at(pos).TypeCast(t, t1); 953 } else if ((lastmode & TYPE) != 0) { 954 switch (token.kind) { 955 /*case PLUSPLUS: case SUBSUB: */ 956 case BANG: case TILDE: 957 case LPAREN: case THIS: case SUPER: 958 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: 959 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: 960 case TRUE: case FALSE: case NULL: 961 case NEW: case IDENTIFIER: case ASSERT: case ENUM: 962 case BYTE: case SHORT: case CHAR: case INT: 963 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: 964 JCExpression t1 = term3(); 965 return F.at(pos).TypeCast(t, t1); 966 } 967 } 968 } else return illegal(); 969 t = toP(F.at(pos).Parens(t)); 970 break; 971 case THIS: 972 if ((mode & EXPR) != 0) { 973 mode = EXPR; 974 t = to(F.at(pos).Ident(names._this)); 975 nextToken(); 976 if (typeArgs == null) 977 t = argumentsOpt(null, t); 978 else 979 t = arguments(typeArgs, t); 980 typeArgs = null; 981 } else return illegal(); 982 break; 983 case SUPER: 984 if ((mode & EXPR) != 0) { 985 mode = EXPR; 986 t = to(F.at(pos).Ident(names._super)); 987 t = superSuffix(typeArgs, t); 988 typeArgs = null; 989 } else return illegal(); 990 break; 991 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL: 992 case CHARLITERAL: case STRINGLITERAL: 993 case TRUE: case FALSE: case NULL: 994 if (typeArgs == null && (mode & EXPR) != 0) { 995 mode = EXPR; 996 t = literal(names.empty); 997 } else return illegal(); 998 break; 999 case NEW: 1000 if (typeArgs != null) return illegal(); 1001 if ((mode & EXPR) != 0) { 1002 mode = EXPR; 1003 nextToken(); 1004 if (token.kind == LT) typeArgs = typeArguments(false); 1005 t = creator(pos, typeArgs); 1006 typeArgs = null; 1007 } else return illegal(); 1008 break; 1009 case IDENTIFIER: case ASSERT: case ENUM: 1010 if (typeArgs != null) return illegal(); 1011 t = toP(F.at(token.pos).Ident(ident())); 1012 loop: while (true) { 1013 pos = token.pos; 1014 switch (token.kind) { 1015 case LBRACKET: 1016 nextToken(); 1017 if (token.kind == RBRACKET) { 1018 nextToken(); 1019 t = bracketsOpt(t); 1020 t = toP(F.at(pos).TypeArray(t)); 1021 t = bracketsSuffix(t); 1022 } else { 1023 if ((mode & EXPR) != 0) { 1024 mode = EXPR; 1025 JCExpression t1 = term(); 1026 t = to(F.at(pos).Indexed(t, t1)); 1027 } 1028 accept(RBRACKET); 1029 } 1030 break loop; 1031 case LPAREN: 1032 if ((mode & EXPR) != 0) { 1033 mode = EXPR; 1034 t = arguments(typeArgs, t); 1035 typeArgs = null; 1036 } 1037 break loop; 1038 case DOT: 1039 nextToken(); 1040 int oldmode = mode; 1041 mode &= ~NOPARAMS; 1042 typeArgs = typeArgumentsOpt(EXPR); 1043 mode = oldmode; 1044 if ((mode & EXPR) != 0) { 1045 switch (token.kind) { 1046 case CLASS: 1047 if (typeArgs != null) return illegal(); 1048 mode = EXPR; 1049 t = to(F.at(pos).Select(t, names._class)); 1050 nextToken(); 1051 break loop; 1052 case THIS: 1053 if (typeArgs != null) return illegal(); 1054 mode = EXPR; 1055 t = to(F.at(pos).Select(t, names._this)); 1056 nextToken(); 1057 break loop; 1058 case SUPER: 1059 mode = EXPR; 1060 t = to(F.at(pos).Select(t, names._super)); 1061 t = superSuffix(typeArgs, t); 1062 typeArgs = null; 1063 break loop; 1064 case NEW: 1065 if (typeArgs != null) return illegal(); 1066 mode = EXPR; 1067 int pos1 = token.pos; 1068 nextToken(); 1069 if (token.kind == LT) typeArgs = typeArguments(false); 1070 t = innerCreator(pos1, typeArgs, t); 1071 typeArgs = null; 1072 break loop; 1073 } 1074 } 1075 // typeArgs saved for next loop iteration. 1076 t = toP(F.at(pos).Select(t, ident())); 1077 break; 1078 default: 1079 break loop; 1080 } 1081 } 1082 if (typeArgs != null) illegal(); 1083 t = typeArgumentsOpt(t); 1084 break; 1085 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 1086 case DOUBLE: case BOOLEAN: 1087 if (typeArgs != null) illegal(); 1088 t = bracketsSuffix(bracketsOpt(basicType())); 1089 break; 1090 case VOID: 1091 if (typeArgs != null) illegal(); 1092 if ((mode & EXPR) != 0) { 1093 nextToken(); 1094 if (token.kind == DOT) { 1095 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID)); 1096 t = bracketsSuffix(ti); 1097 } else { 1098 return illegal(pos); 1099 } 1100 } else { 1101 // Support the corner case of myMethodHandle.<void>invoke() by passing 1102 // a void type (like other primitive types) to the next phase. 1103 // The error will be reported in Attr.attribTypes or Attr.visitApply. 1104 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID)); 1105 nextToken(); 1106 return ti; 1107 //return illegal(); 1108 } 1109 break; 1110 default: 1111 return illegal(); 1112 } 1113 if (typeArgs != null) illegal(); 1114 while (true) { 1115 int pos1 = token.pos; 1116 if (token.kind == LBRACKET) { 1117 nextToken(); 1118 if ((mode & TYPE) != 0) { 1119 int oldmode = mode; 1120 mode = TYPE; 1121 if (token.kind == RBRACKET) { 1122 nextToken(); 1123 t = bracketsOpt(t); 1124 t = toP(F.at(pos1).TypeArray(t)); 1125 return t; 1126 } 1127 mode = oldmode; 1128 } 1129 if ((mode & EXPR) != 0) { 1130 mode = EXPR; 1131 JCExpression t1 = term(); 1132 t = to(F.at(pos1).Indexed(t, t1)); 1133 } 1134 accept(RBRACKET); 1135 } else if (token.kind == DOT) { 1136 nextToken(); 1137 typeArgs = typeArgumentsOpt(EXPR); 1138 if (token.kind == SUPER && (mode & EXPR) != 0) { 1139 mode = EXPR; 1140 t = to(F.at(pos1).Select(t, names._super)); 1141 nextToken(); 1142 t = arguments(typeArgs, t); 1143 typeArgs = null; 1144 } else if (token.kind == NEW && (mode & EXPR) != 0) { 1145 if (typeArgs != null) return illegal(); 1146 mode = EXPR; 1147 int pos2 = token.pos; 1148 nextToken(); 1149 if (token.kind == LT) typeArgs = typeArguments(false); 1150 t = innerCreator(pos2, typeArgs, t); 1151 typeArgs = null; 1152 } else { 1153 t = toP(F.at(pos1).Select(t, ident())); 1154 t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); 1155 typeArgs = null; 1156 } 1157 } else { 1158 break; 1159 } 1160 } 1161 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) { 1162 mode = EXPR; 1163 t = to(F.at(token.pos).Unary( 1164 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t)); 1165 nextToken(); 1166 } 1167 return toP(t); 1168 } 1169 1170 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments] 1171 */ 1172 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { 1173 nextToken(); 1174 if (token.kind == LPAREN || typeArgs != null) { 1175 t = arguments(typeArgs, t); 1176 } else { 1177 int pos = token.pos; 1178 accept(DOT); 1179 typeArgs = (token.kind == LT) ? typeArguments(false) : null; 1180 t = toP(F.at(pos).Select(t, ident())); 1181 t = argumentsOpt(typeArgs, t); 1182 } 1183 return t; 1184 } 1185 1186 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN 1187 */ 1188 JCPrimitiveTypeTree basicType() { 1189 JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind))); 1190 nextToken(); 1191 return t; 1192 } 1193 1194 /** ArgumentsOpt = [ Arguments ] 1195 */ 1196 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) { 1197 if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) { 1198 mode = EXPR; 1199 return arguments(typeArgs, t); 1200 } else { 1201 return t; 1202 } 1203 } 1204 1205 /** Arguments = "(" [Expression { COMMA Expression }] ")" 1206 */ 1207 List<JCExpression> arguments() { 1208 ListBuffer<JCExpression> args = lb(); 1209 if (token.kind == LPAREN) { 1210 nextToken(); 1211 if (token.kind != RPAREN) { 1212 args.append(parseExpression()); 1213 while (token.kind == COMMA) { 1214 nextToken(); 1215 args.append(parseExpression()); 1216 } 1217 } 1218 accept(RPAREN); 1219 } else { 1220 syntaxError(token.pos, "expected", LPAREN); 1221 } 1222 return args.toList(); 1223 } 1224 1225 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) { 1226 int pos = token.pos; 1227 List<JCExpression> args = arguments(); 1228 return toP(F.at(pos).Apply(typeArgs, t, args)); 1229 } 1230 1231 /** TypeArgumentsOpt = [ TypeArguments ] 1232 */ 1233 JCExpression typeArgumentsOpt(JCExpression t) { 1234 if (token.kind == LT && 1235 (mode & TYPE) != 0 && 1236 (mode & NOPARAMS) == 0) { 1237 mode = TYPE; 1238 checkGenerics(); 1239 return typeArguments(t, false); 1240 } else { 1241 return t; 1242 } 1243 } 1244 List<JCExpression> typeArgumentsOpt() { 1245 return typeArgumentsOpt(TYPE); 1246 } 1247 1248 List<JCExpression> typeArgumentsOpt(int useMode) { 1249 if (token.kind == LT) { 1250 checkGenerics(); 1251 if ((mode & useMode) == 0 || 1252 (mode & NOPARAMS) != 0) { 1253 illegal(); 1254 } 1255 mode = useMode; 1256 return typeArguments(false); 1257 } 1258 return null; 1259 } 1260 1261 /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">" 1262 */ 1263 List<JCExpression> typeArguments(boolean diamondAllowed) { 1264 if (token.kind == LT) { 1265 nextToken(); 1266 if (token.kind == GT && diamondAllowed) { 1267 checkDiamond(); 1268 mode |= DIAMOND; 1269 nextToken(); 1270 return List.nil(); 1271 } else { 1272 ListBuffer<JCExpression> args = ListBuffer.lb(); 1273 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 1274 while (token.kind == COMMA) { 1275 nextToken(); 1276 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 1277 } 1278 switch (token.kind) { 1279 1280 case GTGTGTEQ: case GTGTEQ: case GTEQ: 1281 case GTGTGT: case GTGT: 1282 token = S.split(); 1283 break; 1284 case GT: 1285 nextToken(); 1286 break; 1287 default: 1288 args.append(syntaxError(token.pos, "expected", GT)); 1289 break; 1290 } 1291 return args.toList(); 1292 } 1293 } else { 1294 return List.<JCExpression>of(syntaxError(token.pos, "expected", LT)); 1295 } 1296 } 1297 1298 /** TypeArgument = Type 1299 * | "?" 1300 * | "?" EXTENDS Type {"&" Type} 1301 * | "?" SUPER Type 1302 */ 1303 JCExpression typeArgument() { 1304 if (token.kind != QUES) return parseType(); 1305 int pos = token.pos; 1306 nextToken(); 1307 if (token.kind == EXTENDS) { 1308 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); 1309 nextToken(); 1310 JCExpression bound = parseType(); 1311 return F.at(pos).Wildcard(t, bound); 1312 } else if (token.kind == SUPER) { 1313 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); 1314 nextToken(); 1315 JCExpression bound = parseType(); 1316 return F.at(pos).Wildcard(t, bound); 1317 } else if (token.kind == IDENTIFIER) { 1318 //error recovery 1319 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 1320 JCExpression wc = toP(F.at(pos).Wildcard(t, null)); 1321 JCIdent id = toP(F.at(token.pos).Ident(ident())); 1322 JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id)); 1323 reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER); 1324 return err; 1325 } else { 1326 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); 1327 return toP(F.at(pos).Wildcard(t, null)); 1328 } 1329 } 1330 1331 JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) { 1332 int pos = token.pos; 1333 List<JCExpression> args = typeArguments(diamondAllowed); 1334 return toP(F.at(pos).TypeApply(t, args)); 1335 } 1336 1337 /** BracketsOpt = {"[" "]"} 1338 */ 1339 private JCExpression bracketsOpt(JCExpression t) { 1340 if (token.kind == LBRACKET) { 1341 int pos = token.pos; 1342 nextToken(); 1343 t = bracketsOptCont(t, pos); 1344 F.at(pos); 1345 } 1346 return t; 1347 } 1348 1349 private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) { 1350 accept(RBRACKET); 1351 t = bracketsOpt(t); 1352 return toP(F.at(pos).TypeArray(t)); 1353 } 1354 1355 /** BracketsSuffixExpr = "." CLASS 1356 * BracketsSuffixType = 1357 */ 1358 JCExpression bracketsSuffix(JCExpression t) { 1359 if ((mode & EXPR) != 0 && token.kind == DOT) { 1360 mode = EXPR; 1361 int pos = token.pos; 1362 nextToken(); 1363 accept(CLASS); 1364 if (token.pos == errorEndPos) { 1365 // error recovery 1366 Name name = null; 1367 if (token.kind == IDENTIFIER) { 1368 name = token.name(); 1369 nextToken(); 1370 } else { 1371 name = names.error; 1372 } 1373 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name)))); 1374 } else { 1375 t = toP(F.at(pos).Select(t, names._class)); 1376 } 1377 } else if ((mode & TYPE) != 0) { 1378 mode = TYPE; 1379 } else { 1380 syntaxError(token.pos, "dot.class.expected"); 1381 } 1382 return t; 1383 } 1384 1385 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) 1386 */ 1387 JCExpression creator(int newpos, List<JCExpression> typeArgs) { 1388 switch (token.kind) { 1389 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 1390 case DOUBLE: case BOOLEAN: 1391 if (typeArgs == null) 1392 return arrayCreatorRest(newpos, basicType()); 1393 break; 1394 default: 1395 } 1396 JCExpression t = qualident(); 1397 int oldmode = mode; 1398 mode = TYPE; 1399 boolean diamondFound = false; 1400 int lastTypeargsPos = -1; 1401 if (token.kind == LT) { 1402 checkGenerics(); 1403 lastTypeargsPos = token.pos; 1404 t = typeArguments(t, true); 1405 diamondFound = (mode & DIAMOND) != 0; 1406 } 1407 while (token.kind == DOT) { 1408 if (diamondFound) { 1409 //cannot select after a diamond 1410 illegal(); 1411 } 1412 int pos = token.pos; 1413 nextToken(); 1414 t = toP(F.at(pos).Select(t, ident())); 1415 if (token.kind == LT) { 1416 lastTypeargsPos = token.pos; 1417 checkGenerics(); 1418 t = typeArguments(t, true); 1419 diamondFound = (mode & DIAMOND) != 0; 1420 } 1421 } 1422 mode = oldmode; 1423 if (token.kind == LBRACKET) { 1424 JCExpression e = arrayCreatorRest(newpos, t); 1425 if (diamondFound) { 1426 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond"); 1427 return toP(F.at(newpos).Erroneous(List.of(e))); 1428 } 1429 else if (typeArgs != null) { 1430 int pos = newpos; 1431 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) { 1432 // note: this should always happen but we should 1433 // not rely on this as the parser is continuously 1434 // modified to improve error recovery. 1435 pos = typeArgs.head.pos; 1436 } 1437 setErrorEndPos(S.prevToken().endPos); 1438 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e)); 1439 reportSyntaxError(err, "cannot.create.array.with.type.arguments"); 1440 return toP(err); 1441 } 1442 return e; 1443 } else if (token.kind == LPAREN) { 1444 return classCreatorRest(newpos, null, typeArgs, t); 1445 } else { 1446 setErrorEndPos(token.pos); 1447 reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET); 1448 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null)); 1449 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t))); 1450 } 1451 } 1452 1453 /** InnerCreator = Ident [TypeArguments] ClassCreatorRest 1454 */ 1455 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) { 1456 JCExpression t = toP(F.at(token.pos).Ident(ident())); 1457 if (token.kind == LT) { 1458 int oldmode = mode; 1459 checkGenerics(); 1460 t = typeArguments(t, true); 1461 mode = oldmode; 1462 } 1463 return classCreatorRest(newpos, encl, typeArgs, t); 1464 } 1465 1466 /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer 1467 * | Expression "]" {"[" Expression "]"} BracketsOpt ) 1468 */ 1469 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { 1470 accept(LBRACKET); 1471 if (token.kind == RBRACKET) { 1472 accept(RBRACKET); 1473 elemtype = bracketsOpt(elemtype); 1474 if (token.kind == LBRACE) { 1475 return arrayInitializer(newpos, elemtype); 1476 } else { 1477 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null)); 1478 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing"); 1479 } 1480 } else { 1481 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>(); 1482 dims.append(parseExpression()); 1483 accept(RBRACKET); 1484 while (token.kind == LBRACKET) { 1485 int pos = token.pos; 1486 nextToken(); 1487 if (token.kind == RBRACKET) { 1488 elemtype = bracketsOptCont(elemtype, pos); 1489 } else { 1490 dims.append(parseExpression()); 1491 accept(RBRACKET); 1492 } 1493 } 1494 return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); 1495 } 1496 } 1497 1498 /** ClassCreatorRest = Arguments [ClassBody] 1499 */ 1500 JCNewClass classCreatorRest(int newpos, 1501 JCExpression encl, 1502 List<JCExpression> typeArgs, 1503 JCExpression t) 1504 { 1505 List<JCExpression> args = arguments(); 1506 JCClassDecl body = null; 1507 if (token.kind == LBRACE) { 1508 int pos = token.pos; 1509 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 1510 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 1511 body = toP(F.at(pos).AnonymousClassDef(mods, defs)); 1512 } 1513 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); 1514 } 1515 1516 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" 1517 */ 1518 JCExpression arrayInitializer(int newpos, JCExpression t) { 1519 accept(LBRACE); 1520 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>(); 1521 if (token.kind == COMMA) { 1522 nextToken(); 1523 } else if (token.kind != RBRACE) { 1524 elems.append(variableInitializer()); 1525 while (token.kind == COMMA) { 1526 nextToken(); 1527 if (token.kind == RBRACE) break; 1528 elems.append(variableInitializer()); 1529 } 1530 } 1531 accept(RBRACE); 1532 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList())); 1533 } 1534 1535 /** VariableInitializer = ArrayInitializer | Expression 1536 */ 1537 public JCExpression variableInitializer() { 1538 return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression(); 1539 } 1540 1541 /** ParExpression = "(" Expression ")" 1542 */ 1543 JCExpression parExpression() { 1544 accept(LPAREN); 1545 JCExpression t = parseExpression(); 1546 accept(RPAREN); 1547 return t; 1548 } 1549 1550 /** Block = "{" BlockStatements "}" 1551 */ 1552 JCBlock block(int pos, long flags) { 1553 accept(LBRACE); 1554 List<JCStatement> stats = blockStatements(); 1555 JCBlock t = F.at(pos).Block(flags, stats); 1556 while (token.kind == CASE || token.kind == DEFAULT) { 1557 syntaxError("orphaned", token.kind); 1558 switchBlockStatementGroups(); 1559 } 1560 // the Block node has a field "endpos" for first char of last token, which is 1561 // usually but not necessarily the last char of the last token. 1562 t.endpos = token.pos; 1563 accept(RBRACE); 1564 return toP(t); 1565 } 1566 1567 public JCBlock block() { 1568 return block(token.pos, 0); 1569 } 1570 1571 /** BlockStatements = { BlockStatement } 1572 * BlockStatement = LocalVariableDeclarationStatement 1573 * | ClassOrInterfaceOrEnumDeclaration 1574 * | [Ident ":"] Statement 1575 * LocalVariableDeclarationStatement 1576 * = { FINAL | '@' Annotation } Type VariableDeclarators ";" 1577 */ 1578 @SuppressWarnings("fallthrough") 1579 List<JCStatement> blockStatements() { 1580 //todo: skip to anchor on error(?) 1581 int lastErrPos = -1; 1582 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); 1583 while (true) { 1584 int pos = token.pos; 1585 switch (token.kind) { 1586 case RBRACE: case CASE: case DEFAULT: case EOF: 1587 return stats.toList(); 1588 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: 1589 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: 1590 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: 1591 stats.append(parseStatement()); 1592 break; 1593 case MONKEYS_AT: 1594 case FINAL: { 1595 String dc = token.docComment; 1596 JCModifiers mods = modifiersOpt(); 1597 if (token.kind == INTERFACE || 1598 token.kind == CLASS || 1599 allowEnums && token.kind == ENUM) { 1600 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); 1601 } else { 1602 JCExpression t = parseType(); 1603 stats.appendList(variableDeclarators(mods, t, 1604 new ListBuffer<JCStatement>())); 1605 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 1606 storeEnd(stats.elems.last(), token.endPos); 1607 accept(SEMI); 1608 } 1609 break; 1610 } 1611 case ABSTRACT: case STRICTFP: { 1612 String dc = token.docComment; 1613 JCModifiers mods = modifiersOpt(); 1614 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); 1615 break; 1616 } 1617 case INTERFACE: 1618 case CLASS: 1619 String dc = token.docComment; 1620 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); 1621 break; 1622 case ENUM: 1623 case ASSERT: 1624 if (allowEnums && token.kind == ENUM) { 1625 error(token.pos, "local.enum"); 1626 dc = token.docComment; 1627 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); 1628 break; 1629 } else if (allowAsserts && token.kind == ASSERT) { 1630 stats.append(parseStatement()); 1631 break; 1632 } 1633 /* fall through to default */ 1634 default: 1635 Token prevToken = token; 1636 JCExpression t = term(EXPR | TYPE); 1637 if (token.kind == COLON && t.hasTag(IDENT)) { 1638 nextToken(); 1639 JCStatement stat = parseStatement(); 1640 stats.append(F.at(pos).Labelled(prevToken.name(), stat)); 1641 } else if ((lastmode & TYPE) != 0 && 1642 (token.kind == IDENTIFIER || 1643 token.kind == ASSERT || 1644 token.kind == ENUM)) { 1645 pos = token.pos; 1646 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 1647 F.at(pos); 1648 stats.appendList(variableDeclarators(mods, t, 1649 new ListBuffer<JCStatement>())); 1650 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 1651 storeEnd(stats.elems.last(), token.endPos); 1652 accept(SEMI); 1653 } else { 1654 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 1655 stats.append(to(F.at(pos).Exec(checkExprStat(t)))); 1656 accept(SEMI); 1657 } 1658 } 1659 1660 // error recovery 1661 if (token.pos == lastErrPos) 1662 return stats.toList(); 1663 if (token.pos <= errorEndPos) { 1664 skip(false, true, true, true); 1665 lastErrPos = token.pos; 1666 } 1667 } 1668 } 1669 1670 /** Statement = 1671 * Block 1672 * | IF ParExpression Statement [ELSE Statement] 1673 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement 1674 * | FOR "(" FormalParameter : Expression ")" Statement 1675 * | WHILE ParExpression Statement 1676 * | DO Statement WHILE ParExpression ";" 1677 * | TRY Block ( Catches | [Catches] FinallyPart ) 1678 * | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart] 1679 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" 1680 * | SYNCHRONIZED ParExpression Block 1681 * | RETURN [Expression] ";" 1682 * | THROW Expression ";" 1683 * | BREAK [Ident] ";" 1684 * | CONTINUE [Ident] ";" 1685 * | ASSERT Expression [ ":" Expression ] ";" 1686 * | ";" 1687 * | ExpressionStatement 1688 * | Ident ":" Statement 1689 */ 1690 @SuppressWarnings("fallthrough") 1691 public JCStatement parseStatement() { 1692 int pos = token.pos; 1693 switch (token.kind) { 1694 case LBRACE: 1695 return block(); 1696 case IF: { 1697 nextToken(); 1698 JCExpression cond = parExpression(); 1699 JCStatement thenpart = parseStatement(); 1700 JCStatement elsepart = null; 1701 if (token.kind == ELSE) { 1702 nextToken(); 1703 elsepart = parseStatement(); 1704 } 1705 return F.at(pos).If(cond, thenpart, elsepart); 1706 } 1707 case FOR: { 1708 nextToken(); 1709 accept(LPAREN); 1710 List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit(); 1711 if (inits.length() == 1 && 1712 inits.head.hasTag(VARDEF) && 1713 ((JCVariableDecl) inits.head).init == null && 1714 token.kind == COLON) { 1715 checkForeach(); 1716 JCVariableDecl var = (JCVariableDecl)inits.head; 1717 accept(COLON); 1718 JCExpression expr = parseExpression(); 1719 accept(RPAREN); 1720 JCStatement body = parseStatement(); 1721 return F.at(pos).ForeachLoop(var, expr, body); 1722 } else { 1723 accept(SEMI); 1724 JCExpression cond = token.kind == SEMI ? null : parseExpression(); 1725 accept(SEMI); 1726 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); 1727 accept(RPAREN); 1728 JCStatement body = parseStatement(); 1729 return F.at(pos).ForLoop(inits, cond, steps, body); 1730 } 1731 } 1732 case WHILE: { 1733 nextToken(); 1734 JCExpression cond = parExpression(); 1735 JCStatement body = parseStatement(); 1736 return F.at(pos).WhileLoop(cond, body); 1737 } 1738 case DO: { 1739 nextToken(); 1740 JCStatement body = parseStatement(); 1741 accept(WHILE); 1742 JCExpression cond = parExpression(); 1743 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond)); 1744 accept(SEMI); 1745 return t; 1746 } 1747 case TRY: { 1748 nextToken(); 1749 List<JCTree> resources = List.<JCTree>nil(); 1750 if (token.kind == LPAREN) { 1751 checkTryWithResources(); 1752 nextToken(); 1753 resources = resources(); 1754 accept(RPAREN); 1755 } 1756 JCBlock body = block(); 1757 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>(); 1758 JCBlock finalizer = null; 1759 if (token.kind == CATCH || token.kind == FINALLY) { 1760 while (token.kind == CATCH) catchers.append(catchClause()); 1761 if (token.kind == FINALLY) { 1762 nextToken(); 1763 finalizer = block(); 1764 } 1765 } else { 1766 if (allowTWR) { 1767 if (resources.isEmpty()) 1768 error(pos, "try.without.catch.finally.or.resource.decls"); 1769 } else 1770 error(pos, "try.without.catch.or.finally"); 1771 } 1772 return F.at(pos).Try(resources, body, catchers.toList(), finalizer); 1773 } 1774 case SWITCH: { 1775 nextToken(); 1776 JCExpression selector = parExpression(); 1777 accept(LBRACE); 1778 List<JCCase> cases = switchBlockStatementGroups(); 1779 JCSwitch t = to(F.at(pos).Switch(selector, cases)); 1780 accept(RBRACE); 1781 return t; 1782 } 1783 case SYNCHRONIZED: { 1784 nextToken(); 1785 JCExpression lock = parExpression(); 1786 JCBlock body = block(); 1787 return F.at(pos).Synchronized(lock, body); 1788 } 1789 case RETURN: { 1790 nextToken(); 1791 JCExpression result = token.kind == SEMI ? null : parseExpression(); 1792 JCReturn t = to(F.at(pos).Return(result)); 1793 accept(SEMI); 1794 return t; 1795 } 1796 case THROW: { 1797 nextToken(); 1798 JCExpression exc = parseExpression(); 1799 JCThrow t = to(F.at(pos).Throw(exc)); 1800 accept(SEMI); 1801 return t; 1802 } 1803 case BREAK: { 1804 nextToken(); 1805 Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; 1806 JCBreak t = to(F.at(pos).Break(label)); 1807 accept(SEMI); 1808 return t; 1809 } 1810 case CONTINUE: { 1811 nextToken(); 1812 Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; 1813 JCContinue t = to(F.at(pos).Continue(label)); 1814 accept(SEMI); 1815 return t; 1816 } 1817 case SEMI: 1818 nextToken(); 1819 return toP(F.at(pos).Skip()); 1820 case ELSE: 1821 return toP(F.Exec(syntaxError("else.without.if"))); 1822 case FINALLY: 1823 return toP(F.Exec(syntaxError("finally.without.try"))); 1824 case CATCH: 1825 return toP(F.Exec(syntaxError("catch.without.try"))); 1826 case ASSERT: { 1827 if (allowAsserts && token.kind == ASSERT) { 1828 nextToken(); 1829 JCExpression assertion = parseExpression(); 1830 JCExpression message = null; 1831 if (token.kind == COLON) { 1832 nextToken(); 1833 message = parseExpression(); 1834 } 1835 JCAssert t = to(F.at(pos).Assert(assertion, message)); 1836 accept(SEMI); 1837 return t; 1838 } 1839 /* else fall through to default case */ 1840 } 1841 case ENUM: 1842 default: 1843 Token prevToken = token; 1844 JCExpression expr = parseExpression(); 1845 if (token.kind == COLON && expr.hasTag(IDENT)) { 1846 nextToken(); 1847 JCStatement stat = parseStatement(); 1848 return F.at(pos).Labelled(prevToken.name(), stat); 1849 } else { 1850 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 1851 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr))); 1852 accept(SEMI); 1853 return stat; 1854 } 1855 } 1856 } 1857 1858 /** CatchClause = CATCH "(" FormalParameter ")" Block 1859 */ 1860 protected JCCatch catchClause() { 1861 int pos = token.pos; 1862 accept(CATCH); 1863 accept(LPAREN); 1864 JCModifiers mods = optFinal(Flags.PARAMETER); 1865 List<JCExpression> catchTypes = catchTypes(); 1866 JCExpression paramType = catchTypes.size() > 1 ? 1867 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) : 1868 catchTypes.head; 1869 JCVariableDecl formal = variableDeclaratorId(mods, paramType); 1870 accept(RPAREN); 1871 JCBlock body = block(); 1872 return F.at(pos).Catch(formal, body); 1873 } 1874 1875 List<JCExpression> catchTypes() { 1876 ListBuffer<JCExpression> catchTypes = ListBuffer.lb(); 1877 catchTypes.add(parseType()); 1878 while (token.kind == BAR) { 1879 checkMulticatch(); 1880 nextToken(); 1881 catchTypes.add(qualident()); 1882 } 1883 return catchTypes.toList(); 1884 } 1885 1886 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup } 1887 * SwitchBlockStatementGroup = SwitchLabel BlockStatements 1888 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" 1889 */ 1890 List<JCCase> switchBlockStatementGroups() { 1891 ListBuffer<JCCase> cases = new ListBuffer<JCCase>(); 1892 while (true) { 1893 int pos = token.pos; 1894 switch (token.kind) { 1895 case CASE: { 1896 nextToken(); 1897 JCExpression pat = parseExpression(); 1898 accept(COLON); 1899 List<JCStatement> stats = blockStatements(); 1900 JCCase c = F.at(pos).Case(pat, stats); 1901 if (stats.isEmpty()) 1902 storeEnd(c, S.prevToken().endPos); 1903 cases.append(c); 1904 break; 1905 } 1906 case DEFAULT: { 1907 nextToken(); 1908 accept(COLON); 1909 List<JCStatement> stats = blockStatements(); 1910 JCCase c = F.at(pos).Case(null, stats); 1911 if (stats.isEmpty()) 1912 storeEnd(c, S.prevToken().endPos); 1913 cases.append(c); 1914 break; 1915 } 1916 case RBRACE: case EOF: 1917 return cases.toList(); 1918 default: 1919 nextToken(); // to ensure progress 1920 syntaxError(pos, "expected3", 1921 CASE, DEFAULT, RBRACE); 1922 } 1923 } 1924 } 1925 1926 /** MoreStatementExpressions = { COMMA StatementExpression } 1927 */ 1928 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos, 1929 JCExpression first, 1930 T stats) { 1931 // This Exec is a "StatementExpression"; it subsumes no terminating token 1932 stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); 1933 while (token.kind == COMMA) { 1934 nextToken(); 1935 pos = token.pos; 1936 JCExpression t = parseExpression(); 1937 // This Exec is a "StatementExpression"; it subsumes no terminating token 1938 stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); 1939 } 1940 return stats; 1941 } 1942 1943 /** ForInit = StatementExpression MoreStatementExpressions 1944 * | { FINAL | '@' Annotation } Type VariableDeclarators 1945 */ 1946 List<JCStatement> forInit() { 1947 ListBuffer<JCStatement> stats = lb(); 1948 int pos = token.pos; 1949 if (token.kind == FINAL || token.kind == MONKEYS_AT) { 1950 return variableDeclarators(optFinal(0), parseType(), stats).toList(); 1951 } else { 1952 JCExpression t = term(EXPR | TYPE); 1953 if ((lastmode & TYPE) != 0 && 1954 (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM)) 1955 return variableDeclarators(modifiersOpt(), t, stats).toList(); 1956 else 1957 return moreStatementExpressions(pos, t, stats).toList(); 1958 } 1959 } 1960 1961 /** ForUpdate = StatementExpression MoreStatementExpressions 1962 */ 1963 List<JCExpressionStatement> forUpdate() { 1964 return moreStatementExpressions(token.pos, 1965 parseExpression(), 1966 new ListBuffer<JCExpressionStatement>()).toList(); 1967 } 1968 1969 /** AnnotationsOpt = { '@' Annotation } 1970 */ 1971 List<JCAnnotation> annotationsOpt() { 1972 if (token.kind != MONKEYS_AT) return List.nil(); // optimization 1973 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>(); 1974 while (token.kind == MONKEYS_AT) { 1975 int pos = token.pos; 1976 nextToken(); 1977 buf.append(annotation(pos)); 1978 } 1979 return buf.toList(); 1980 } 1981 1982 /** ModifiersOpt = { Modifier } 1983 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL 1984 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" 1985 * | "@" Annotation 1986 */ 1987 JCModifiers modifiersOpt() { 1988 return modifiersOpt(null); 1989 } 1990 protected JCModifiers modifiersOpt(JCModifiers partial) { 1991 long flags; 1992 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>(); 1993 int pos; 1994 if (partial == null) { 1995 flags = 0; 1996 pos = token.pos; 1997 } else { 1998 flags = partial.flags; 1999 annotations.appendList(partial.annotations); 2000 pos = partial.pos; 2001 } 2002 if (token.deprecatedFlag) { 2003 flags |= Flags.DEPRECATED; 2004 } 2005 int lastPos = Position.NOPOS; 2006 loop: 2007 while (true) { 2008 long flag; 2009 switch (token.kind) { 2010 case PRIVATE : flag = Flags.PRIVATE; break; 2011 case PROTECTED : flag = Flags.PROTECTED; break; 2012 case PUBLIC : flag = Flags.PUBLIC; break; 2013 case STATIC : flag = Flags.STATIC; break; 2014 case TRANSIENT : flag = Flags.TRANSIENT; break; 2015 case FINAL : flag = Flags.FINAL; break; 2016 case ABSTRACT : flag = Flags.ABSTRACT; break; 2017 case NATIVE : flag = Flags.NATIVE; break; 2018 case VOLATILE : flag = Flags.VOLATILE; break; 2019 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; 2020 case STRICTFP : flag = Flags.STRICTFP; break; 2021 case MONKEYS_AT : flag = Flags.ANNOTATION; break; 2022 case ERROR : flag = 0; nextToken(); break; 2023 default: break loop; 2024 } 2025 if ((flags & flag) != 0) error(token.pos, "repeated.modifier"); 2026 lastPos = token.pos; 2027 nextToken(); 2028 if (flag == Flags.ANNOTATION) { 2029 checkAnnotations(); 2030 if (token.kind != INTERFACE) { 2031 JCAnnotation ann = annotation(lastPos); 2032 // if first modifier is an annotation, set pos to annotation's. 2033 if (flags == 0 && annotations.isEmpty()) 2034 pos = ann.pos; 2035 annotations.append(ann); 2036 lastPos = ann.pos; 2037 flag = 0; 2038 } 2039 } 2040 flags |= flag; 2041 } 2042 switch (token.kind) { 2043 case ENUM: flags |= Flags.ENUM; break; 2044 case INTERFACE: flags |= Flags.INTERFACE; break; 2045 default: break; 2046 } 2047 2048 /* A modifiers tree with no modifier tokens or annotations 2049 * has no text position. */ 2050 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty()) 2051 pos = Position.NOPOS; 2052 2053 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); 2054 if (pos != Position.NOPOS) 2055 storeEnd(mods, S.prevToken().endPos); 2056 return mods; 2057 } 2058 2059 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] 2060 * @param pos position of "@" token 2061 */ 2062 JCAnnotation annotation(int pos) { 2063 // accept(AT); // AT consumed by caller 2064 checkAnnotations(); 2065 JCTree ident = qualident(); 2066 List<JCExpression> fieldValues = annotationFieldValuesOpt(); 2067 JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); 2068 storeEnd(ann, S.prevToken().endPos); 2069 return ann; 2070 } 2071 2072 List<JCExpression> annotationFieldValuesOpt() { 2073 return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil(); 2074 } 2075 2076 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ 2077 List<JCExpression> annotationFieldValues() { 2078 accept(LPAREN); 2079 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 2080 if (token.kind != RPAREN) { 2081 buf.append(annotationFieldValue()); 2082 while (token.kind == COMMA) { 2083 nextToken(); 2084 buf.append(annotationFieldValue()); 2085 } 2086 } 2087 accept(RPAREN); 2088 return buf.toList(); 2089 } 2090 2091 /** AnnotationFieldValue = AnnotationValue 2092 * | Identifier "=" AnnotationValue 2093 */ 2094 JCExpression annotationFieldValue() { 2095 if (token.kind == IDENTIFIER) { 2096 mode = EXPR; 2097 JCExpression t1 = term1(); 2098 if (t1.hasTag(IDENT) && token.kind == EQ) { 2099 int pos = token.pos; 2100 accept(EQ); 2101 JCExpression v = annotationValue(); 2102 return toP(F.at(pos).Assign(t1, v)); 2103 } else { 2104 return t1; 2105 } 2106 } 2107 return annotationValue(); 2108 } 2109 2110 /* AnnotationValue = ConditionalExpression 2111 * | Annotation 2112 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}" 2113 */ 2114 JCExpression annotationValue() { 2115 int pos; 2116 switch (token.kind) { 2117 case MONKEYS_AT: 2118 pos = token.pos; 2119 nextToken(); 2120 return annotation(pos); 2121 case LBRACE: 2122 pos = token.pos; 2123 accept(LBRACE); 2124 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 2125 if (token.kind != RBRACE) { 2126 buf.append(annotationValue()); 2127 while (token.kind == COMMA) { 2128 nextToken(); 2129 if (token.kind == RBRACE) break; 2130 buf.append(annotationValue()); 2131 } 2132 } 2133 accept(RBRACE); 2134 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList())); 2135 default: 2136 mode = EXPR; 2137 return term1(); 2138 } 2139 } 2140 2141 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator } 2142 */ 2143 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods, 2144 JCExpression type, 2145 T vdefs) 2146 { 2147 return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs); 2148 } 2149 2150 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } 2151 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } 2152 * 2153 * @param reqInit Is an initializer always required? 2154 * @param dc The documentation comment for the variable declarations, or null. 2155 */ 2156 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos, 2157 JCModifiers mods, 2158 JCExpression type, 2159 Name name, 2160 boolean reqInit, 2161 String dc, 2162 T vdefs) 2163 { 2164 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); 2165 while (token.kind == COMMA) { 2166 // All but last of multiple declarators subsume a comma 2167 storeEnd((JCTree)vdefs.elems.last(), token.endPos); 2168 nextToken(); 2169 vdefs.append(variableDeclarator(mods, type, reqInit, dc)); 2170 } 2171 return vdefs; 2172 } 2173 2174 /** VariableDeclarator = Ident VariableDeclaratorRest 2175 * ConstantDeclarator = Ident ConstantDeclaratorRest 2176 */ 2177 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) { 2178 return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc); 2179 } 2180 2181 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] 2182 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer 2183 * 2184 * @param reqInit Is an initializer always required? 2185 * @param dc The documentation comment for the variable declarations, or null. 2186 */ 2187 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, 2188 boolean reqInit, String dc) { 2189 type = bracketsOpt(type); 2190 JCExpression init = null; 2191 if (token.kind == EQ) { 2192 nextToken(); 2193 init = variableInitializer(); 2194 } 2195 else if (reqInit) syntaxError(token.pos, "expected", EQ); 2196 JCVariableDecl result = 2197 toP(F.at(pos).VarDef(mods, name, type, init)); 2198 attach(result, dc); 2199 return result; 2200 } 2201 2202 /** VariableDeclaratorId = Ident BracketsOpt 2203 */ 2204 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { 2205 int pos = token.pos; 2206 Name name = ident(); 2207 if ((mods.flags & Flags.VARARGS) != 0 && 2208 token.kind == LBRACKET) { 2209 log.error(token.pos, "varargs.and.old.array.syntax"); 2210 } 2211 type = bracketsOpt(type); 2212 return toP(F.at(pos).VarDef(mods, name, type, null)); 2213 } 2214 2215 /** Resources = Resource { ";" Resources } 2216 */ 2217 List<JCTree> resources() { 2218 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2219 defs.append(resource()); 2220 while (token.kind == SEMI) { 2221 // All but last of multiple declarators must subsume a semicolon 2222 storeEnd(defs.elems.last(), token.endPos); 2223 int semiColonPos = token.pos; 2224 nextToken(); 2225 if (token.kind == RPAREN) { // Optional trailing semicolon 2226 // after last resource 2227 break; 2228 } 2229 defs.append(resource()); 2230 } 2231 return defs.toList(); 2232 } 2233 2234 /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression 2235 */ 2236 protected JCTree resource() { 2237 JCModifiers optFinal = optFinal(Flags.FINAL); 2238 JCExpression type = parseType(); 2239 int pos = token.pos; 2240 Name ident = ident(); 2241 return variableDeclaratorRest(pos, optFinal, type, ident, true, null); 2242 } 2243 2244 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} 2245 */ 2246 public JCTree.JCCompilationUnit parseCompilationUnit() { 2247 Token firstToken = token; 2248 JCExpression pid = null; 2249 JCModifiers mods = null; 2250 boolean consumedToplevelDoc = false; 2251 boolean seenImport = false; 2252 boolean seenPackage = false; 2253 List<JCAnnotation> packageAnnotations = List.nil(); 2254 if (token.kind == MONKEYS_AT) 2255 mods = modifiersOpt(); 2256 2257 if (token.kind == PACKAGE) { 2258 seenPackage = true; 2259 if (mods != null) { 2260 checkNoMods(mods.flags); 2261 packageAnnotations = mods.annotations; 2262 mods = null; 2263 } 2264 nextToken(); 2265 pid = qualident(); 2266 accept(SEMI); 2267 } 2268 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2269 boolean checkForImports = true; 2270 boolean firstTypeDecl = true; 2271 while (token.kind != EOF) { 2272 if (token.pos <= errorEndPos) { 2273 // error recovery 2274 skip(checkForImports, false, false, false); 2275 if (token.kind == EOF) 2276 break; 2277 } 2278 if (checkForImports && mods == null && token.kind == IMPORT) { 2279 seenImport = true; 2280 defs.append(importDeclaration()); 2281 } else { 2282 String docComment = token.docComment; 2283 if (firstTypeDecl && !seenImport && !seenPackage) { 2284 docComment = firstToken.docComment; 2285 consumedToplevelDoc = true; 2286 } 2287 JCTree def = typeDeclaration(mods, docComment); 2288 if (def instanceof JCExpressionStatement) 2289 def = ((JCExpressionStatement)def).expr; 2290 defs.append(def); 2291 if (def instanceof JCClassDecl) 2292 checkForImports = false; 2293 mods = null; 2294 firstTypeDecl = false; 2295 } 2296 } 2297 JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList()); 2298 if (!consumedToplevelDoc) 2299 attach(toplevel, firstToken.docComment); 2300 if (defs.elems.isEmpty()) 2301 storeEnd(toplevel, S.prevToken().endPos); 2302 if (keepDocComments) 2303 toplevel.docComments = docComments; 2304 if (keepLineMap) 2305 toplevel.lineMap = S.getLineMap(); 2306 return toplevel; 2307 } 2308 2309 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" 2310 */ 2311 JCTree importDeclaration() { 2312 int pos = token.pos; 2313 nextToken(); 2314 boolean importStatic = false; 2315 if (token.kind == STATIC) { 2316 checkStaticImports(); 2317 importStatic = true; 2318 nextToken(); 2319 } 2320 JCExpression pid = toP(F.at(token.pos).Ident(ident())); 2321 do { 2322 int pos1 = token.pos; 2323 accept(DOT); 2324 if (token.kind == STAR) { 2325 pid = to(F.at(pos1).Select(pid, names.asterisk)); 2326 nextToken(); 2327 break; 2328 } else { 2329 pid = toP(F.at(pos1).Select(pid, ident())); 2330 } 2331 } while (token.kind == DOT); 2332 accept(SEMI); 2333 return toP(F.at(pos).Import(pid, importStatic)); 2334 } 2335 2336 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration 2337 * | ";" 2338 */ 2339 JCTree typeDeclaration(JCModifiers mods, String docComment) { 2340 int pos = token.pos; 2341 if (mods == null && token.kind == SEMI) { 2342 nextToken(); 2343 return toP(F.at(pos).Skip()); 2344 } else { 2345 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment); 2346 } 2347 } 2348 2349 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt 2350 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) 2351 * @param mods Any modifiers starting the class or interface declaration 2352 * @param dc The documentation comment for the class, or null. 2353 */ 2354 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) { 2355 if (token.kind == CLASS) { 2356 return classDeclaration(mods, dc); 2357 } else if (token.kind == INTERFACE) { 2358 return interfaceDeclaration(mods, dc); 2359 } else if (allowEnums) { 2360 if (token.kind == ENUM) { 2361 return enumDeclaration(mods, dc); 2362 } else { 2363 int pos = token.pos; 2364 List<JCTree> errs; 2365 if (token.kind == IDENTIFIER) { 2366 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 2367 setErrorEndPos(token.pos); 2368 } else { 2369 errs = List.<JCTree>of(mods); 2370 } 2371 return toP(F.Exec(syntaxError(pos, errs, "expected3", 2372 CLASS, INTERFACE, ENUM))); 2373 } 2374 } else { 2375 if (token.kind == ENUM) { 2376 error(token.pos, "enums.not.supported.in.source", source.name); 2377 allowEnums = true; 2378 return enumDeclaration(mods, dc); 2379 } 2380 int pos = token.pos; 2381 List<JCTree> errs; 2382 if (token.kind == IDENTIFIER) { 2383 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 2384 setErrorEndPos(token.pos); 2385 } else { 2386 errs = List.<JCTree>of(mods); 2387 } 2388 return toP(F.Exec(syntaxError(pos, errs, "expected2", 2389 CLASS, INTERFACE))); 2390 } 2391 } 2392 2393 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] 2394 * [IMPLEMENTS TypeList] ClassBody 2395 * @param mods The modifiers starting the class declaration 2396 * @param dc The documentation comment for the class, or null. 2397 */ 2398 JCClassDecl classDeclaration(JCModifiers mods, String dc) { 2399 int pos = token.pos; 2400 accept(CLASS); 2401 Name name = ident(); 2402 2403 List<JCTypeParameter> typarams = typeParametersOpt(); 2404 2405 JCExpression extending = null; 2406 if (token.kind == EXTENDS) { 2407 nextToken(); 2408 extending = parseType(); 2409 } 2410 List<JCExpression> implementing = List.nil(); 2411 if (token.kind == IMPLEMENTS) { 2412 nextToken(); 2413 implementing = typeList(); 2414 } 2415 List<JCTree> defs = classOrInterfaceBody(name, false); 2416 JCClassDecl result = toP(F.at(pos).ClassDef( 2417 mods, name, typarams, extending, implementing, defs)); 2418 attach(result, dc); 2419 return result; 2420 } 2421 2422 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt 2423 * [EXTENDS TypeList] InterfaceBody 2424 * @param mods The modifiers starting the interface declaration 2425 * @param dc The documentation comment for the interface, or null. 2426 */ 2427 JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { 2428 int pos = token.pos; 2429 accept(INTERFACE); 2430 Name name = ident(); 2431 2432 List<JCTypeParameter> typarams = typeParametersOpt(); 2433 2434 List<JCExpression> extending = List.nil(); 2435 if (token.kind == EXTENDS) { 2436 nextToken(); 2437 extending = typeList(); 2438 } 2439 List<JCTree> defs = classOrInterfaceBody(name, true); 2440 JCClassDecl result = toP(F.at(pos).ClassDef( 2441 mods, name, typarams, null, extending, defs)); 2442 attach(result, dc); 2443 return result; 2444 } 2445 2446 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody 2447 * @param mods The modifiers starting the enum declaration 2448 * @param dc The documentation comment for the enum, or null. 2449 */ 2450 JCClassDecl enumDeclaration(JCModifiers mods, String dc) { 2451 int pos = token.pos; 2452 accept(ENUM); 2453 Name name = ident(); 2454 2455 List<JCExpression> implementing = List.nil(); 2456 if (token.kind == IMPLEMENTS) { 2457 nextToken(); 2458 implementing = typeList(); 2459 } 2460 2461 List<JCTree> defs = enumBody(name); 2462 mods.flags |= Flags.ENUM; 2463 JCClassDecl result = toP(F.at(pos). 2464 ClassDef(mods, name, List.<JCTypeParameter>nil(), 2465 null, implementing, defs)); 2466 attach(result, dc); 2467 return result; 2468 } 2469 2470 /** EnumBody = "{" { EnumeratorDeclarationList } [","] 2471 * [ ";" {ClassBodyDeclaration} ] "}" 2472 */ 2473 List<JCTree> enumBody(Name enumName) { 2474 accept(LBRACE); 2475 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2476 if (token.kind == COMMA) { 2477 nextToken(); 2478 } else if (token.kind != RBRACE && token.kind != SEMI) { 2479 defs.append(enumeratorDeclaration(enumName)); 2480 while (token.kind == COMMA) { 2481 nextToken(); 2482 if (token.kind == RBRACE || token.kind == SEMI) break; 2483 defs.append(enumeratorDeclaration(enumName)); 2484 } 2485 if (token.kind != SEMI && token.kind != RBRACE) { 2486 defs.append(syntaxError(token.pos, "expected3", 2487 COMMA, RBRACE, SEMI)); 2488 nextToken(); 2489 } 2490 } 2491 if (token.kind == SEMI) { 2492 nextToken(); 2493 while (token.kind != RBRACE && token.kind != EOF) { 2494 defs.appendList(classOrInterfaceBodyDeclaration(enumName, 2495 false)); 2496 if (token.pos <= errorEndPos) { 2497 // error recovery 2498 skip(false, true, true, false); 2499 } 2500 } 2501 } 2502 accept(RBRACE); 2503 return defs.toList(); 2504 } 2505 2506 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] 2507 */ 2508 JCTree enumeratorDeclaration(Name enumName) { 2509 String dc = token.docComment; 2510 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; 2511 if (token.deprecatedFlag) { 2512 flags |= Flags.DEPRECATED; 2513 } 2514 int pos = token.pos; 2515 List<JCAnnotation> annotations = annotationsOpt(); 2516 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 2517 List<JCExpression> typeArgs = typeArgumentsOpt(); 2518 int identPos = token.pos; 2519 Name name = ident(); 2520 int createPos = token.pos; 2521 List<JCExpression> args = (token.kind == LPAREN) 2522 ? arguments() : List.<JCExpression>nil(); 2523 JCClassDecl body = null; 2524 if (token.kind == LBRACE) { 2525 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); 2526 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 2527 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); 2528 } 2529 if (args.isEmpty() && body == null) 2530 createPos = identPos; 2531 JCIdent ident = F.at(identPos).Ident(enumName); 2532 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); 2533 if (createPos != identPos) 2534 storeEnd(create, S.prevToken().endPos); 2535 ident = F.at(identPos).Ident(enumName); 2536 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); 2537 attach(result, dc); 2538 return result; 2539 } 2540 2541 /** TypeList = Type {"," Type} 2542 */ 2543 List<JCExpression> typeList() { 2544 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 2545 ts.append(parseType()); 2546 while (token.kind == COMMA) { 2547 nextToken(); 2548 ts.append(parseType()); 2549 } 2550 return ts.toList(); 2551 } 2552 2553 /** ClassBody = "{" {ClassBodyDeclaration} "}" 2554 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" 2555 */ 2556 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 2557 accept(LBRACE); 2558 if (token.pos <= errorEndPos) { 2559 // error recovery 2560 skip(false, true, false, false); 2561 if (token.kind == LBRACE) 2562 nextToken(); 2563 } 2564 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2565 while (token.kind != RBRACE && token.kind != EOF) { 2566 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 2567 if (token.pos <= errorEndPos) { 2568 // error recovery 2569 skip(false, true, true, false); 2570 } 2571 } 2572 accept(RBRACE); 2573 return defs.toList(); 2574 } 2575 2576 /** ClassBodyDeclaration = 2577 * ";" 2578 * | [STATIC] Block 2579 * | ModifiersOpt 2580 * ( Type Ident 2581 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) 2582 * | VOID Ident MethodDeclaratorRest 2583 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest 2584 * | Ident ConstructorDeclaratorRest 2585 * | TypeParameters Ident ConstructorDeclaratorRest 2586 * | ClassOrInterfaceOrEnumDeclaration 2587 * ) 2588 * InterfaceBodyDeclaration = 2589 * ";" 2590 * | ModifiersOpt Type Ident 2591 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) 2592 */ 2593 protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { 2594 if (token.kind == SEMI) { 2595 nextToken(); 2596 return List.<JCTree>nil(); 2597 } else { 2598 String dc = token.docComment; 2599 int pos = token.pos; 2600 JCModifiers mods = modifiersOpt(); 2601 if (token.kind == CLASS || 2602 token.kind == INTERFACE || 2603 allowEnums && token.kind == ENUM) { 2604 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 2605 } else if (token.kind == LBRACE && !isInterface && 2606 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && 2607 mods.annotations.isEmpty()) { 2608 return List.<JCTree>of(block(pos, mods.flags)); 2609 } else { 2610 pos = token.pos; 2611 List<JCTypeParameter> typarams = typeParametersOpt(); 2612 // if there are type parameters but no modifiers, save the start 2613 // position of the method in the modifiers. 2614 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { 2615 mods.pos = pos; 2616 storeEnd(mods, pos); 2617 } 2618 Token tk = token; 2619 pos = token.pos; 2620 JCExpression type; 2621 boolean isVoid = token.kind == VOID; 2622 if (isVoid) { 2623 type = to(F.at(pos).TypeIdent(TypeTags.VOID)); 2624 nextToken(); 2625 } else { 2626 type = parseType(); 2627 } 2628 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) { 2629 if (isInterface || tk.name() != className) 2630 error(pos, "invalid.meth.decl.ret.type.req"); 2631 return List.of(methodDeclaratorRest( 2632 pos, mods, null, names.init, typarams, 2633 isInterface, true, dc)); 2634 } else { 2635 pos = token.pos; 2636 Name name = ident(); 2637 if (token.kind == LPAREN) { 2638 return List.of(methodDeclaratorRest( 2639 pos, mods, type, name, typarams, 2640 isInterface, isVoid, dc)); 2641 } else if (!isVoid && typarams.isEmpty()) { 2642 List<JCTree> defs = 2643 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, 2644 new ListBuffer<JCTree>()).toList(); 2645 storeEnd(defs.last(), token.endPos); 2646 accept(SEMI); 2647 return defs; 2648 } else { 2649 pos = token.pos; 2650 List<JCTree> err = isVoid 2651 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, 2652 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 2653 : null; 2654 return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN)); 2655 } 2656 } 2657 } 2658 } 2659 } 2660 2661 /** MethodDeclaratorRest = 2662 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 2663 * VoidMethodDeclaratorRest = 2664 * FormalParameters [Throws TypeList] ( MethodBody | ";") 2665 * InterfaceMethodDeclaratorRest = 2666 * FormalParameters BracketsOpt [THROWS TypeList] ";" 2667 * VoidInterfaceMethodDeclaratorRest = 2668 * FormalParameters [THROWS TypeList] ";" 2669 * ConstructorDeclaratorRest = 2670 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody 2671 */ 2672 JCTree methodDeclaratorRest(int pos, 2673 JCModifiers mods, 2674 JCExpression type, 2675 Name name, 2676 List<JCTypeParameter> typarams, 2677 boolean isInterface, boolean isVoid, 2678 String dc) { 2679 List<JCVariableDecl> params = formalParameters(); 2680 if (!isVoid) type = bracketsOpt(type); 2681 List<JCExpression> thrown = List.nil(); 2682 if (token.kind == THROWS) { 2683 nextToken(); 2684 thrown = qualidentList(); 2685 } 2686 JCBlock body = null; 2687 JCExpression defaultValue; 2688 if (token.kind == LBRACE) { 2689 body = block(); 2690 defaultValue = null; 2691 } else { 2692 if (token.kind == DEFAULT) { 2693 accept(DEFAULT); 2694 defaultValue = annotationValue(); 2695 } else { 2696 defaultValue = null; 2697 } 2698 accept(SEMI); 2699 if (token.pos <= errorEndPos) { 2700 // error recovery 2701 skip(false, true, false, false); 2702 if (token.kind == LBRACE) { 2703 body = block(); 2704 } 2705 } 2706 } 2707 2708 JCMethodDecl result = 2709 toP(F.at(pos).MethodDef(mods, name, type, typarams, 2710 params, thrown, 2711 body, defaultValue)); 2712 attach(result, dc); 2713 return result; 2714 } 2715 2716 /** QualidentList = Qualident {"," Qualident} 2717 */ 2718 List<JCExpression> qualidentList() { 2719 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 2720 ts.append(qualident()); 2721 while (token.kind == COMMA) { 2722 nextToken(); 2723 ts.append(qualident()); 2724 } 2725 return ts.toList(); 2726 } 2727 2728 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] 2729 */ 2730 List<JCTypeParameter> typeParametersOpt() { 2731 if (token.kind == LT) { 2732 checkGenerics(); 2733 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>(); 2734 nextToken(); 2735 typarams.append(typeParameter()); 2736 while (token.kind == COMMA) { 2737 nextToken(); 2738 typarams.append(typeParameter()); 2739 } 2740 accept(GT); 2741 return typarams.toList(); 2742 } else { 2743 return List.nil(); 2744 } 2745 } 2746 2747 /** TypeParameter = TypeVariable [TypeParameterBound] 2748 * TypeParameterBound = EXTENDS Type {"&" Type} 2749 * TypeVariable = Ident 2750 */ 2751 JCTypeParameter typeParameter() { 2752 int pos = token.pos; 2753 Name name = ident(); 2754 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); 2755 if (token.kind == EXTENDS) { 2756 nextToken(); 2757 bounds.append(parseType()); 2758 while (token.kind == AMP) { 2759 nextToken(); 2760 bounds.append(parseType()); 2761 } 2762 } 2763 return toP(F.at(pos).TypeParameter(name, bounds.toList())); 2764 } 2765 2766 /** FormalParameters = "(" [ FormalParameterList ] ")" 2767 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter 2768 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter 2769 */ 2770 List<JCVariableDecl> formalParameters() { 2771 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); 2772 JCVariableDecl lastParam = null; 2773 accept(LPAREN); 2774 if (token.kind != RPAREN) { 2775 params.append(lastParam = formalParameter()); 2776 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { 2777 nextToken(); 2778 params.append(lastParam = formalParameter()); 2779 } 2780 } 2781 accept(RPAREN); 2782 return params.toList(); 2783 } 2784 2785 JCModifiers optFinal(long flags) { 2786 JCModifiers mods = modifiersOpt(); 2787 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); 2788 mods.flags |= flags; 2789 return mods; 2790 } 2791 2792 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId 2793 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter 2794 */ 2795 protected JCVariableDecl formalParameter() { 2796 JCModifiers mods = optFinal(Flags.PARAMETER); 2797 JCExpression type = parseType(); 2798 if (token.kind == ELLIPSIS) { 2799 checkVarargs(); 2800 mods.flags |= Flags.VARARGS; 2801 type = to(F.at(token.pos).TypeArray(type)); 2802 nextToken(); 2803 } 2804 return variableDeclaratorId(mods, type); 2805 } 2806 2807 /* ---------- auxiliary methods -------------- */ 2808 2809 void error(int pos, String key, Object ... args) { 2810 log.error(DiagnosticFlag.SYNTAX, pos, key, args); 2811 } 2812 2813 void error(DiagnosticPosition pos, String key, Object ... args) { 2814 log.error(DiagnosticFlag.SYNTAX, pos, key, args); 2815 } 2816 2817 void warning(int pos, String key, Object ... args) { 2818 log.warning(pos, key, args); 2819 } 2820 2821 /** Check that given tree is a legal expression statement. 2822 */ 2823 protected JCExpression checkExprStat(JCExpression t) { 2824 switch(t.getTag()) { 2825 case PREINC: case PREDEC: 2826 case POSTINC: case POSTDEC: 2827 case ASSIGN: 2828 case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG: 2829 case SL_ASG: case SR_ASG: case USR_ASG: 2830 case PLUS_ASG: case MINUS_ASG: 2831 case MUL_ASG: case DIV_ASG: case MOD_ASG: 2832 case APPLY: case NEWCLASS: 2833 case ERRONEOUS: 2834 return t; 2835 default: 2836 JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t)); 2837 error(ret, "not.stmt"); 2838 return ret; 2839 } 2840 } 2841 2842 /** Return precedence of operator represented by token, 2843 * -1 if token is not a binary operator. @see TreeInfo.opPrec 2844 */ 2845 static int prec(TokenKind token) { 2846 JCTree.Tag oc = optag(token); 2847 return (oc.ordinal() > NO_TAG.ordinal()) ? TreeInfo.opPrec(oc) : -1; 2848 } 2849 2850 /** 2851 * Return the lesser of two positions, making allowance for either one 2852 * being unset. 2853 */ 2854 static int earlier(int pos1, int pos2) { 2855 if (pos1 == Position.NOPOS) 2856 return pos2; 2857 if (pos2 == Position.NOPOS) 2858 return pos1; 2859 return (pos1 < pos2 ? pos1 : pos2); 2860 } 2861 2862 /** Return operation tag of binary operator represented by token, 2863 * No_TAG if token is not a binary operator. 2864 */ 2865 static JCTree.Tag optag(TokenKind token) { 2866 switch (token) { 2867 case BARBAR: 2868 return OR; 2869 case AMPAMP: 2870 return AND; 2871 case BAR: 2872 return BITOR; 2873 case BAREQ: 2874 return BITOR_ASG; 2875 case CARET: 2876 return BITXOR; 2877 case CARETEQ: 2878 return BITXOR_ASG; 2879 case AMP: 2880 return BITAND; 2881 case AMPEQ: 2882 return BITAND_ASG; 2883 case EQEQ: 2884 return JCTree.Tag.EQ; 2885 case BANGEQ: 2886 return NE; 2887 case LT: 2888 return JCTree.Tag.LT; 2889 case GT: 2890 return JCTree.Tag.GT; 2891 case LTEQ: 2892 return LE; 2893 case GTEQ: 2894 return GE; 2895 case LTLT: 2896 return SL; 2897 case LTLTEQ: 2898 return SL_ASG; 2899 case GTGT: 2900 return SR; 2901 case GTGTEQ: 2902 return SR_ASG; 2903 case GTGTGT: 2904 return USR; 2905 case GTGTGTEQ: 2906 return USR_ASG; 2907 case PLUS: 2908 return JCTree.Tag.PLUS; 2909 case PLUSEQ: 2910 return PLUS_ASG; 2911 case SUB: 2912 return MINUS; 2913 case SUBEQ: 2914 return MINUS_ASG; 2915 case STAR: 2916 return MUL; 2917 case STAREQ: 2918 return MUL_ASG; 2919 case SLASH: 2920 return DIV; 2921 case SLASHEQ: 2922 return DIV_ASG; 2923 case PERCENT: 2924 return MOD; 2925 case PERCENTEQ: 2926 return MOD_ASG; 2927 case INSTANCEOF: 2928 return TYPETEST; 2929 default: 2930 return NO_TAG; 2931 } 2932 } 2933 2934 /** Return operation tag of unary operator represented by token, 2935 * No_TAG if token is not a binary operator. 2936 */ 2937 static JCTree.Tag unoptag(TokenKind token) { 2938 switch (token) { 2939 case PLUS: 2940 return POS; 2941 case SUB: 2942 return NEG; 2943 case BANG: 2944 return NOT; 2945 case TILDE: 2946 return COMPL; 2947 case PLUSPLUS: 2948 return PREINC; 2949 case SUBSUB: 2950 return PREDEC; 2951 default: 2952 return NO_TAG; 2953 } 2954 } 2955 2956 /** Return type tag of basic type represented by token, 2957 * -1 if token is not a basic type identifier. 2958 */ 2959 static int typetag(TokenKind token) { 2960 switch (token) { 2961 case BYTE: 2962 return TypeTags.BYTE; 2963 case CHAR: 2964 return TypeTags.CHAR; 2965 case SHORT: 2966 return TypeTags.SHORT; 2967 case INT: 2968 return TypeTags.INT; 2969 case LONG: 2970 return TypeTags.LONG; 2971 case FLOAT: 2972 return TypeTags.FLOAT; 2973 case DOUBLE: 2974 return TypeTags.DOUBLE; 2975 case BOOLEAN: 2976 return TypeTags.BOOLEAN; 2977 default: 2978 return -1; 2979 } 2980 } 2981 2982 void checkGenerics() { 2983 if (!allowGenerics) { 2984 error(token.pos, "generics.not.supported.in.source", source.name); 2985 allowGenerics = true; 2986 } 2987 } 2988 void checkVarargs() { 2989 if (!allowVarargs) { 2990 error(token.pos, "varargs.not.supported.in.source", source.name); 2991 allowVarargs = true; 2992 } 2993 } 2994 void checkForeach() { 2995 if (!allowForeach) { 2996 error(token.pos, "foreach.not.supported.in.source", source.name); 2997 allowForeach = true; 2998 } 2999 } 3000 void checkStaticImports() { 3001 if (!allowStaticImport) { 3002 error(token.pos, "static.import.not.supported.in.source", source.name); 3003 allowStaticImport = true; 3004 } 3005 } 3006 void checkAnnotations() { 3007 if (!allowAnnotations) { 3008 error(token.pos, "annotations.not.supported.in.source", source.name); 3009 allowAnnotations = true; 3010 } 3011 } 3012 void checkDiamond() { 3013 if (!allowDiamond) { 3014 error(token.pos, "diamond.not.supported.in.source", source.name); 3015 allowDiamond = true; 3016 } 3017 } 3018 void checkMulticatch() { 3019 if (!allowMulticatch) { 3020 error(token.pos, "multicatch.not.supported.in.source", source.name); 3021 allowMulticatch = true; 3022 } 3023 } 3024 void checkTryWithResources() { 3025 if (!allowTWR) { 3026 error(token.pos, "try.with.resources.not.supported.in.source", source.name); 3027 allowTWR = true; 3028 } 3029 } 3030 }