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