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