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 try-with-resources? 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 S.token() == LBRACKET) { 2173 log.error(S.pos(), "varargs.and.old.array.syntax"); 2174 } 2175 type = bracketsOpt(type); 2176 return toP(F.at(pos).VarDef(mods, name, type, null)); 2177 } 2178 2179 /** Resources = Resource { ";" Resources } 2180 */ 2181 List<JCTree> resources() { 2182 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2183 defs.append(resource()); 2184 while (S.token() == SEMI) { 2185 // All but last of multiple declarators subsume a semicolon 2186 storeEnd(defs.elems.last(), S.endPos()); 2187 int semiColonPos = S.pos(); 2188 S.nextToken(); 2189 if (S.token() == RPAREN) { // Illegal trailing semicolon 2190 // after last resource 2191 error(semiColonPos, "try.resource.trailing.semi"); 2192 break; 2193 } 2194 defs.append(resource()); 2195 } 2196 return defs.toList(); 2197 } 2198 2199 /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression 2200 */ 2201 JCTree resource() { 2202 return variableDeclaratorRest(S.pos(), optFinal(Flags.FINAL), 2203 parseType(), ident(), true, null); 2204 } 2205 2206 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} 2207 */ 2208 public JCTree.JCCompilationUnit parseCompilationUnit() { 2209 int pos = S.pos(); 2210 JCExpression pid = null; 2211 String dc = S.docComment(); 2212 JCModifiers mods = null; 2213 List<JCAnnotation> packageAnnotations = List.nil(); 2214 if (S.token() == MONKEYS_AT) 2215 mods = modifiersOpt(); 2216 2217 if (S.token() == PACKAGE) { 2218 if (mods != null) { 2219 checkNoMods(mods.flags); 2220 packageAnnotations = mods.annotations; 2221 mods = null; 2222 } 2223 S.nextToken(); 2224 pid = qualident(); 2225 accept(SEMI); 2226 } 2227 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2228 boolean checkForImports = true; 2229 while (S.token() != EOF) { 2230 if (S.pos() <= errorEndPos) { 2231 // error recovery 2232 skip(checkForImports, false, false, false); 2233 if (S.token() == EOF) 2234 break; 2235 } 2236 if (checkForImports && mods == null && S.token() == IMPORT) { 2237 defs.append(importDeclaration()); 2238 } else { 2239 JCTree def = typeDeclaration(mods); 2240 if (keepDocComments && dc != null && docComments.get(def) == dc) { 2241 // If the first type declaration has consumed the first doc 2242 // comment, then don't use it for the top level comment as well. 2243 dc = null; 2244 } 2245 if (def instanceof JCExpressionStatement) 2246 def = ((JCExpressionStatement)def).expr; 2247 defs.append(def); 2248 if (def instanceof JCClassDecl) 2249 checkForImports = false; 2250 mods = null; 2251 } 2252 } 2253 JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList()); 2254 attach(toplevel, dc); 2255 if (defs.elems.isEmpty()) 2256 storeEnd(toplevel, S.prevEndPos()); 2257 if (keepDocComments) 2258 toplevel.docComments = docComments; 2259 if (keepLineMap) 2260 toplevel.lineMap = S.getLineMap(); 2261 return toplevel; 2262 } 2263 2264 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" 2265 */ 2266 JCTree importDeclaration() { 2267 int pos = S.pos(); 2268 S.nextToken(); 2269 boolean importStatic = false; 2270 if (S.token() == STATIC) { 2271 checkStaticImports(); 2272 importStatic = true; 2273 S.nextToken(); 2274 } 2275 JCExpression pid = toP(F.at(S.pos()).Ident(ident())); 2276 do { 2277 int pos1 = S.pos(); 2278 accept(DOT); 2279 if (S.token() == STAR) { 2280 pid = to(F.at(pos1).Select(pid, names.asterisk)); 2281 S.nextToken(); 2282 break; 2283 } else { 2284 pid = toP(F.at(pos1).Select(pid, ident())); 2285 } 2286 } while (S.token() == DOT); 2287 accept(SEMI); 2288 return toP(F.at(pos).Import(pid, importStatic)); 2289 } 2290 2291 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration 2292 * | ";" 2293 */ 2294 JCTree typeDeclaration(JCModifiers mods) { 2295 int pos = S.pos(); 2296 if (mods == null && S.token() == SEMI) { 2297 S.nextToken(); 2298 return toP(F.at(pos).Skip()); 2299 } else { 2300 String dc = S.docComment(); 2301 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc); 2302 } 2303 } 2304 2305 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt 2306 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) 2307 * @param mods Any modifiers starting the class or interface declaration 2308 * @param dc The documentation comment for the class, or null. 2309 */ 2310 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) { 2311 if (S.token() == CLASS) { 2312 return classDeclaration(mods, dc); 2313 } else if (S.token() == INTERFACE) { 2314 return interfaceDeclaration(mods, dc); 2315 } else if (allowEnums) { 2316 if (S.token() == ENUM) { 2317 return enumDeclaration(mods, dc); 2318 } else { 2319 int pos = S.pos(); 2320 List<JCTree> errs; 2321 if (S.token() == IDENTIFIER) { 2322 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 2323 setErrorEndPos(S.pos()); 2324 } else { 2325 errs = List.<JCTree>of(mods); 2326 } 2327 return toP(F.Exec(syntaxError(pos, errs, "expected3", 2328 CLASS, INTERFACE, ENUM))); 2329 } 2330 } else { 2331 if (S.token() == ENUM) { 2332 error(S.pos(), "enums.not.supported.in.source", source.name); 2333 allowEnums = true; 2334 return enumDeclaration(mods, dc); 2335 } 2336 int pos = S.pos(); 2337 List<JCTree> errs; 2338 if (S.token() == IDENTIFIER) { 2339 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 2340 setErrorEndPos(S.pos()); 2341 } else { 2342 errs = List.<JCTree>of(mods); 2343 } 2344 return toP(F.Exec(syntaxError(pos, errs, "expected2", 2345 CLASS, INTERFACE))); 2346 } 2347 } 2348 2349 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] 2350 * [IMPLEMENTS TypeList] ClassBody 2351 * @param mods The modifiers starting the class declaration 2352 * @param dc The documentation comment for the class, or null. 2353 */ 2354 JCClassDecl classDeclaration(JCModifiers mods, String dc) { 2355 int pos = S.pos(); 2356 accept(CLASS); 2357 Name name = ident(); 2358 2359 List<JCTypeParameter> typarams = typeParametersOpt(); 2360 2361 JCTree extending = null; 2362 if (S.token() == EXTENDS) { 2363 S.nextToken(); 2364 extending = parseType(); 2365 } 2366 List<JCExpression> implementing = List.nil(); 2367 if (S.token() == IMPLEMENTS) { 2368 S.nextToken(); 2369 implementing = typeList(); 2370 } 2371 List<JCTree> defs = classOrInterfaceBody(name, false); 2372 JCClassDecl result = toP(F.at(pos).ClassDef( 2373 mods, name, typarams, extending, implementing, defs)); 2374 attach(result, dc); 2375 return result; 2376 } 2377 2378 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt 2379 * [EXTENDS TypeList] InterfaceBody 2380 * @param mods The modifiers starting the interface declaration 2381 * @param dc The documentation comment for the interface, or null. 2382 */ 2383 JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { 2384 int pos = S.pos(); 2385 accept(INTERFACE); 2386 Name name = ident(); 2387 2388 List<JCTypeParameter> typarams = typeParametersOpt(); 2389 2390 List<JCExpression> extending = List.nil(); 2391 if (S.token() == EXTENDS) { 2392 S.nextToken(); 2393 extending = typeList(); 2394 } 2395 List<JCTree> defs = classOrInterfaceBody(name, true); 2396 JCClassDecl result = toP(F.at(pos).ClassDef( 2397 mods, name, typarams, null, extending, defs)); 2398 attach(result, dc); 2399 return result; 2400 } 2401 2402 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody 2403 * @param mods The modifiers starting the enum declaration 2404 * @param dc The documentation comment for the enum, or null. 2405 */ 2406 JCClassDecl enumDeclaration(JCModifiers mods, String dc) { 2407 int pos = S.pos(); 2408 accept(ENUM); 2409 Name name = ident(); 2410 2411 List<JCExpression> implementing = List.nil(); 2412 if (S.token() == IMPLEMENTS) { 2413 S.nextToken(); 2414 implementing = typeList(); 2415 } 2416 2417 List<JCTree> defs = enumBody(name); 2418 mods.flags |= Flags.ENUM; 2419 JCClassDecl result = toP(F.at(pos). 2420 ClassDef(mods, name, List.<JCTypeParameter>nil(), 2421 null, implementing, defs)); 2422 attach(result, dc); 2423 return result; 2424 } 2425 2426 /** EnumBody = "{" { EnumeratorDeclarationList } [","] 2427 * [ ";" {ClassBodyDeclaration} ] "}" 2428 */ 2429 List<JCTree> enumBody(Name enumName) { 2430 accept(LBRACE); 2431 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2432 if (S.token() == COMMA) { 2433 S.nextToken(); 2434 } else if (S.token() != RBRACE && S.token() != SEMI) { 2435 defs.append(enumeratorDeclaration(enumName)); 2436 while (S.token() == COMMA) { 2437 S.nextToken(); 2438 if (S.token() == RBRACE || S.token() == SEMI) break; 2439 defs.append(enumeratorDeclaration(enumName)); 2440 } 2441 if (S.token() != SEMI && S.token() != RBRACE) { 2442 defs.append(syntaxError(S.pos(), "expected3", 2443 COMMA, RBRACE, SEMI)); 2444 S.nextToken(); 2445 } 2446 } 2447 if (S.token() == SEMI) { 2448 S.nextToken(); 2449 while (S.token() != RBRACE && S.token() != EOF) { 2450 defs.appendList(classOrInterfaceBodyDeclaration(enumName, 2451 false)); 2452 if (S.pos() <= errorEndPos) { 2453 // error recovery 2454 skip(false, true, true, false); 2455 } 2456 } 2457 } 2458 accept(RBRACE); 2459 return defs.toList(); 2460 } 2461 2462 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] 2463 */ 2464 JCTree enumeratorDeclaration(Name enumName) { 2465 String dc = S.docComment(); 2466 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; 2467 if (S.deprecatedFlag()) { 2468 flags |= Flags.DEPRECATED; 2469 S.resetDeprecatedFlag(); 2470 } 2471 int pos = S.pos(); 2472 List<JCAnnotation> annotations = annotationsOpt(); 2473 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 2474 List<JCExpression> typeArgs = typeArgumentsOpt(); 2475 int identPos = S.pos(); 2476 Name name = ident(); 2477 int createPos = S.pos(); 2478 List<JCExpression> args = (S.token() == LPAREN) 2479 ? arguments() : List.<JCExpression>nil(); 2480 JCClassDecl body = null; 2481 if (S.token() == LBRACE) { 2482 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); 2483 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 2484 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); 2485 } 2486 if (args.isEmpty() && body == null) 2487 createPos = identPos; 2488 JCIdent ident = F.at(identPos).Ident(enumName); 2489 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); 2490 if (createPos != identPos) 2491 storeEnd(create, S.prevEndPos()); 2492 ident = F.at(identPos).Ident(enumName); 2493 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); 2494 attach(result, dc); 2495 return result; 2496 } 2497 2498 /** TypeList = Type {"," Type} 2499 */ 2500 List<JCExpression> typeList() { 2501 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 2502 ts.append(parseType()); 2503 while (S.token() == COMMA) { 2504 S.nextToken(); 2505 ts.append(parseType()); 2506 } 2507 return ts.toList(); 2508 } 2509 2510 /** ClassBody = "{" {ClassBodyDeclaration} "}" 2511 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" 2512 */ 2513 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 2514 accept(LBRACE); 2515 if (S.pos() <= errorEndPos) { 2516 // error recovery 2517 skip(false, true, false, false); 2518 if (S.token() == LBRACE) 2519 S.nextToken(); 2520 } 2521 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2522 while (S.token() != RBRACE && S.token() != EOF) { 2523 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 2524 if (S.pos() <= errorEndPos) { 2525 // error recovery 2526 skip(false, true, true, false); 2527 } 2528 } 2529 accept(RBRACE); 2530 return defs.toList(); 2531 } 2532 2533 /** ClassBodyDeclaration = 2534 * ";" 2535 * | [STATIC] Block 2536 * | ModifiersOpt 2537 * ( Type Ident 2538 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) 2539 * | VOID Ident MethodDeclaratorRest 2540 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest 2541 * | Ident ConstructorDeclaratorRest 2542 * | TypeParameters Ident ConstructorDeclaratorRest 2543 * | ClassOrInterfaceOrEnumDeclaration 2544 * ) 2545 * InterfaceBodyDeclaration = 2546 * ";" 2547 * | ModifiersOpt Type Ident 2548 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) 2549 */ 2550 List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { 2551 if (S.token() == SEMI) { 2552 S.nextToken(); 2553 return List.<JCTree>nil(); 2554 } else { 2555 String dc = S.docComment(); 2556 int pos = S.pos(); 2557 JCModifiers mods = modifiersOpt(); 2558 if (S.token() == CLASS || 2559 S.token() == INTERFACE || 2560 allowEnums && S.token() == ENUM) { 2561 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 2562 } else if (S.token() == LBRACE && !isInterface && 2563 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && 2564 mods.annotations.isEmpty()) { 2565 return List.<JCTree>of(block(pos, mods.flags)); 2566 } else { 2567 pos = S.pos(); 2568 List<JCTypeParameter> typarams = typeParametersOpt(); 2569 // if there are type parameters but no modifiers, save the start 2570 // position of the method in the modifiers. 2571 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { 2572 mods.pos = pos; 2573 storeEnd(mods, pos); 2574 } 2575 Name name = S.name(); 2576 pos = S.pos(); 2577 JCExpression type; 2578 boolean isVoid = S.token() == VOID; 2579 if (isVoid) { 2580 type = to(F.at(pos).TypeIdent(TypeTags.VOID)); 2581 S.nextToken(); 2582 } else { 2583 type = parseType(); 2584 } 2585 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { 2586 if (isInterface || name != className) 2587 error(pos, "invalid.meth.decl.ret.type.req"); 2588 return List.of(methodDeclaratorRest( 2589 pos, mods, null, names.init, typarams, 2590 isInterface, true, dc)); 2591 } else { 2592 pos = S.pos(); 2593 name = ident(); 2594 if (S.token() == LPAREN) { 2595 return List.of(methodDeclaratorRest( 2596 pos, mods, type, name, typarams, 2597 isInterface, isVoid, dc)); 2598 } else if (!isVoid && typarams.isEmpty()) { 2599 List<JCTree> defs = 2600 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, 2601 new ListBuffer<JCTree>()).toList(); 2602 storeEnd(defs.last(), S.endPos()); 2603 accept(SEMI); 2604 return defs; 2605 } else { 2606 pos = S.pos(); 2607 List<JCTree> err = isVoid 2608 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, 2609 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 2610 : null; 2611 return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN)); 2612 } 2613 } 2614 } 2615 } 2616 } 2617 2618 /** MethodDeclaratorRest = 2619 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 2620 * VoidMethodDeclaratorRest = 2621 * FormalParameters [Throws TypeList] ( MethodBody | ";") 2622 * InterfaceMethodDeclaratorRest = 2623 * FormalParameters BracketsOpt [THROWS TypeList] ";" 2624 * VoidInterfaceMethodDeclaratorRest = 2625 * FormalParameters [THROWS TypeList] ";" 2626 * ConstructorDeclaratorRest = 2627 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody 2628 */ 2629 JCTree methodDeclaratorRest(int pos, 2630 JCModifiers mods, 2631 JCExpression type, 2632 Name name, 2633 List<JCTypeParameter> typarams, 2634 boolean isInterface, boolean isVoid, 2635 String dc) { 2636 List<JCVariableDecl> params = formalParameters(); 2637 if (!isVoid) type = bracketsOpt(type); 2638 List<JCExpression> thrown = List.nil(); 2639 if (S.token() == THROWS) { 2640 S.nextToken(); 2641 thrown = qualidentList(); 2642 } 2643 JCBlock body = null; 2644 JCExpression defaultValue; 2645 if (S.token() == LBRACE) { 2646 body = block(); 2647 defaultValue = null; 2648 } else { 2649 if (S.token() == DEFAULT) { 2650 accept(DEFAULT); 2651 defaultValue = annotationValue(); 2652 } else { 2653 defaultValue = null; 2654 } 2655 accept(SEMI); 2656 if (S.pos() <= errorEndPos) { 2657 // error recovery 2658 skip(false, true, false, false); 2659 if (S.token() == LBRACE) { 2660 body = block(); 2661 } 2662 } 2663 } 2664 2665 JCMethodDecl result = 2666 toP(F.at(pos).MethodDef(mods, name, type, typarams, 2667 params, thrown, 2668 body, defaultValue)); 2669 attach(result, dc); 2670 return result; 2671 } 2672 2673 /** QualidentList = Qualident {"," Qualident} 2674 */ 2675 List<JCExpression> qualidentList() { 2676 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 2677 ts.append(qualident()); 2678 while (S.token() == COMMA) { 2679 S.nextToken(); 2680 ts.append(qualident()); 2681 } 2682 return ts.toList(); 2683 } 2684 2685 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] 2686 */ 2687 List<JCTypeParameter> typeParametersOpt() { 2688 if (S.token() == LT) { 2689 checkGenerics(); 2690 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>(); 2691 S.nextToken(); 2692 typarams.append(typeParameter()); 2693 while (S.token() == COMMA) { 2694 S.nextToken(); 2695 typarams.append(typeParameter()); 2696 } 2697 accept(GT); 2698 return typarams.toList(); 2699 } else { 2700 return List.nil(); 2701 } 2702 } 2703 2704 /** TypeParameter = TypeVariable [TypeParameterBound] 2705 * TypeParameterBound = EXTENDS Type {"&" Type} 2706 * TypeVariable = Ident 2707 */ 2708 JCTypeParameter typeParameter() { 2709 int pos = S.pos(); 2710 Name name = ident(); 2711 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); 2712 if (S.token() == EXTENDS) { 2713 S.nextToken(); 2714 bounds.append(parseType()); 2715 while (S.token() == AMP) { 2716 S.nextToken(); 2717 bounds.append(parseType()); 2718 } 2719 } 2720 return toP(F.at(pos).TypeParameter(name, bounds.toList())); 2721 } 2722 2723 /** FormalParameters = "(" [ FormalParameterList ] ")" 2724 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter 2725 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter 2726 */ 2727 List<JCVariableDecl> formalParameters() { 2728 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); 2729 JCVariableDecl lastParam = null; 2730 accept(LPAREN); 2731 if (S.token() != RPAREN) { 2732 params.append(lastParam = formalParameter()); 2733 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) { 2734 S.nextToken(); 2735 params.append(lastParam = formalParameter()); 2736 } 2737 } 2738 accept(RPAREN); 2739 return params.toList(); 2740 } 2741 2742 JCModifiers optFinal(long flags) { 2743 JCModifiers mods = modifiersOpt(); 2744 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); 2745 mods.flags |= flags; 2746 return mods; 2747 } 2748 2749 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId 2750 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter 2751 */ 2752 JCVariableDecl formalParameter() { 2753 JCModifiers mods = optFinal(Flags.PARAMETER); 2754 JCExpression type = parseType(); 2755 if (S.token() == ELLIPSIS) { 2756 checkVarargs(); 2757 mods.flags |= Flags.VARARGS; 2758 type = to(F.at(S.pos()).TypeArray(type)); 2759 S.nextToken(); 2760 } 2761 return variableDeclaratorId(mods, type); 2762 } 2763 2764 /* ---------- auxiliary methods -------------- */ 2765 2766 void error(int pos, String key, Object ... args) { 2767 log.error(DiagnosticFlag.SYNTAX, pos, key, args); 2768 } 2769 2770 void warning(int pos, String key, Object ... args) { 2771 log.warning(pos, key, args); 2772 } 2773 2774 /** Check that given tree is a legal expression statement. 2775 */ 2776 protected JCExpression checkExprStat(JCExpression t) { 2777 switch(t.getTag()) { 2778 case JCTree.PREINC: case JCTree.PREDEC: 2779 case JCTree.POSTINC: case JCTree.POSTDEC: 2780 case JCTree.ASSIGN: 2781 case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG: 2782 case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG: 2783 case JCTree.PLUS_ASG: case JCTree.MINUS_ASG: 2784 case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG: 2785 case JCTree.APPLY: case JCTree.NEWCLASS: 2786 case JCTree.ERRONEOUS: 2787 return t; 2788 default: 2789 error(t.pos, "not.stmt"); 2790 return F.at(t.pos).Erroneous(List.<JCTree>of(t)); 2791 } 2792 } 2793 2794 /** Return precedence of operator represented by token, 2795 * -1 if token is not a binary operator. @see TreeInfo.opPrec 2796 */ 2797 static int prec(Token token) { 2798 int oc = optag(token); 2799 return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; 2800 } 2801 2802 /** 2803 * Return the lesser of two positions, making allowance for either one 2804 * being unset. 2805 */ 2806 static int earlier(int pos1, int pos2) { 2807 if (pos1 == Position.NOPOS) 2808 return pos2; 2809 if (pos2 == Position.NOPOS) 2810 return pos1; 2811 return (pos1 < pos2 ? pos1 : pos2); 2812 } 2813 2814 /** Return operation tag of binary operator represented by token, 2815 * -1 if token is not a binary operator. 2816 */ 2817 static int optag(Token token) { 2818 switch (token) { 2819 case BARBAR: 2820 return JCTree.OR; 2821 case AMPAMP: 2822 return JCTree.AND; 2823 case BAR: 2824 return JCTree.BITOR; 2825 case BAREQ: 2826 return JCTree.BITOR_ASG; 2827 case CARET: 2828 return JCTree.BITXOR; 2829 case CARETEQ: 2830 return JCTree.BITXOR_ASG; 2831 case AMP: 2832 return JCTree.BITAND; 2833 case AMPEQ: 2834 return JCTree.BITAND_ASG; 2835 case EQEQ: 2836 return JCTree.EQ; 2837 case BANGEQ: 2838 return JCTree.NE; 2839 case LT: 2840 return JCTree.LT; 2841 case GT: 2842 return JCTree.GT; 2843 case LTEQ: 2844 return JCTree.LE; 2845 case GTEQ: 2846 return JCTree.GE; 2847 case LTLT: 2848 return JCTree.SL; 2849 case LTLTEQ: 2850 return JCTree.SL_ASG; 2851 case GTGT: 2852 return JCTree.SR; 2853 case GTGTEQ: 2854 return JCTree.SR_ASG; 2855 case GTGTGT: 2856 return JCTree.USR; 2857 case GTGTGTEQ: 2858 return JCTree.USR_ASG; 2859 case PLUS: 2860 return JCTree.PLUS; 2861 case PLUSEQ: 2862 return JCTree.PLUS_ASG; 2863 case SUB: 2864 return JCTree.MINUS; 2865 case SUBEQ: 2866 return JCTree.MINUS_ASG; 2867 case STAR: 2868 return JCTree.MUL; 2869 case STAREQ: 2870 return JCTree.MUL_ASG; 2871 case SLASH: 2872 return JCTree.DIV; 2873 case SLASHEQ: 2874 return JCTree.DIV_ASG; 2875 case PERCENT: 2876 return JCTree.MOD; 2877 case PERCENTEQ: 2878 return JCTree.MOD_ASG; 2879 case INSTANCEOF: 2880 return JCTree.TYPETEST; 2881 default: 2882 return -1; 2883 } 2884 } 2885 2886 /** Return operation tag of unary operator represented by token, 2887 * -1 if token is not a binary operator. 2888 */ 2889 static int unoptag(Token token) { 2890 switch (token) { 2891 case PLUS: 2892 return JCTree.POS; 2893 case SUB: 2894 return JCTree.NEG; 2895 case BANG: 2896 return JCTree.NOT; 2897 case TILDE: 2898 return JCTree.COMPL; 2899 case PLUSPLUS: 2900 return JCTree.PREINC; 2901 case SUBSUB: 2902 return JCTree.PREDEC; 2903 default: 2904 return -1; 2905 } 2906 } 2907 2908 /** Return type tag of basic type represented by token, 2909 * -1 if token is not a basic type identifier. 2910 */ 2911 static int typetag(Token token) { 2912 switch (token) { 2913 case BYTE: 2914 return TypeTags.BYTE; 2915 case CHAR: 2916 return TypeTags.CHAR; 2917 case SHORT: 2918 return TypeTags.SHORT; 2919 case INT: 2920 return TypeTags.INT; 2921 case LONG: 2922 return TypeTags.LONG; 2923 case FLOAT: 2924 return TypeTags.FLOAT; 2925 case DOUBLE: 2926 return TypeTags.DOUBLE; 2927 case BOOLEAN: 2928 return TypeTags.BOOLEAN; 2929 default: 2930 return -1; 2931 } 2932 } 2933 2934 void checkGenerics() { 2935 if (!allowGenerics) { 2936 error(S.pos(), "generics.not.supported.in.source", source.name); 2937 allowGenerics = true; 2938 } 2939 } 2940 void checkVarargs() { 2941 if (!allowVarargs) { 2942 error(S.pos(), "varargs.not.supported.in.source", source.name); 2943 allowVarargs = true; 2944 } 2945 } 2946 void checkForeach() { 2947 if (!allowForeach) { 2948 error(S.pos(), "foreach.not.supported.in.source", source.name); 2949 allowForeach = true; 2950 } 2951 } 2952 void checkStaticImports() { 2953 if (!allowStaticImport) { 2954 error(S.pos(), "static.import.not.supported.in.source", source.name); 2955 allowStaticImport = true; 2956 } 2957 } 2958 void checkAnnotations() { 2959 if (!allowAnnotations) { 2960 error(S.pos(), "annotations.not.supported.in.source", source.name); 2961 allowAnnotations = true; 2962 } 2963 } 2964 void checkDiamond() { 2965 if (!allowDiamond) { 2966 error(S.pos(), "diamond.not.supported.in.source", source.name); 2967 allowDiamond = true; 2968 } 2969 } 2970 void checkMulticatch() { 2971 if (!allowMulticatch) { 2972 error(S.pos(), "multicatch.not.supported.in.source", source.name); 2973 allowMulticatch = true; 2974 } 2975 } 2976 void checkTryWithResources() { 2977 if (!allowTWR) { 2978 error(S.pos(), "try.with.resources.not.supported.in.source", source.name); 2979 allowTWR = true; 2980 } 2981 } 2982 }