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