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