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(false); 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(false); 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(false); 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(false) : 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, false); 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(false); 1227 } 1228 return null; 1229 } 1230 1231 /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">" 1232 */ 1233 List<JCExpression> typeArguments(boolean diamondAllowed) { 1234 if (S.token() == LT) { 1235 S.nextToken(); 1236 if (S.token() == GT && diamondAllowed) { 1237 checkDiamond(); 1238 mode |= DIAMOND; 1239 S.nextToken(); 1240 return List.nil(); 1241 } else { 1242 ListBuffer<JCExpression> args = ListBuffer.lb(); 1243 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 1244 while (S.token() == COMMA) { 1245 S.nextToken(); 1246 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 1247 } 1248 switch (S.token()) { 1249 case GTGTGTEQ: 1250 S.token(GTGTEQ); 1251 break; 1252 case GTGTEQ: 1253 S.token(GTEQ); 1254 break; 1255 case GTEQ: 1256 S.token(EQ); 1257 break; 1258 case GTGTGT: 1259 S.token(GTGT); 1260 break; 1261 case GTGT: 1262 S.token(GT); 1263 break; 1264 default: 1265 accept(GT); 1266 break; 1267 } 1268 return args.toList(); 1269 } 1270 } else { 1271 syntaxError(S.pos(), "expected", LT); 1272 return List.nil(); 1273 } 1274 } 1275 1276 /** TypeArgument = Type 1277 * | "?" 1278 * | "?" EXTENDS Type {"&" Type} 1279 * | "?" SUPER Type 1280 */ 1281 JCExpression typeArgument() { 1282 if (S.token() != QUES) return parseType(); 1283 int pos = S.pos(); 1284 S.nextToken(); 1285 if (S.token() == EXTENDS) { 1286 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); 1287 S.nextToken(); 1288 JCExpression bound = parseType(); 1289 return F.at(pos).Wildcard(t, bound); 1290 } else if (S.token() == SUPER) { 1291 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); 1292 S.nextToken(); 1293 JCExpression bound = parseType(); 1294 return F.at(pos).Wildcard(t, bound); 1295 } else if (S.token() == IDENTIFIER) { 1296 //error recovery 1297 reportSyntaxError(S.prevEndPos(), "expected3", 1298 GT, EXTENDS, SUPER); 1299 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 1300 JCExpression wc = toP(F.at(pos).Wildcard(t, null)); 1301 JCIdent id = toP(F.at(S.pos()).Ident(ident())); 1302 return F.at(pos).Erroneous(List.<JCTree>of(wc, id)); 1303 } else { 1304 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); 1305 return toP(F.at(pos).Wildcard(t, null)); 1306 } 1307 } 1308 1309 JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) { 1310 int pos = S.pos(); 1311 List<JCExpression> args = typeArguments(diamondAllowed); 1312 return toP(F.at(pos).TypeApply(t, args)); 1313 } 1314 1315 /** BracketsOpt = {"[" "]"} 1316 */ 1317 private JCExpression bracketsOpt(JCExpression t) { 1318 if (S.token() == LBRACKET) { 1319 int pos = S.pos(); 1320 S.nextToken(); 1321 t = bracketsOptCont(t, pos); 1322 F.at(pos); 1323 } 1324 return t; 1325 } 1326 1327 private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) { 1328 accept(RBRACKET); 1329 t = bracketsOpt(t); 1330 return toP(F.at(pos).TypeArray(t)); 1331 } 1332 1333 /** BracketsSuffixExpr = "." CLASS 1334 * BracketsSuffixType = 1335 */ 1336 JCExpression bracketsSuffix(JCExpression t) { 1337 if ((mode & EXPR) != 0 && S.token() == DOT) { 1338 mode = EXPR; 1339 int pos = S.pos(); 1340 S.nextToken(); 1341 accept(CLASS); 1342 if (S.pos() == errorEndPos) { 1343 // error recovery 1344 Name name = null; 1345 if (S.token() == IDENTIFIER) { 1346 name = S.name(); 1347 S.nextToken(); 1348 } else { 1349 name = names.error; 1350 } 1351 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name)))); 1352 } else { 1353 t = toP(F.at(pos).Select(t, names._class)); 1354 } 1355 } else if ((mode & TYPE) != 0) { 1356 mode = TYPE; 1357 } else { 1358 syntaxError(S.pos(), "dot.class.expected"); 1359 } 1360 return t; 1361 } 1362 1363 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) 1364 */ 1365 JCExpression creator(int newpos, List<JCExpression> typeArgs) { 1366 switch (S.token()) { 1367 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 1368 case DOUBLE: case BOOLEAN: 1369 if (typeArgs == null) 1370 return arrayCreatorRest(newpos, basicType()); 1371 break; 1372 default: 1373 } 1374 JCExpression t = qualident(); 1375 int oldmode = mode; 1376 mode = TYPE; 1377 boolean diamondFound = false; 1378 if (S.token() == LT) { 1379 checkGenerics(); 1380 t = typeArguments(t, true); 1381 diamondFound = (mode & DIAMOND) != 0; 1382 } 1383 while (S.token() == DOT) { 1384 if (diamondFound) { 1385 //cannot select after a diamond 1386 illegal(S.pos()); 1387 } 1388 int pos = S.pos(); 1389 S.nextToken(); 1390 t = toP(F.at(pos).Select(t, ident())); 1391 if (S.token() == LT) { 1392 checkGenerics(); 1393 t = typeArguments(t, true); 1394 diamondFound = (mode & DIAMOND) != 0; 1395 } 1396 } 1397 mode = oldmode; 1398 if (S.token() == LBRACKET) { 1399 JCExpression e = arrayCreatorRest(newpos, t); 1400 if (typeArgs != null) { 1401 int pos = newpos; 1402 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) { 1403 // note: this should always happen but we should 1404 // not rely on this as the parser is continuously 1405 // modified to improve error recovery. 1406 pos = typeArgs.head.pos; 1407 } 1408 setErrorEndPos(S.prevEndPos()); 1409 reportSyntaxError(pos, "cannot.create.array.with.type.arguments"); 1410 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e))); 1411 } 1412 return e; 1413 } else if (S.token() == LPAREN) { 1414 return classCreatorRest(newpos, null, typeArgs, t); 1415 } else { 1416 reportSyntaxError(S.pos(), "expected2", 1417 LPAREN, LBRACKET); 1418 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null)); 1419 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t))); 1420 } 1421 } 1422 1423 /** InnerCreator = Ident [TypeArguments] ClassCreatorRest 1424 */ 1425 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) { 1426 JCExpression t = toP(F.at(S.pos()).Ident(ident())); 1427 if (S.token() == LT) { 1428 int oldmode = mode; 1429 checkGenerics(); 1430 t = typeArguments(t, true); 1431 mode = oldmode; 1432 } 1433 return classCreatorRest(newpos, encl, typeArgs, t); 1434 } 1435 1436 /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer 1437 * | Expression "]" {"[" Expression "]"} BracketsOpt ) 1438 */ 1439 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { 1440 accept(LBRACKET); 1441 if (S.token() == RBRACKET) { 1442 accept(RBRACKET); 1443 elemtype = bracketsOpt(elemtype); 1444 if (S.token() == LBRACE) { 1445 return arrayInitializer(newpos, elemtype); 1446 } else { 1447 return syntaxError(S.pos(), "array.dimension.missing"); 1448 } 1449 } else { 1450 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>(); 1451 dims.append(parseExpression()); 1452 accept(RBRACKET); 1453 while (S.token() == LBRACKET) { 1454 int pos = S.pos(); 1455 S.nextToken(); 1456 if (S.token() == RBRACKET) { 1457 elemtype = bracketsOptCont(elemtype, pos); 1458 } else { 1459 dims.append(parseExpression()); 1460 accept(RBRACKET); 1461 } 1462 } 1463 return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); 1464 } 1465 } 1466 1467 /** ClassCreatorRest = Arguments [ClassBody] 1468 */ 1469 JCNewClass classCreatorRest(int newpos, 1470 JCExpression encl, 1471 List<JCExpression> typeArgs, 1472 JCExpression t) 1473 { 1474 List<JCExpression> args = arguments(); 1475 JCClassDecl body = null; 1476 if (S.token() == LBRACE) { 1477 int pos = S.pos(); 1478 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 1479 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 1480 body = toP(F.at(pos).AnonymousClassDef(mods, defs)); 1481 } 1482 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); 1483 } 1484 1485 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" 1486 */ 1487 JCExpression arrayInitializer(int newpos, JCExpression t) { 1488 accept(LBRACE); 1489 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>(); 1490 if (S.token() == COMMA) { 1491 S.nextToken(); 1492 } else if (S.token() != RBRACE) { 1493 elems.append(variableInitializer()); 1494 while (S.token() == COMMA) { 1495 S.nextToken(); 1496 if (S.token() == RBRACE) break; 1497 elems.append(variableInitializer()); 1498 } 1499 } 1500 accept(RBRACE); 1501 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList())); 1502 } 1503 1504 /** VariableInitializer = ArrayInitializer | Expression 1505 */ 1506 public JCExpression variableInitializer() { 1507 return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression(); 1508 } 1509 1510 /** ParExpression = "(" Expression ")" 1511 */ 1512 JCExpression parExpression() { 1513 accept(LPAREN); 1514 JCExpression t = parseExpression(); 1515 accept(RPAREN); 1516 return t; 1517 } 1518 1519 /** Block = "{" BlockStatements "}" 1520 */ 1521 JCBlock block(int pos, long flags) { 1522 accept(LBRACE); 1523 List<JCStatement> stats = blockStatements(); 1524 JCBlock t = F.at(pos).Block(flags, stats); 1525 while (S.token() == CASE || S.token() == DEFAULT) { 1526 syntaxError("orphaned", S.token()); 1527 switchBlockStatementGroups(); 1528 } 1529 // the Block node has a field "endpos" for first char of last token, which is 1530 // usually but not necessarily the last char of the last token. 1531 t.endpos = S.pos(); 1532 accept(RBRACE); 1533 return toP(t); 1534 } 1535 1536 public JCBlock block() { 1537 return block(S.pos(), 0); 1538 } 1539 1540 /** BlockStatements = { BlockStatement } 1541 * BlockStatement = LocalVariableDeclarationStatement 1542 * | ClassOrInterfaceOrEnumDeclaration 1543 * | [Ident ":"] Statement 1544 * LocalVariableDeclarationStatement 1545 * = { FINAL | '@' Annotation } Type VariableDeclarators ";" 1546 */ 1547 @SuppressWarnings("fallthrough") 1548 List<JCStatement> blockStatements() { 1549 //todo: skip to anchor on error(?) 1550 int lastErrPos = -1; 1551 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); 1552 while (true) { 1553 int pos = S.pos(); 1554 switch (S.token()) { 1555 case RBRACE: case CASE: case DEFAULT: case EOF: 1556 return stats.toList(); 1557 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: 1558 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: 1559 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: 1560 stats.append(parseStatement()); 1561 break; 1562 case MONKEYS_AT: 1563 case FINAL: { 1564 String dc = S.docComment(); 1565 JCModifiers mods = modifiersOpt(); 1566 if (S.token() == INTERFACE || 1567 S.token() == CLASS || 1568 allowEnums && S.token() == ENUM) { 1569 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); 1570 } else { 1571 JCExpression t = parseType(); 1572 stats.appendList(variableDeclarators(mods, t, 1573 new ListBuffer<JCStatement>())); 1574 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 1575 storeEnd(stats.elems.last(), S.endPos()); 1576 accept(SEMI); 1577 } 1578 break; 1579 } 1580 case ABSTRACT: case STRICTFP: { 1581 String dc = S.docComment(); 1582 JCModifiers mods = modifiersOpt(); 1583 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); 1584 break; 1585 } 1586 case INTERFACE: 1587 case CLASS: 1588 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), 1589 S.docComment())); 1590 break; 1591 case ENUM: 1592 case ASSERT: 1593 if (allowEnums && S.token() == ENUM) { 1594 error(S.pos(), "local.enum"); 1595 stats. 1596 append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), 1597 S.docComment())); 1598 break; 1599 } else if (allowAsserts && S.token() == ASSERT) { 1600 stats.append(parseStatement()); 1601 break; 1602 } 1603 /* fall through to default */ 1604 default: 1605 Name name = S.name(); 1606 JCExpression t = term(EXPR | TYPE); 1607 if (S.token() == COLON && t.getTag() == JCTree.IDENT) { 1608 S.nextToken(); 1609 JCStatement stat = parseStatement(); 1610 stats.append(F.at(pos).Labelled(name, stat)); 1611 } else if ((lastmode & TYPE) != 0 && 1612 (S.token() == IDENTIFIER || 1613 S.token() == ASSERT || 1614 S.token() == ENUM)) { 1615 pos = S.pos(); 1616 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 1617 F.at(pos); 1618 stats.appendList(variableDeclarators(mods, t, 1619 new ListBuffer<JCStatement>())); 1620 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 1621 storeEnd(stats.elems.last(), S.endPos()); 1622 accept(SEMI); 1623 } else { 1624 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 1625 stats.append(to(F.at(pos).Exec(checkExprStat(t)))); 1626 accept(SEMI); 1627 } 1628 } 1629 1630 // error recovery 1631 if (S.pos() == lastErrPos) 1632 return stats.toList(); 1633 if (S.pos() <= errorEndPos) { 1634 skip(false, true, true, true); 1635 lastErrPos = S.pos(); 1636 } 1637 1638 // ensure no dangling /** @deprecated */ active 1639 S.resetDeprecatedFlag(); 1640 } 1641 } 1642 1643 /** Statement = 1644 * Block 1645 * | IF ParExpression Statement [ELSE Statement] 1646 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement 1647 * | FOR "(" FormalParameter : Expression ")" Statement 1648 * | WHILE ParExpression Statement 1649 * | DO Statement WHILE ParExpression ";" 1650 * | TRY Block ( Catches | [Catches] FinallyPart ) 1651 * | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart] 1652 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" 1653 * | SYNCHRONIZED ParExpression Block 1654 * | RETURN [Expression] ";" 1655 * | THROW Expression ";" 1656 * | BREAK [Ident] ";" 1657 * | CONTINUE [Ident] ";" 1658 * | ASSERT Expression [ ":" Expression ] ";" 1659 * | ";" 1660 * | ExpressionStatement 1661 * | Ident ":" Statement 1662 */ 1663 @SuppressWarnings("fallthrough") 1664 public JCStatement parseStatement() { 1665 int pos = S.pos(); 1666 switch (S.token()) { 1667 case LBRACE: 1668 return block(); 1669 case IF: { 1670 S.nextToken(); 1671 JCExpression cond = parExpression(); 1672 JCStatement thenpart = parseStatement(); 1673 JCStatement elsepart = null; 1674 if (S.token() == ELSE) { 1675 S.nextToken(); 1676 elsepart = parseStatement(); 1677 } 1678 return F.at(pos).If(cond, thenpart, elsepart); 1679 } 1680 case FOR: { 1681 S.nextToken(); 1682 accept(LPAREN); 1683 List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit(); 1684 if (inits.length() == 1 && 1685 inits.head.getTag() == JCTree.VARDEF && 1686 ((JCVariableDecl) inits.head).init == null && 1687 S.token() == COLON) { 1688 checkForeach(); 1689 JCVariableDecl var = (JCVariableDecl)inits.head; 1690 accept(COLON); 1691 JCExpression expr = parseExpression(); 1692 accept(RPAREN); 1693 JCStatement body = parseStatement(); 1694 return F.at(pos).ForeachLoop(var, expr, body); 1695 } else { 1696 accept(SEMI); 1697 JCExpression cond = S.token() == SEMI ? null : parseExpression(); 1698 accept(SEMI); 1699 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); 1700 accept(RPAREN); 1701 JCStatement body = parseStatement(); 1702 return F.at(pos).ForLoop(inits, cond, steps, body); 1703 } 1704 } 1705 case WHILE: { 1706 S.nextToken(); 1707 JCExpression cond = parExpression(); 1708 JCStatement body = parseStatement(); 1709 return F.at(pos).WhileLoop(cond, body); 1710 } 1711 case DO: { 1712 S.nextToken(); 1713 JCStatement body = parseStatement(); 1714 accept(WHILE); 1715 JCExpression cond = parExpression(); 1716 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond)); 1717 accept(SEMI); 1718 return t; 1719 } 1720 case TRY: { 1721 S.nextToken(); 1722 List<JCTree> resources = List.<JCTree>nil(); 1723 if (S.token() == LPAREN) { 1724 checkTryWithResources(); 1725 S.nextToken(); 1726 resources = resources(); 1727 accept(RPAREN); 1728 } 1729 JCBlock body = block(); 1730 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>(); 1731 JCBlock finalizer = null; 1732 if (S.token() == CATCH || S.token() == FINALLY) { 1733 while (S.token() == CATCH) catchers.append(catchClause()); 1734 if (S.token() == FINALLY) { 1735 S.nextToken(); 1736 finalizer = block(); 1737 } 1738 } else { 1739 if (allowTWR) { 1740 if (resources.isEmpty()) 1741 error(pos, "try.without.catch.finally.or.resource.decls"); 1742 } else 1743 error(pos, "try.without.catch.or.finally"); 1744 } 1745 return F.at(pos).Try(resources, body, catchers.toList(), finalizer); 1746 } 1747 case SWITCH: { 1748 S.nextToken(); 1749 JCExpression selector = parExpression(); 1750 accept(LBRACE); 1751 List<JCCase> cases = switchBlockStatementGroups(); 1752 JCSwitch t = to(F.at(pos).Switch(selector, cases)); 1753 accept(RBRACE); 1754 return t; 1755 } 1756 case SYNCHRONIZED: { 1757 S.nextToken(); 1758 JCExpression lock = parExpression(); 1759 JCBlock body = block(); 1760 return F.at(pos).Synchronized(lock, body); 1761 } 1762 case RETURN: { 1763 S.nextToken(); 1764 JCExpression result = S.token() == SEMI ? null : parseExpression(); 1765 JCReturn t = to(F.at(pos).Return(result)); 1766 accept(SEMI); 1767 return t; 1768 } 1769 case THROW: { 1770 S.nextToken(); 1771 JCExpression exc = parseExpression(); 1772 JCThrow t = to(F.at(pos).Throw(exc)); 1773 accept(SEMI); 1774 return t; 1775 } 1776 case BREAK: { 1777 S.nextToken(); 1778 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; 1779 JCBreak t = to(F.at(pos).Break(label)); 1780 accept(SEMI); 1781 return t; 1782 } 1783 case CONTINUE: { 1784 S.nextToken(); 1785 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; 1786 JCContinue t = to(F.at(pos).Continue(label)); 1787 accept(SEMI); 1788 return t; 1789 } 1790 case SEMI: 1791 S.nextToken(); 1792 return toP(F.at(pos).Skip()); 1793 case ELSE: 1794 return toP(F.Exec(syntaxError("else.without.if"))); 1795 case FINALLY: 1796 return toP(F.Exec(syntaxError("finally.without.try"))); 1797 case CATCH: 1798 return toP(F.Exec(syntaxError("catch.without.try"))); 1799 case ASSERT: { 1800 if (allowAsserts && S.token() == ASSERT) { 1801 S.nextToken(); 1802 JCExpression assertion = parseExpression(); 1803 JCExpression message = null; 1804 if (S.token() == COLON) { 1805 S.nextToken(); 1806 message = parseExpression(); 1807 } 1808 JCAssert t = to(F.at(pos).Assert(assertion, message)); 1809 accept(SEMI); 1810 return t; 1811 } 1812 /* else fall through to default case */ 1813 } 1814 case ENUM: 1815 default: 1816 Name name = S.name(); 1817 JCExpression expr = parseExpression(); 1818 if (S.token() == COLON && expr.getTag() == JCTree.IDENT) { 1819 S.nextToken(); 1820 JCStatement stat = parseStatement(); 1821 return F.at(pos).Labelled(name, stat); 1822 } else { 1823 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 1824 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr))); 1825 accept(SEMI); 1826 return stat; 1827 } 1828 } 1829 } 1830 1831 /** CatchClause = CATCH "(" FormalParameter ")" Block 1832 */ 1833 JCCatch catchClause() { 1834 int pos = S.pos(); 1835 accept(CATCH); 1836 accept(LPAREN); 1837 JCModifiers mods = optFinal(Flags.PARAMETER); 1838 List<JCExpression> catchTypes = catchTypes(); 1839 JCExpression paramType = catchTypes.size() > 1 ? 1840 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) : 1841 catchTypes.head; 1842 JCVariableDecl formal = variableDeclaratorId(mods, paramType); 1843 accept(RPAREN); 1844 JCBlock body = block(); 1845 return F.at(pos).Catch(formal, body); 1846 } 1847 1848 List<JCExpression> catchTypes() { 1849 ListBuffer<JCExpression> catchTypes = ListBuffer.lb(); 1850 catchTypes.add(parseType()); 1851 while (S.token() == BAR) { 1852 checkMulticatch(); 1853 S.nextToken(); 1854 catchTypes.add(qualident()); 1855 } 1856 return catchTypes.toList(); 1857 } 1858 1859 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup } 1860 * SwitchBlockStatementGroup = SwitchLabel BlockStatements 1861 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" 1862 */ 1863 List<JCCase> switchBlockStatementGroups() { 1864 ListBuffer<JCCase> cases = new ListBuffer<JCCase>(); 1865 while (true) { 1866 int pos = S.pos(); 1867 switch (S.token()) { 1868 case CASE: { 1869 S.nextToken(); 1870 JCExpression pat = parseExpression(); 1871 accept(COLON); 1872 List<JCStatement> stats = blockStatements(); 1873 JCCase c = F.at(pos).Case(pat, stats); 1874 if (stats.isEmpty()) 1875 storeEnd(c, S.prevEndPos()); 1876 cases.append(c); 1877 break; 1878 } 1879 case DEFAULT: { 1880 S.nextToken(); 1881 accept(COLON); 1882 List<JCStatement> stats = blockStatements(); 1883 JCCase c = F.at(pos).Case(null, stats); 1884 if (stats.isEmpty()) 1885 storeEnd(c, S.prevEndPos()); 1886 cases.append(c); 1887 break; 1888 } 1889 case RBRACE: case EOF: 1890 return cases.toList(); 1891 default: 1892 S.nextToken(); // to ensure progress 1893 syntaxError(pos, "expected3", 1894 CASE, DEFAULT, RBRACE); 1895 } 1896 } 1897 } 1898 1899 /** MoreStatementExpressions = { COMMA StatementExpression } 1900 */ 1901 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos, 1902 JCExpression first, 1903 T stats) { 1904 // This Exec is a "StatementExpression"; it subsumes no terminating token 1905 stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); 1906 while (S.token() == COMMA) { 1907 S.nextToken(); 1908 pos = S.pos(); 1909 JCExpression t = parseExpression(); 1910 // This Exec is a "StatementExpression"; it subsumes no terminating token 1911 stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); 1912 } 1913 return stats; 1914 } 1915 1916 /** ForInit = StatementExpression MoreStatementExpressions 1917 * | { FINAL | '@' Annotation } Type VariableDeclarators 1918 */ 1919 List<JCStatement> forInit() { 1920 ListBuffer<JCStatement> stats = lb(); 1921 int pos = S.pos(); 1922 if (S.token() == FINAL || S.token() == MONKEYS_AT) { 1923 return variableDeclarators(optFinal(0), parseType(), stats).toList(); 1924 } else { 1925 JCExpression t = term(EXPR | TYPE); 1926 if ((lastmode & TYPE) != 0 && 1927 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM)) 1928 return variableDeclarators(modifiersOpt(), t, stats).toList(); 1929 else 1930 return moreStatementExpressions(pos, t, stats).toList(); 1931 } 1932 } 1933 1934 /** ForUpdate = StatementExpression MoreStatementExpressions 1935 */ 1936 List<JCExpressionStatement> forUpdate() { 1937 return moreStatementExpressions(S.pos(), 1938 parseExpression(), 1939 new ListBuffer<JCExpressionStatement>()).toList(); 1940 } 1941 1942 /** AnnotationsOpt = { '@' Annotation } 1943 */ 1944 List<JCAnnotation> annotationsOpt() { 1945 if (S.token() != MONKEYS_AT) return List.nil(); // optimization 1946 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>(); 1947 while (S.token() == MONKEYS_AT) { 1948 int pos = S.pos(); 1949 S.nextToken(); 1950 buf.append(annotation(pos)); 1951 } 1952 return buf.toList(); 1953 } 1954 1955 /** ModifiersOpt = { Modifier } 1956 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL 1957 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" 1958 * | "@" Annotation 1959 */ 1960 JCModifiers modifiersOpt() { 1961 return modifiersOpt(null); 1962 } 1963 JCModifiers modifiersOpt(JCModifiers partial) { 1964 long flags; 1965 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>(); 1966 int pos; 1967 if (partial == null) { 1968 flags = 0; 1969 pos = S.pos(); 1970 } else { 1971 flags = partial.flags; 1972 annotations.appendList(partial.annotations); 1973 pos = partial.pos; 1974 } 1975 if (S.deprecatedFlag()) { 1976 flags |= Flags.DEPRECATED; 1977 S.resetDeprecatedFlag(); 1978 } 1979 int lastPos = Position.NOPOS; 1980 loop: 1981 while (true) { 1982 long flag; 1983 switch (S.token()) { 1984 case PRIVATE : flag = Flags.PRIVATE; break; 1985 case PROTECTED : flag = Flags.PROTECTED; break; 1986 case PUBLIC : flag = Flags.PUBLIC; break; 1987 case STATIC : flag = Flags.STATIC; break; 1988 case TRANSIENT : flag = Flags.TRANSIENT; break; 1989 case FINAL : flag = Flags.FINAL; break; 1990 case ABSTRACT : flag = Flags.ABSTRACT; break; 1991 case NATIVE : flag = Flags.NATIVE; break; 1992 case VOLATILE : flag = Flags.VOLATILE; break; 1993 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; 1994 case STRICTFP : flag = Flags.STRICTFP; break; 1995 case MONKEYS_AT : flag = Flags.ANNOTATION; break; 1996 default: break loop; 1997 } 1998 if ((flags & flag) != 0) error(S.pos(), "repeated.modifier"); 1999 lastPos = S.pos(); 2000 S.nextToken(); 2001 if (flag == Flags.ANNOTATION) { 2002 checkAnnotations(); 2003 if (S.token() != INTERFACE) { 2004 JCAnnotation ann = annotation(lastPos); 2005 // if first modifier is an annotation, set pos to annotation's. 2006 if (flags == 0 && annotations.isEmpty()) 2007 pos = ann.pos; 2008 annotations.append(ann); 2009 lastPos = ann.pos; 2010 flag = 0; 2011 } 2012 } 2013 flags |= flag; 2014 } 2015 switch (S.token()) { 2016 case ENUM: flags |= Flags.ENUM; break; 2017 case INTERFACE: flags |= Flags.INTERFACE; break; 2018 default: break; 2019 } 2020 2021 /* A modifiers tree with no modifier tokens or annotations 2022 * has no text position. */ 2023 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty()) 2024 pos = Position.NOPOS; 2025 2026 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); 2027 if (pos != Position.NOPOS) 2028 storeEnd(mods, S.prevEndPos()); 2029 return mods; 2030 } 2031 2032 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] 2033 * @param pos position of "@" token 2034 */ 2035 JCAnnotation annotation(int pos) { 2036 // accept(AT); // AT consumed by caller 2037 checkAnnotations(); 2038 JCTree ident = qualident(); 2039 List<JCExpression> fieldValues = annotationFieldValuesOpt(); 2040 JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); 2041 storeEnd(ann, S.prevEndPos()); 2042 return ann; 2043 } 2044 2045 List<JCExpression> annotationFieldValuesOpt() { 2046 return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil(); 2047 } 2048 2049 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ 2050 List<JCExpression> annotationFieldValues() { 2051 accept(LPAREN); 2052 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 2053 if (S.token() != RPAREN) { 2054 buf.append(annotationFieldValue()); 2055 while (S.token() == COMMA) { 2056 S.nextToken(); 2057 buf.append(annotationFieldValue()); 2058 } 2059 } 2060 accept(RPAREN); 2061 return buf.toList(); 2062 } 2063 2064 /** AnnotationFieldValue = AnnotationValue 2065 * | Identifier "=" AnnotationValue 2066 */ 2067 JCExpression annotationFieldValue() { 2068 if (S.token() == IDENTIFIER) { 2069 mode = EXPR; 2070 JCExpression t1 = term1(); 2071 if (t1.getTag() == JCTree.IDENT && S.token() == EQ) { 2072 int pos = S.pos(); 2073 accept(EQ); 2074 JCExpression v = annotationValue(); 2075 return toP(F.at(pos).Assign(t1, v)); 2076 } else { 2077 return t1; 2078 } 2079 } 2080 return annotationValue(); 2081 } 2082 2083 /* AnnotationValue = ConditionalExpression 2084 * | Annotation 2085 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}" 2086 */ 2087 JCExpression annotationValue() { 2088 int pos; 2089 switch (S.token()) { 2090 case MONKEYS_AT: 2091 pos = S.pos(); 2092 S.nextToken(); 2093 return annotation(pos); 2094 case LBRACE: 2095 pos = S.pos(); 2096 accept(LBRACE); 2097 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 2098 if (S.token() != RBRACE) { 2099 buf.append(annotationValue()); 2100 while (S.token() == COMMA) { 2101 S.nextToken(); 2102 if (S.token() == RBRACE) break; 2103 buf.append(annotationValue()); 2104 } 2105 } 2106 accept(RBRACE); 2107 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList())); 2108 default: 2109 mode = EXPR; 2110 return term1(); 2111 } 2112 } 2113 2114 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator } 2115 */ 2116 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods, 2117 JCExpression type, 2118 T vdefs) 2119 { 2120 return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs); 2121 } 2122 2123 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } 2124 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } 2125 * 2126 * @param reqInit Is an initializer always required? 2127 * @param dc The documentation comment for the variable declarations, or null. 2128 */ 2129 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos, 2130 JCModifiers mods, 2131 JCExpression type, 2132 Name name, 2133 boolean reqInit, 2134 String dc, 2135 T vdefs) 2136 { 2137 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); 2138 while (S.token() == COMMA) { 2139 // All but last of multiple declarators subsume a comma 2140 storeEnd((JCTree)vdefs.elems.last(), S.endPos()); 2141 S.nextToken(); 2142 vdefs.append(variableDeclarator(mods, type, reqInit, dc)); 2143 } 2144 return vdefs; 2145 } 2146 2147 /** VariableDeclarator = Ident VariableDeclaratorRest 2148 * ConstantDeclarator = Ident ConstantDeclaratorRest 2149 */ 2150 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) { 2151 return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc); 2152 } 2153 2154 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] 2155 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer 2156 * 2157 * @param reqInit Is an initializer always required? 2158 * @param dc The documentation comment for the variable declarations, or null. 2159 */ 2160 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, 2161 boolean reqInit, String dc) { 2162 type = bracketsOpt(type); 2163 JCExpression init = null; 2164 if (S.token() == EQ) { 2165 S.nextToken(); 2166 init = variableInitializer(); 2167 } 2168 else if (reqInit) syntaxError(S.pos(), "expected", EQ); 2169 JCVariableDecl result = 2170 toP(F.at(pos).VarDef(mods, name, type, init)); 2171 attach(result, dc); 2172 return result; 2173 } 2174 2175 /** VariableDeclaratorId = Ident BracketsOpt 2176 */ 2177 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { 2178 int pos = S.pos(); 2179 Name name = ident(); 2180 if ((mods.flags & Flags.VARARGS) != 0 && 2181 S.token() == LBRACKET) { 2182 log.error(S.pos(), "varargs.and.old.array.syntax"); 2183 } 2184 type = bracketsOpt(type); 2185 return toP(F.at(pos).VarDef(mods, name, type, null)); 2186 } 2187 2188 /** Resources = Resource { ";" Resources } 2189 */ 2190 List<JCTree> resources() { 2191 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2192 defs.append(resource()); 2193 while (S.token() == SEMI) { 2194 // All but last of multiple declarators must subsume a semicolon 2195 storeEnd(defs.elems.last(), S.endPos()); 2196 int semiColonPos = S.pos(); 2197 S.nextToken(); 2198 if (S.token() == RPAREN) { // Optional trailing semicolon 2199 // after last resource 2200 break; 2201 } 2202 defs.append(resource()); 2203 } 2204 return defs.toList(); 2205 } 2206 2207 /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression 2208 */ 2209 JCTree resource() { 2210 return variableDeclaratorRest(S.pos(), optFinal(Flags.FINAL), 2211 parseType(), ident(), true, null); 2212 } 2213 2214 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} 2215 */ 2216 public JCTree.JCCompilationUnit parseCompilationUnit() { 2217 int pos = S.pos(); 2218 JCExpression pid = null; 2219 String dc = S.docComment(); 2220 JCModifiers mods = null; 2221 List<JCAnnotation> packageAnnotations = List.nil(); 2222 if (S.token() == MONKEYS_AT) 2223 mods = modifiersOpt(); 2224 2225 if (S.token() == PACKAGE) { 2226 if (mods != null) { 2227 checkNoMods(mods.flags); 2228 packageAnnotations = mods.annotations; 2229 mods = null; 2230 } 2231 S.nextToken(); 2232 pid = qualident(); 2233 accept(SEMI); 2234 } 2235 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2236 boolean checkForImports = true; 2237 while (S.token() != EOF) { 2238 if (S.pos() <= errorEndPos) { 2239 // error recovery 2240 skip(checkForImports, false, false, false); 2241 if (S.token() == EOF) 2242 break; 2243 } 2244 if (checkForImports && mods == null && S.token() == IMPORT) { 2245 defs.append(importDeclaration()); 2246 } else { 2247 JCTree def = typeDeclaration(mods); 2248 if (keepDocComments && dc != null && docComments.get(def) == dc) { 2249 // If the first type declaration has consumed the first doc 2250 // comment, then don't use it for the top level comment as well. 2251 dc = null; 2252 } 2253 if (def instanceof JCExpressionStatement) 2254 def = ((JCExpressionStatement)def).expr; 2255 defs.append(def); 2256 if (def instanceof JCClassDecl) 2257 checkForImports = false; 2258 mods = null; 2259 } 2260 } 2261 JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList()); 2262 attach(toplevel, dc); 2263 if (defs.elems.isEmpty()) 2264 storeEnd(toplevel, S.prevEndPos()); 2265 if (keepDocComments) 2266 toplevel.docComments = docComments; 2267 if (keepLineMap) 2268 toplevel.lineMap = S.getLineMap(); 2269 return toplevel; 2270 } 2271 2272 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" 2273 */ 2274 JCTree importDeclaration() { 2275 int pos = S.pos(); 2276 S.nextToken(); 2277 boolean importStatic = false; 2278 if (S.token() == STATIC) { 2279 checkStaticImports(); 2280 importStatic = true; 2281 S.nextToken(); 2282 } 2283 JCExpression pid = toP(F.at(S.pos()).Ident(ident())); 2284 do { 2285 int pos1 = S.pos(); 2286 accept(DOT); 2287 if (S.token() == STAR) { 2288 pid = to(F.at(pos1).Select(pid, names.asterisk)); 2289 S.nextToken(); 2290 break; 2291 } else { 2292 pid = toP(F.at(pos1).Select(pid, ident())); 2293 } 2294 } while (S.token() == DOT); 2295 accept(SEMI); 2296 return toP(F.at(pos).Import(pid, importStatic)); 2297 } 2298 2299 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration 2300 * | ";" 2301 */ 2302 JCTree typeDeclaration(JCModifiers mods) { 2303 int pos = S.pos(); 2304 if (mods == null && S.token() == SEMI) { 2305 S.nextToken(); 2306 return toP(F.at(pos).Skip()); 2307 } else { 2308 String dc = S.docComment(); 2309 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc); 2310 } 2311 } 2312 2313 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt 2314 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) 2315 * @param mods Any modifiers starting the class or interface declaration 2316 * @param dc The documentation comment for the class, or null. 2317 */ 2318 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) { 2319 if (S.token() == CLASS) { 2320 return classDeclaration(mods, dc); 2321 } else if (S.token() == INTERFACE) { 2322 return interfaceDeclaration(mods, dc); 2323 } else if (allowEnums) { 2324 if (S.token() == ENUM) { 2325 return enumDeclaration(mods, dc); 2326 } else { 2327 int pos = S.pos(); 2328 List<JCTree> errs; 2329 if (S.token() == IDENTIFIER) { 2330 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 2331 setErrorEndPos(S.pos()); 2332 } else { 2333 errs = List.<JCTree>of(mods); 2334 } 2335 return toP(F.Exec(syntaxError(pos, errs, "expected3", 2336 CLASS, INTERFACE, ENUM))); 2337 } 2338 } else { 2339 if (S.token() == ENUM) { 2340 error(S.pos(), "enums.not.supported.in.source", source.name); 2341 allowEnums = true; 2342 return enumDeclaration(mods, dc); 2343 } 2344 int pos = S.pos(); 2345 List<JCTree> errs; 2346 if (S.token() == IDENTIFIER) { 2347 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 2348 setErrorEndPos(S.pos()); 2349 } else { 2350 errs = List.<JCTree>of(mods); 2351 } 2352 return toP(F.Exec(syntaxError(pos, errs, "expected2", 2353 CLASS, INTERFACE))); 2354 } 2355 } 2356 2357 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] 2358 * [IMPLEMENTS TypeList] ClassBody 2359 * @param mods The modifiers starting the class declaration 2360 * @param dc The documentation comment for the class, or null. 2361 */ 2362 JCClassDecl classDeclaration(JCModifiers mods, String dc) { 2363 int pos = S.pos(); 2364 accept(CLASS); 2365 Name name = ident(); 2366 2367 List<JCTypeParameter> typarams = typeParametersOpt(); 2368 2369 JCExpression extending = null; 2370 if (S.token() == EXTENDS) { 2371 S.nextToken(); 2372 extending = parseType(); 2373 } 2374 List<JCExpression> implementing = List.nil(); 2375 if (S.token() == IMPLEMENTS) { 2376 S.nextToken(); 2377 implementing = typeList(); 2378 } 2379 List<JCTree> defs = classOrInterfaceBody(name, false); 2380 JCClassDecl result = toP(F.at(pos).ClassDef( 2381 mods, name, typarams, extending, implementing, defs)); 2382 attach(result, dc); 2383 return result; 2384 } 2385 2386 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt 2387 * [EXTENDS TypeList] InterfaceBody 2388 * @param mods The modifiers starting the interface declaration 2389 * @param dc The documentation comment for the interface, or null. 2390 */ 2391 JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { 2392 int pos = S.pos(); 2393 accept(INTERFACE); 2394 Name name = ident(); 2395 2396 List<JCTypeParameter> typarams = typeParametersOpt(); 2397 2398 List<JCExpression> extending = List.nil(); 2399 if (S.token() == EXTENDS) { 2400 S.nextToken(); 2401 extending = typeList(); 2402 } 2403 List<JCTree> defs = classOrInterfaceBody(name, true); 2404 JCClassDecl result = toP(F.at(pos).ClassDef( 2405 mods, name, typarams, null, extending, defs)); 2406 attach(result, dc); 2407 return result; 2408 } 2409 2410 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody 2411 * @param mods The modifiers starting the enum declaration 2412 * @param dc The documentation comment for the enum, or null. 2413 */ 2414 JCClassDecl enumDeclaration(JCModifiers mods, String dc) { 2415 int pos = S.pos(); 2416 accept(ENUM); 2417 Name name = ident(); 2418 2419 List<JCExpression> implementing = List.nil(); 2420 if (S.token() == IMPLEMENTS) { 2421 S.nextToken(); 2422 implementing = typeList(); 2423 } 2424 2425 List<JCTree> defs = enumBody(name); 2426 mods.flags |= Flags.ENUM; 2427 JCClassDecl result = toP(F.at(pos). 2428 ClassDef(mods, name, List.<JCTypeParameter>nil(), 2429 null, implementing, defs)); 2430 attach(result, dc); 2431 return result; 2432 } 2433 2434 /** EnumBody = "{" { EnumeratorDeclarationList } [","] 2435 * [ ";" {ClassBodyDeclaration} ] "}" 2436 */ 2437 List<JCTree> enumBody(Name enumName) { 2438 accept(LBRACE); 2439 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2440 if (S.token() == COMMA) { 2441 S.nextToken(); 2442 } else if (S.token() != RBRACE && S.token() != SEMI) { 2443 defs.append(enumeratorDeclaration(enumName)); 2444 while (S.token() == COMMA) { 2445 S.nextToken(); 2446 if (S.token() == RBRACE || S.token() == SEMI) break; 2447 defs.append(enumeratorDeclaration(enumName)); 2448 } 2449 if (S.token() != SEMI && S.token() != RBRACE) { 2450 defs.append(syntaxError(S.pos(), "expected3", 2451 COMMA, RBRACE, SEMI)); 2452 S.nextToken(); 2453 } 2454 } 2455 if (S.token() == SEMI) { 2456 S.nextToken(); 2457 while (S.token() != RBRACE && S.token() != EOF) { 2458 defs.appendList(classOrInterfaceBodyDeclaration(enumName, 2459 false)); 2460 if (S.pos() <= errorEndPos) { 2461 // error recovery 2462 skip(false, true, true, false); 2463 } 2464 } 2465 } 2466 accept(RBRACE); 2467 return defs.toList(); 2468 } 2469 2470 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] 2471 */ 2472 JCTree enumeratorDeclaration(Name enumName) { 2473 String dc = S.docComment(); 2474 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; 2475 if (S.deprecatedFlag()) { 2476 flags |= Flags.DEPRECATED; 2477 S.resetDeprecatedFlag(); 2478 } 2479 int pos = S.pos(); 2480 List<JCAnnotation> annotations = annotationsOpt(); 2481 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 2482 List<JCExpression> typeArgs = typeArgumentsOpt(); 2483 int identPos = S.pos(); 2484 Name name = ident(); 2485 int createPos = S.pos(); 2486 List<JCExpression> args = (S.token() == LPAREN) 2487 ? arguments() : List.<JCExpression>nil(); 2488 JCClassDecl body = null; 2489 if (S.token() == LBRACE) { 2490 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); 2491 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 2492 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); 2493 } 2494 if (args.isEmpty() && body == null) 2495 createPos = identPos; 2496 JCIdent ident = F.at(identPos).Ident(enumName); 2497 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); 2498 if (createPos != identPos) 2499 storeEnd(create, S.prevEndPos()); 2500 ident = F.at(identPos).Ident(enumName); 2501 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); 2502 attach(result, dc); 2503 return result; 2504 } 2505 2506 /** TypeList = Type {"," Type} 2507 */ 2508 List<JCExpression> typeList() { 2509 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 2510 ts.append(parseType()); 2511 while (S.token() == COMMA) { 2512 S.nextToken(); 2513 ts.append(parseType()); 2514 } 2515 return ts.toList(); 2516 } 2517 2518 /** ClassBody = "{" {ClassBodyDeclaration} "}" 2519 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" 2520 */ 2521 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 2522 accept(LBRACE); 2523 if (S.pos() <= errorEndPos) { 2524 // error recovery 2525 skip(false, true, false, false); 2526 if (S.token() == LBRACE) 2527 S.nextToken(); 2528 } 2529 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2530 while (S.token() != RBRACE && S.token() != EOF) { 2531 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 2532 if (S.pos() <= errorEndPos) { 2533 // error recovery 2534 skip(false, true, true, false); 2535 } 2536 } 2537 accept(RBRACE); 2538 return defs.toList(); 2539 } 2540 2541 /** ClassBodyDeclaration = 2542 * ";" 2543 * | [STATIC] Block 2544 * | ModifiersOpt 2545 * ( Type Ident 2546 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) 2547 * | VOID Ident MethodDeclaratorRest 2548 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest 2549 * | Ident ConstructorDeclaratorRest 2550 * | TypeParameters Ident ConstructorDeclaratorRest 2551 * | ClassOrInterfaceOrEnumDeclaration 2552 * ) 2553 * InterfaceBodyDeclaration = 2554 * ";" 2555 * | ModifiersOpt Type Ident 2556 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) 2557 */ 2558 List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { 2559 if (S.token() == SEMI) { 2560 S.nextToken(); 2561 return List.<JCTree>nil(); 2562 } else { 2563 String dc = S.docComment(); 2564 int pos = S.pos(); 2565 JCModifiers mods = modifiersOpt(); 2566 if (S.token() == CLASS || 2567 S.token() == INTERFACE || 2568 allowEnums && S.token() == ENUM) { 2569 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 2570 } else if (S.token() == LBRACE && !isInterface && 2571 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && 2572 mods.annotations.isEmpty()) { 2573 return List.<JCTree>of(block(pos, mods.flags)); 2574 } else { 2575 pos = S.pos(); 2576 List<JCTypeParameter> typarams = typeParametersOpt(); 2577 // if there are type parameters but no modifiers, save the start 2578 // position of the method in the modifiers. 2579 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { 2580 mods.pos = pos; 2581 storeEnd(mods, pos); 2582 } 2583 Name name = S.name(); 2584 pos = S.pos(); 2585 JCExpression type; 2586 boolean isVoid = S.token() == VOID; 2587 if (isVoid) { 2588 type = to(F.at(pos).TypeIdent(TypeTags.VOID)); 2589 S.nextToken(); 2590 } else { 2591 type = parseType(); 2592 } 2593 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { 2594 if (isInterface || name != className) 2595 error(pos, "invalid.meth.decl.ret.type.req"); 2596 return List.of(methodDeclaratorRest( 2597 pos, mods, null, names.init, typarams, 2598 isInterface, true, dc)); 2599 } else { 2600 pos = S.pos(); 2601 name = ident(); 2602 if (S.token() == LPAREN) { 2603 return List.of(methodDeclaratorRest( 2604 pos, mods, type, name, typarams, 2605 isInterface, isVoid, dc)); 2606 } else if (!isVoid && typarams.isEmpty()) { 2607 List<JCTree> defs = 2608 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, 2609 new ListBuffer<JCTree>()).toList(); 2610 storeEnd(defs.last(), S.endPos()); 2611 accept(SEMI); 2612 return defs; 2613 } else { 2614 pos = S.pos(); 2615 List<JCTree> err = isVoid 2616 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, 2617 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 2618 : null; 2619 return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN)); 2620 } 2621 } 2622 } 2623 } 2624 } 2625 2626 /** MethodDeclaratorRest = 2627 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 2628 * VoidMethodDeclaratorRest = 2629 * FormalParameters [Throws TypeList] ( MethodBody | ";") 2630 * InterfaceMethodDeclaratorRest = 2631 * FormalParameters BracketsOpt [THROWS TypeList] ";" 2632 * VoidInterfaceMethodDeclaratorRest = 2633 * FormalParameters [THROWS TypeList] ";" 2634 * ConstructorDeclaratorRest = 2635 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody 2636 */ 2637 JCTree methodDeclaratorRest(int pos, 2638 JCModifiers mods, 2639 JCExpression type, 2640 Name name, 2641 List<JCTypeParameter> typarams, 2642 boolean isInterface, boolean isVoid, 2643 String dc) { 2644 List<JCVariableDecl> params = formalParameters(); 2645 if (!isVoid) type = bracketsOpt(type); 2646 List<JCExpression> thrown = List.nil(); 2647 if (S.token() == THROWS) { 2648 S.nextToken(); 2649 thrown = qualidentList(); 2650 } 2651 JCBlock body = null; 2652 JCExpression defaultValue; 2653 if (S.token() == LBRACE) { 2654 body = block(); 2655 defaultValue = null; 2656 } else { 2657 if (S.token() == DEFAULT) { 2658 accept(DEFAULT); 2659 defaultValue = annotationValue(); 2660 } else { 2661 defaultValue = null; 2662 } 2663 accept(SEMI); 2664 if (S.pos() <= errorEndPos) { 2665 // error recovery 2666 skip(false, true, false, false); 2667 if (S.token() == LBRACE) { 2668 body = block(); 2669 } 2670 } 2671 } 2672 2673 JCMethodDecl result = 2674 toP(F.at(pos).MethodDef(mods, name, type, typarams, 2675 params, thrown, 2676 body, defaultValue)); 2677 attach(result, dc); 2678 return result; 2679 } 2680 2681 /** QualidentList = Qualident {"," Qualident} 2682 */ 2683 List<JCExpression> qualidentList() { 2684 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 2685 ts.append(qualident()); 2686 while (S.token() == COMMA) { 2687 S.nextToken(); 2688 ts.append(qualident()); 2689 } 2690 return ts.toList(); 2691 } 2692 2693 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] 2694 */ 2695 List<JCTypeParameter> typeParametersOpt() { 2696 if (S.token() == LT) { 2697 checkGenerics(); 2698 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>(); 2699 S.nextToken(); 2700 typarams.append(typeParameter()); 2701 while (S.token() == COMMA) { 2702 S.nextToken(); 2703 typarams.append(typeParameter()); 2704 } 2705 accept(GT); 2706 return typarams.toList(); 2707 } else { 2708 return List.nil(); 2709 } 2710 } 2711 2712 /** TypeParameter = TypeVariable [TypeParameterBound] 2713 * TypeParameterBound = EXTENDS Type {"&" Type} 2714 * TypeVariable = Ident 2715 */ 2716 JCTypeParameter typeParameter() { 2717 int pos = S.pos(); 2718 Name name = ident(); 2719 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); 2720 if (S.token() == EXTENDS) { 2721 S.nextToken(); 2722 bounds.append(parseType()); 2723 while (S.token() == AMP) { 2724 S.nextToken(); 2725 bounds.append(parseType()); 2726 } 2727 } 2728 return toP(F.at(pos).TypeParameter(name, bounds.toList())); 2729 } 2730 2731 /** FormalParameters = "(" [ FormalParameterList ] ")" 2732 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter 2733 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter 2734 */ 2735 List<JCVariableDecl> formalParameters() { 2736 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); 2737 JCVariableDecl lastParam = null; 2738 accept(LPAREN); 2739 if (S.token() != RPAREN) { 2740 params.append(lastParam = formalParameter()); 2741 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) { 2742 S.nextToken(); 2743 params.append(lastParam = formalParameter()); 2744 } 2745 } 2746 accept(RPAREN); 2747 return params.toList(); 2748 } 2749 2750 JCModifiers optFinal(long flags) { 2751 JCModifiers mods = modifiersOpt(); 2752 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); 2753 mods.flags |= flags; 2754 return mods; 2755 } 2756 2757 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId 2758 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter 2759 */ 2760 JCVariableDecl formalParameter() { 2761 JCModifiers mods = optFinal(Flags.PARAMETER); 2762 JCExpression type = parseType(); 2763 if (S.token() == ELLIPSIS) { 2764 checkVarargs(); 2765 mods.flags |= Flags.VARARGS; 2766 type = to(F.at(S.pos()).TypeArray(type)); 2767 S.nextToken(); 2768 } 2769 return variableDeclaratorId(mods, type); 2770 } 2771 2772 /* ---------- auxiliary methods -------------- */ 2773 2774 void error(int pos, String key, Object ... args) { 2775 log.error(DiagnosticFlag.SYNTAX, pos, key, args); 2776 } 2777 2778 void warning(int pos, String key, Object ... args) { 2779 log.warning(pos, key, args); 2780 } 2781 2782 /** Check that given tree is a legal expression statement. 2783 */ 2784 protected JCExpression checkExprStat(JCExpression t) { 2785 switch(t.getTag()) { 2786 case JCTree.PREINC: case JCTree.PREDEC: 2787 case JCTree.POSTINC: case JCTree.POSTDEC: 2788 case JCTree.ASSIGN: 2789 case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG: 2790 case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG: 2791 case JCTree.PLUS_ASG: case JCTree.MINUS_ASG: 2792 case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG: 2793 case JCTree.APPLY: case JCTree.NEWCLASS: 2794 case JCTree.ERRONEOUS: 2795 return t; 2796 default: 2797 error(t.pos, "not.stmt"); 2798 return F.at(t.pos).Erroneous(List.<JCTree>of(t)); 2799 } 2800 } 2801 2802 /** Return precedence of operator represented by token, 2803 * -1 if token is not a binary operator. @see TreeInfo.opPrec 2804 */ 2805 static int prec(Token token) { 2806 int oc = optag(token); 2807 return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; 2808 } 2809 2810 /** 2811 * Return the lesser of two positions, making allowance for either one 2812 * being unset. 2813 */ 2814 static int earlier(int pos1, int pos2) { 2815 if (pos1 == Position.NOPOS) 2816 return pos2; 2817 if (pos2 == Position.NOPOS) 2818 return pos1; 2819 return (pos1 < pos2 ? pos1 : pos2); 2820 } 2821 2822 /** Return operation tag of binary operator represented by token, 2823 * -1 if token is not a binary operator. 2824 */ 2825 static int optag(Token token) { 2826 switch (token) { 2827 case BARBAR: 2828 return JCTree.OR; 2829 case AMPAMP: 2830 return JCTree.AND; 2831 case BAR: 2832 return JCTree.BITOR; 2833 case BAREQ: 2834 return JCTree.BITOR_ASG; 2835 case CARET: 2836 return JCTree.BITXOR; 2837 case CARETEQ: 2838 return JCTree.BITXOR_ASG; 2839 case AMP: 2840 return JCTree.BITAND; 2841 case AMPEQ: 2842 return JCTree.BITAND_ASG; 2843 case EQEQ: 2844 return JCTree.EQ; 2845 case BANGEQ: 2846 return JCTree.NE; 2847 case LT: 2848 return JCTree.LT; 2849 case GT: 2850 return JCTree.GT; 2851 case LTEQ: 2852 return JCTree.LE; 2853 case GTEQ: 2854 return JCTree.GE; 2855 case LTLT: 2856 return JCTree.SL; 2857 case LTLTEQ: 2858 return JCTree.SL_ASG; 2859 case GTGT: 2860 return JCTree.SR; 2861 case GTGTEQ: 2862 return JCTree.SR_ASG; 2863 case GTGTGT: 2864 return JCTree.USR; 2865 case GTGTGTEQ: 2866 return JCTree.USR_ASG; 2867 case PLUS: 2868 return JCTree.PLUS; 2869 case PLUSEQ: 2870 return JCTree.PLUS_ASG; 2871 case SUB: 2872 return JCTree.MINUS; 2873 case SUBEQ: 2874 return JCTree.MINUS_ASG; 2875 case STAR: 2876 return JCTree.MUL; 2877 case STAREQ: 2878 return JCTree.MUL_ASG; 2879 case SLASH: 2880 return JCTree.DIV; 2881 case SLASHEQ: 2882 return JCTree.DIV_ASG; 2883 case PERCENT: 2884 return JCTree.MOD; 2885 case PERCENTEQ: 2886 return JCTree.MOD_ASG; 2887 case INSTANCEOF: 2888 return JCTree.TYPETEST; 2889 default: 2890 return -1; 2891 } 2892 } 2893 2894 /** Return operation tag of unary operator represented by token, 2895 * -1 if token is not a binary operator. 2896 */ 2897 static int unoptag(Token token) { 2898 switch (token) { 2899 case PLUS: 2900 return JCTree.POS; 2901 case SUB: 2902 return JCTree.NEG; 2903 case BANG: 2904 return JCTree.NOT; 2905 case TILDE: 2906 return JCTree.COMPL; 2907 case PLUSPLUS: 2908 return JCTree.PREINC; 2909 case SUBSUB: 2910 return JCTree.PREDEC; 2911 default: 2912 return -1; 2913 } 2914 } 2915 2916 /** Return type tag of basic type represented by token, 2917 * -1 if token is not a basic type identifier. 2918 */ 2919 static int typetag(Token token) { 2920 switch (token) { 2921 case BYTE: 2922 return TypeTags.BYTE; 2923 case CHAR: 2924 return TypeTags.CHAR; 2925 case SHORT: 2926 return TypeTags.SHORT; 2927 case INT: 2928 return TypeTags.INT; 2929 case LONG: 2930 return TypeTags.LONG; 2931 case FLOAT: 2932 return TypeTags.FLOAT; 2933 case DOUBLE: 2934 return TypeTags.DOUBLE; 2935 case BOOLEAN: 2936 return TypeTags.BOOLEAN; 2937 default: 2938 return -1; 2939 } 2940 } 2941 2942 void checkGenerics() { 2943 if (!allowGenerics) { 2944 error(S.pos(), "generics.not.supported.in.source", source.name); 2945 allowGenerics = true; 2946 } 2947 } 2948 void checkVarargs() { 2949 if (!allowVarargs) { 2950 error(S.pos(), "varargs.not.supported.in.source", source.name); 2951 allowVarargs = true; 2952 } 2953 } 2954 void checkForeach() { 2955 if (!allowForeach) { 2956 error(S.pos(), "foreach.not.supported.in.source", source.name); 2957 allowForeach = true; 2958 } 2959 } 2960 void checkStaticImports() { 2961 if (!allowStaticImport) { 2962 error(S.pos(), "static.import.not.supported.in.source", source.name); 2963 allowStaticImport = true; 2964 } 2965 } 2966 void checkAnnotations() { 2967 if (!allowAnnotations) { 2968 error(S.pos(), "annotations.not.supported.in.source", source.name); 2969 allowAnnotations = true; 2970 } 2971 } 2972 void checkDiamond() { 2973 if (!allowDiamond) { 2974 error(S.pos(), "diamond.not.supported.in.source", source.name); 2975 allowDiamond = true; 2976 } 2977 } 2978 void checkMulticatch() { 2979 if (!allowMulticatch) { 2980 error(S.pos(), "multicatch.not.supported.in.source", source.name); 2981 allowMulticatch = true; 2982 } 2983 } 2984 void checkTryWithResources() { 2985 if (!allowTWR) { 2986 error(S.pos(), "try.with.resources.not.supported.in.source", source.name); 2987 allowTWR = true; 2988 } 2989 } 2990 }