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 * | TRY "(" ResourceSpecification ")" Block [Catches] [FinallyPart] 1851 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" 1852 * | SYNCHRONIZED ParExpression Block 1853 * | RETURN [Expression] ";" 1854 * | THROW Expression ";" 1855 * | BREAK [Ident] ";" 1856 * | CONTINUE [Ident] ";" 1857 * | ASSERT Expression [ ":" Expression ] ";" 1858 * | ";" 1859 * | ExpressionStatement 1860 * | Ident ":" Statement 1861 */ 1862 @SuppressWarnings("fallthrough") 1863 public JCStatement parseStatement() { 1864 int pos = S.pos(); 1865 switch (S.token()) { 1866 case LBRACE: 1867 return block(); 1868 case IF: { 1869 S.nextToken(); 1870 JCExpression cond = parExpression(); 1871 JCStatement thenpart = parseStatement(); 1872 JCStatement elsepart = null; 1873 if (S.token() == ELSE) { 1874 S.nextToken(); 1875 elsepart = parseStatement(); 1876 } 1877 return F.at(pos).If(cond, thenpart, elsepart); 1878 } 1879 case FOR: { 1880 S.nextToken(); 1881 accept(LPAREN); 1882 List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit(); 1883 if (inits.length() == 1 && 1884 inits.head.getTag() == JCTree.VARDEF && 1885 ((JCVariableDecl) inits.head).init == null && 1886 S.token() == COLON) { 1887 checkForeach(); 1888 JCVariableDecl var = (JCVariableDecl)inits.head; 1889 accept(COLON); 1890 JCExpression expr = parseExpression(); 1891 accept(RPAREN); 1892 JCStatement body = parseStatement(); 1893 return F.at(pos).ForeachLoop(var, expr, body); 1894 } else { 1895 accept(SEMI); 1896 JCExpression cond = S.token() == SEMI ? null : parseExpression(); 1897 accept(SEMI); 1898 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); 1899 accept(RPAREN); 1900 JCStatement body = parseStatement(); 1901 return F.at(pos).ForLoop(inits, cond, steps, body); 1902 } 1903 } 1904 case WHILE: { 1905 S.nextToken(); 1906 JCExpression cond = parExpression(); 1907 JCStatement body = parseStatement(); 1908 return F.at(pos).WhileLoop(cond, body); 1909 } 1910 case DO: { 1911 S.nextToken(); 1912 JCStatement body = parseStatement(); 1913 accept(WHILE); 1914 JCExpression cond = parExpression(); 1915 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond)); 1916 accept(SEMI); 1917 return t; 1918 } 1919 case TRY: { 1920 S.nextToken(); 1921 List<JCTree> resources = List.<JCTree>nil(); 1922 if (S.token() == LPAREN) { 1923 checkAutomaticResourceManagement(); 1924 S.nextToken(); 1925 resources = resourceDeclarators(); 1926 accept(RPAREN); 1927 } 1928 JCBlock body = block(); 1929 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>(); 1930 JCBlock finalizer = null; 1931 if (S.token() == CATCH || S.token() == FINALLY) { 1932 while (S.token() == CATCH) catchers.append(catchClause()); 1933 if (S.token() == FINALLY) { 1934 S.nextToken(); 1935 finalizer = block(); 1936 } 1937 } else { 1938 if (allowARM) { 1939 if (resources.isEmpty()) 1940 log.error(pos, "try.without.catch.finally.or.resource.decls"); 1941 } else 1942 log.error(pos, "try.without.catch.or.finally"); 1943 } 1944 return F.at(pos).Try(body, catchers.toList(), finalizer, resources); 1945 } 1946 case SWITCH: { 1947 S.nextToken(); 1948 JCExpression selector = parExpression(); 1949 accept(LBRACE); 1950 List<JCCase> cases = switchBlockStatementGroups(); 1951 JCSwitch t = to(F.at(pos).Switch(selector, cases)); 1952 accept(RBRACE); 1953 return t; 1954 } 1955 case SYNCHRONIZED: { 1956 S.nextToken(); 1957 JCExpression lock = parExpression(); 1958 JCBlock body = block(); 1959 return F.at(pos).Synchronized(lock, body); 1960 } 1961 case RETURN: { 1962 S.nextToken(); 1963 JCExpression result = S.token() == SEMI ? null : parseExpression(); 1964 JCReturn t = to(F.at(pos).Return(result)); 1965 accept(SEMI); 1966 return t; 1967 } 1968 case THROW: { 1969 S.nextToken(); 1970 JCExpression exc = parseExpression(); 1971 JCThrow t = to(F.at(pos).Throw(exc)); 1972 accept(SEMI); 1973 return t; 1974 } 1975 case BREAK: { 1976 S.nextToken(); 1977 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; 1978 JCBreak t = to(F.at(pos).Break(label)); 1979 accept(SEMI); 1980 return t; 1981 } 1982 case CONTINUE: { 1983 S.nextToken(); 1984 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; 1985 JCContinue t = to(F.at(pos).Continue(label)); 1986 accept(SEMI); 1987 return t; 1988 } 1989 case SEMI: 1990 S.nextToken(); 1991 return toP(F.at(pos).Skip()); 1992 case ELSE: 1993 return toP(F.Exec(syntaxError("else.without.if"))); 1994 case FINALLY: 1995 return toP(F.Exec(syntaxError("finally.without.try"))); 1996 case CATCH: 1997 return toP(F.Exec(syntaxError("catch.without.try"))); 1998 case ASSERT: { 1999 if (allowAsserts && S.token() == ASSERT) { 2000 S.nextToken(); 2001 JCExpression assertion = parseExpression(); 2002 JCExpression message = null; 2003 if (S.token() == COLON) { 2004 S.nextToken(); 2005 message = parseExpression(); 2006 } 2007 JCAssert t = to(F.at(pos).Assert(assertion, message)); 2008 accept(SEMI); 2009 return t; 2010 } 2011 /* else fall through to default case */ 2012 } 2013 case ENUM: 2014 default: 2015 Name name = S.name(); 2016 JCExpression expr = parseExpression(); 2017 if (S.token() == COLON && expr.getTag() == JCTree.IDENT) { 2018 S.nextToken(); 2019 JCStatement stat = parseStatement(); 2020 return F.at(pos).Labelled(name, stat); 2021 } else { 2022 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 2023 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr))); 2024 accept(SEMI); 2025 return stat; 2026 } 2027 } 2028 } 2029 2030 /** CatchClause = CATCH "(" FormalParameter ")" Block 2031 */ 2032 JCCatch catchClause() { 2033 int pos = S.pos(); 2034 accept(CATCH); 2035 accept(LPAREN); 2036 JCModifiers mods = optFinal(Flags.PARAMETER); 2037 List<JCExpression> catchTypes = catchTypes(); 2038 JCExpression paramType = catchTypes.size() > 1 ? 2039 toP(F.at(catchTypes.head.getStartPosition()).TypeDisjoint(catchTypes)) : 2040 catchTypes.head; 2041 JCVariableDecl formal = variableDeclaratorId(mods, paramType); 2042 accept(RPAREN); 2043 JCBlock body = block(); 2044 return F.at(pos).Catch(formal, body); 2045 } 2046 2047 List<JCExpression> catchTypes() { 2048 ListBuffer<JCExpression> catchTypes = ListBuffer.lb(); 2049 catchTypes.add(parseType()); 2050 while (S.token() == BAR) { 2051 checkMulticatch(); 2052 S.nextToken(); 2053 catchTypes.add(qualident()); 2054 } 2055 return catchTypes.toList(); 2056 } 2057 2058 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup } 2059 * SwitchBlockStatementGroup = SwitchLabel BlockStatements 2060 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" 2061 */ 2062 List<JCCase> switchBlockStatementGroups() { 2063 ListBuffer<JCCase> cases = new ListBuffer<JCCase>(); 2064 while (true) { 2065 int pos = S.pos(); 2066 switch (S.token()) { 2067 case CASE: { 2068 S.nextToken(); 2069 JCExpression pat = parseExpression(); 2070 accept(COLON); 2071 List<JCStatement> stats = blockStatements(); 2072 JCCase c = F.at(pos).Case(pat, stats); 2073 if (stats.isEmpty()) 2074 storeEnd(c, S.prevEndPos()); 2075 cases.append(c); 2076 break; 2077 } 2078 case DEFAULT: { 2079 S.nextToken(); 2080 accept(COLON); 2081 List<JCStatement> stats = blockStatements(); 2082 JCCase c = F.at(pos).Case(null, stats); 2083 if (stats.isEmpty()) 2084 storeEnd(c, S.prevEndPos()); 2085 cases.append(c); 2086 break; 2087 } 2088 case RBRACE: case EOF: 2089 return cases.toList(); 2090 default: 2091 S.nextToken(); // to ensure progress 2092 syntaxError(pos, "expected3", 2093 CASE, DEFAULT, RBRACE); 2094 } 2095 } 2096 } 2097 2098 /** MoreStatementExpressions = { COMMA StatementExpression } 2099 */ 2100 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos, 2101 JCExpression first, 2102 T stats) { 2103 // This Exec is a "StatementExpression"; it subsumes no terminating token 2104 stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); 2105 while (S.token() == COMMA) { 2106 S.nextToken(); 2107 pos = S.pos(); 2108 JCExpression t = parseExpression(); 2109 // This Exec is a "StatementExpression"; it subsumes no terminating token 2110 stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); 2111 } 2112 return stats; 2113 } 2114 2115 /** ForInit = StatementExpression MoreStatementExpressions 2116 * | { FINAL | '@' Annotation } Type VariableDeclarators 2117 */ 2118 List<JCStatement> forInit() { 2119 ListBuffer<JCStatement> stats = lb(); 2120 int pos = S.pos(); 2121 if (S.token() == FINAL || S.token() == MONKEYS_AT) { 2122 return variableDeclarators(optFinal(0), parseType(), stats).toList(); 2123 } else { 2124 JCExpression t = term(EXPR | TYPE); 2125 if ((lastmode & TYPE) != 0 && 2126 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM)) 2127 return variableDeclarators(modifiersOpt(), t, stats).toList(); 2128 else 2129 return moreStatementExpressions(pos, t, stats).toList(); 2130 } 2131 } 2132 2133 /** ForUpdate = StatementExpression MoreStatementExpressions 2134 */ 2135 List<JCExpressionStatement> forUpdate() { 2136 return moreStatementExpressions(S.pos(), 2137 parseExpression(), 2138 new ListBuffer<JCExpressionStatement>()).toList(); 2139 } 2140 2141 enum AnnotationKind { DEFAULT_ANNO, TYPE_ANNO }; 2142 2143 /** AnnotationsOpt = { '@' Annotation } 2144 */ 2145 List<JCAnnotation> annotationsOpt(AnnotationKind kind) { 2146 if (S.token() != MONKEYS_AT) return List.nil(); // optimization 2147 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>(); 2148 int prevmode = mode; 2149 while (S.token() == MONKEYS_AT) { 2150 int pos = S.pos(); 2151 S.nextToken(); 2152 buf.append(annotation(pos, kind)); 2153 } 2154 lastmode = mode; 2155 mode = prevmode; 2156 List<JCAnnotation> annotations = buf.toList(); 2157 2158 if (debugJSR308 && kind == AnnotationKind.TYPE_ANNO) 2159 System.out.println("TA: parsing " + annotations 2160 + " in " + log.currentSourceFile()); 2161 return annotations; 2162 } 2163 2164 List<JCTypeAnnotation> typeAnnotationsOpt() { 2165 List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.TYPE_ANNO); 2166 return List.convert(JCTypeAnnotation.class, annotations); 2167 } 2168 2169 /** ModifiersOpt = { Modifier } 2170 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL 2171 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" 2172 * | "@" Annotation 2173 */ 2174 JCModifiers modifiersOpt() { 2175 return modifiersOpt(null); 2176 } 2177 JCModifiers modifiersOpt(JCModifiers partial) { 2178 long flags; 2179 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>(); 2180 int pos; 2181 if (partial == null) { 2182 flags = 0; 2183 pos = S.pos(); 2184 } else { 2185 flags = partial.flags; 2186 annotations.appendList(partial.annotations); 2187 pos = partial.pos; 2188 } 2189 if (S.deprecatedFlag()) { 2190 flags |= Flags.DEPRECATED; 2191 S.resetDeprecatedFlag(); 2192 } 2193 int lastPos = Position.NOPOS; 2194 loop: 2195 while (true) { 2196 long flag; 2197 switch (S.token()) { 2198 case PRIVATE : flag = Flags.PRIVATE; break; 2199 case PROTECTED : flag = Flags.PROTECTED; break; 2200 case PUBLIC : flag = Flags.PUBLIC; break; 2201 case STATIC : flag = Flags.STATIC; break; 2202 case TRANSIENT : flag = Flags.TRANSIENT; break; 2203 case FINAL : flag = Flags.FINAL; break; 2204 case ABSTRACT : flag = Flags.ABSTRACT; break; 2205 case NATIVE : flag = Flags.NATIVE; break; 2206 case VOLATILE : flag = Flags.VOLATILE; break; 2207 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; 2208 case STRICTFP : flag = Flags.STRICTFP; break; 2209 case MONKEYS_AT : flag = Flags.ANNOTATION; break; 2210 default: break loop; 2211 } 2212 if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier"); 2213 lastPos = S.pos(); 2214 S.nextToken(); 2215 if (flag == Flags.ANNOTATION) { 2216 checkAnnotations(); 2217 if (S.token() != INTERFACE) { 2218 JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO); 2219 // if first modifier is an annotation, set pos to annotation's. 2220 if (flags == 0 && annotations.isEmpty()) 2221 pos = ann.pos; 2222 annotations.append(ann); 2223 lastPos = ann.pos; 2224 flag = 0; 2225 } 2226 } 2227 flags |= flag; 2228 } 2229 switch (S.token()) { 2230 case ENUM: flags |= Flags.ENUM; break; 2231 case INTERFACE: flags |= Flags.INTERFACE; break; 2232 default: break; 2233 } 2234 2235 /* A modifiers tree with no modifier tokens or annotations 2236 * has no text position. */ 2237 if ((flags & Flags.ModifierFlags) == 0 && annotations.isEmpty()) 2238 pos = Position.NOPOS; 2239 2240 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); 2241 if (pos != Position.NOPOS) 2242 storeEnd(mods, S.prevEndPos()); 2243 return mods; 2244 } 2245 2246 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] 2247 * @param pos position of "@" token 2248 */ 2249 JCAnnotation annotation(int pos, AnnotationKind kind) { 2250 // accept(AT); // AT consumed by caller 2251 checkAnnotations(); 2252 if (kind == AnnotationKind.TYPE_ANNO) 2253 checkTypeAnnotations(); 2254 JCTree ident = qualident(); 2255 List<JCExpression> fieldValues = annotationFieldValuesOpt(); 2256 JCAnnotation ann; 2257 if (kind == AnnotationKind.DEFAULT_ANNO) 2258 ann = F.at(pos).Annotation(ident, fieldValues); 2259 else 2260 ann = F.at(pos).TypeAnnotation(ident, fieldValues); 2261 storeEnd(ann, S.prevEndPos()); 2262 return ann; 2263 } 2264 2265 List<JCExpression> annotationFieldValuesOpt() { 2266 return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil(); 2267 } 2268 2269 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ 2270 List<JCExpression> annotationFieldValues() { 2271 accept(LPAREN); 2272 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 2273 if (S.token() != RPAREN) { 2274 buf.append(annotationFieldValue()); 2275 while (S.token() == COMMA) { 2276 S.nextToken(); 2277 buf.append(annotationFieldValue()); 2278 } 2279 } 2280 accept(RPAREN); 2281 return buf.toList(); 2282 } 2283 2284 /** AnnotationFieldValue = AnnotationValue 2285 * | Identifier "=" AnnotationValue 2286 */ 2287 JCExpression annotationFieldValue() { 2288 if (S.token() == IDENTIFIER) { 2289 mode = EXPR; 2290 JCExpression t1 = term1(); 2291 if (t1.getTag() == JCTree.IDENT && S.token() == EQ) { 2292 int pos = S.pos(); 2293 accept(EQ); 2294 JCExpression v = annotationValue(); 2295 return toP(F.at(pos).Assign(t1, v)); 2296 } else { 2297 return t1; 2298 } 2299 } 2300 return annotationValue(); 2301 } 2302 2303 /* AnnotationValue = ConditionalExpression 2304 * | Annotation 2305 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}" 2306 */ 2307 JCExpression annotationValue() { 2308 int pos; 2309 switch (S.token()) { 2310 case MONKEYS_AT: 2311 pos = S.pos(); 2312 S.nextToken(); 2313 return annotation(pos, AnnotationKind.DEFAULT_ANNO); 2314 case LBRACE: 2315 pos = S.pos(); 2316 accept(LBRACE); 2317 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 2318 if (S.token() != RBRACE) { 2319 buf.append(annotationValue()); 2320 while (S.token() == COMMA) { 2321 S.nextToken(); 2322 if (S.token() == RBRACE) break; 2323 buf.append(annotationValue()); 2324 } 2325 } 2326 accept(RBRACE); 2327 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList())); 2328 default: 2329 mode = EXPR; 2330 return term1(); 2331 } 2332 } 2333 2334 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator } 2335 */ 2336 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods, 2337 JCExpression type, 2338 T vdefs) 2339 { 2340 return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs); 2341 } 2342 2343 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } 2344 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } 2345 * 2346 * @param reqInit Is an initializer always required? 2347 * @param dc The documentation comment for the variable declarations, or null. 2348 */ 2349 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos, 2350 JCModifiers mods, 2351 JCExpression type, 2352 Name name, 2353 boolean reqInit, 2354 String dc, 2355 T vdefs) 2356 { 2357 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); 2358 while (S.token() == COMMA) { 2359 // All but last of multiple declarators subsume a comma 2360 storeEnd((JCTree)vdefs.elems.last(), S.endPos()); 2361 S.nextToken(); 2362 vdefs.append(variableDeclarator(mods, type, reqInit, dc)); 2363 } 2364 return vdefs; 2365 } 2366 2367 /** VariableDeclarator = Ident VariableDeclaratorRest 2368 * ConstantDeclarator = Ident ConstantDeclaratorRest 2369 */ 2370 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) { 2371 return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc); 2372 } 2373 2374 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] 2375 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer 2376 * 2377 * @param reqInit Is an initializer always required? 2378 * @param dc The documentation comment for the variable declarations, or null. 2379 */ 2380 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, 2381 boolean reqInit, String dc) { 2382 type = bracketsOpt(type); 2383 JCExpression init = null; 2384 if (S.token() == EQ) { 2385 S.nextToken(); 2386 init = variableInitializer(); 2387 } 2388 else if (reqInit) syntaxError(S.pos(), "expected", EQ); 2389 JCVariableDecl result = 2390 toP(F.at(pos).VarDef(mods, name, type, init)); 2391 attach(result, dc); 2392 return result; 2393 } 2394 2395 /** VariableDeclaratorId = Ident BracketsOpt 2396 */ 2397 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { 2398 int pos = S.pos(); 2399 Name name = ident(); 2400 if ((mods.flags & Flags.VARARGS) == 0) 2401 type = bracketsOpt(type); 2402 return toP(F.at(pos).VarDef(mods, name, type, null)); 2403 } 2404 2405 /** ResourceDeclarators = ResourceDeclarator { ";" ResourceDeclarator } 2406 */ 2407 List<JCTree> resourceDeclarators() { 2408 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2409 defs.append(resourceDeclarator()); 2410 while (S.token() == SEMI) { 2411 // All but last of multiple declarators subsume a semicolon 2412 storeEnd(defs.elems.last(), S.endPos()); 2413 S.nextToken(); 2414 defs.append(resourceDeclarator()); 2415 } 2416 return defs.toList(); 2417 } 2418 2419 /** ResourceDeclarator = LocalVariableDeclaration */ 2420 JCTree resourceDeclarator() { 2421 int pos = S.pos(); 2422 if (S.token() == FINAL || S.token() == MONKEYS_AT) { 2423 return variableDeclaratorRest(pos, optFinal(0), parseType(), 2424 ident(), true, null); 2425 } else { 2426 JCExpression t = term(EXPR | TYPE); 2427 if ((lastmode & TYPE) != 0 && S.token() == IDENTIFIER) 2428 return variableDeclaratorRest(pos, toP(F.at(pos).Modifiers(Flags.FINAL)), t, 2429 ident(), true, null); 2430 else 2431 return t; 2432 } 2433 } 2434 2435 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} 2436 */ 2437 public JCTree.JCCompilationUnit parseCompilationUnit() { 2438 int pos = S.pos(); 2439 JCExpression pid = null; 2440 String dc = S.docComment(); 2441 JCModifiers mods = null; 2442 List<JCAnnotation> packageAnnotations = List.nil(); 2443 if (S.token() == MONKEYS_AT) 2444 mods = modifiersOpt(); 2445 2446 if (S.token() == PACKAGE) { 2447 if (mods != null) { 2448 checkNoMods(mods.flags); 2449 packageAnnotations = mods.annotations; 2450 mods = null; 2451 } 2452 S.nextToken(); 2453 pid = qualident(); 2454 accept(SEMI); 2455 } 2456 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2457 boolean checkForImports = true; 2458 while (S.token() != EOF) { 2459 if (S.pos() <= errorEndPos) { 2460 // error recovery 2461 skip(checkForImports, false, false, false); 2462 if (S.token() == EOF) 2463 break; 2464 } 2465 if (checkForImports && mods == null && S.token() == IMPORT) { 2466 defs.append(importDeclaration()); 2467 } else { 2468 JCTree def = typeDeclaration(mods); 2469 if (def instanceof JCExpressionStatement) 2470 def = ((JCExpressionStatement)def).expr; 2471 defs.append(def); 2472 if (def instanceof JCClassDecl) 2473 checkForImports = false; 2474 mods = null; 2475 } 2476 } 2477 JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList()); 2478 attach(toplevel, dc); 2479 if (defs.elems.isEmpty()) 2480 storeEnd(toplevel, S.prevEndPos()); 2481 if (keepDocComments) 2482 toplevel.docComments = docComments; 2483 if (keepLineMap) 2484 toplevel.lineMap = S.getLineMap(); 2485 return toplevel; 2486 } 2487 2488 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" 2489 */ 2490 JCTree importDeclaration() { 2491 int pos = S.pos(); 2492 S.nextToken(); 2493 boolean importStatic = false; 2494 if (S.token() == STATIC) { 2495 checkStaticImports(); 2496 importStatic = true; 2497 S.nextToken(); 2498 } 2499 JCExpression pid = toP(F.at(S.pos()).Ident(ident())); 2500 do { 2501 int pos1 = S.pos(); 2502 accept(DOT); 2503 if (S.token() == STAR) { 2504 pid = to(F.at(pos1).Select(pid, names.asterisk)); 2505 S.nextToken(); 2506 break; 2507 } else { 2508 pid = toP(F.at(pos1).Select(pid, ident())); 2509 } 2510 } while (S.token() == DOT); 2511 accept(SEMI); 2512 return toP(F.at(pos).Import(pid, importStatic)); 2513 } 2514 2515 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration 2516 * | ";" 2517 */ 2518 JCTree typeDeclaration(JCModifiers mods) { 2519 int pos = S.pos(); 2520 if (mods == null && S.token() == SEMI) { 2521 S.nextToken(); 2522 return toP(F.at(pos).Skip()); 2523 } else { 2524 String dc = S.docComment(); 2525 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc); 2526 } 2527 } 2528 2529 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt 2530 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) 2531 * @param mods Any modifiers starting the class or interface declaration 2532 * @param dc The documentation comment for the class, or null. 2533 */ 2534 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) { 2535 if (S.token() == CLASS) { 2536 return classDeclaration(mods, dc); 2537 } else if (S.token() == INTERFACE) { 2538 return interfaceDeclaration(mods, dc); 2539 } else if (allowEnums) { 2540 if (S.token() == ENUM) { 2541 return enumDeclaration(mods, dc); 2542 } else { 2543 int pos = S.pos(); 2544 List<JCTree> errs; 2545 if (S.token() == IDENTIFIER) { 2546 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 2547 setErrorEndPos(S.pos()); 2548 } else { 2549 errs = List.<JCTree>of(mods); 2550 } 2551 return toP(F.Exec(syntaxError(pos, errs, "expected3", 2552 CLASS, INTERFACE, ENUM))); 2553 } 2554 } else { 2555 if (S.token() == ENUM) { 2556 log.error(S.pos(), "enums.not.supported.in.source", source.name); 2557 allowEnums = true; 2558 return enumDeclaration(mods, dc); 2559 } 2560 int pos = S.pos(); 2561 List<JCTree> errs; 2562 if (S.token() == IDENTIFIER) { 2563 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 2564 setErrorEndPos(S.pos()); 2565 } else { 2566 errs = List.<JCTree>of(mods); 2567 } 2568 return toP(F.Exec(syntaxError(pos, errs, "expected2", 2569 CLASS, INTERFACE))); 2570 } 2571 } 2572 2573 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] 2574 * [IMPLEMENTS TypeList] ClassBody 2575 * @param mods The modifiers starting the class declaration 2576 * @param dc The documentation comment for the class, or null. 2577 */ 2578 JCClassDecl classDeclaration(JCModifiers mods, String dc) { 2579 int pos = S.pos(); 2580 accept(CLASS); 2581 Name name = ident(); 2582 2583 List<JCTypeParameter> typarams = typeParametersOpt(); 2584 2585 JCTree extending = null; 2586 if (S.token() == EXTENDS) { 2587 S.nextToken(); 2588 extending = parseType(); 2589 } 2590 List<JCExpression> implementing = List.nil(); 2591 if (S.token() == IMPLEMENTS) { 2592 S.nextToken(); 2593 implementing = typeList(); 2594 } 2595 List<JCTree> defs = classOrInterfaceBody(name, false); 2596 JCClassDecl result = toP(F.at(pos).ClassDef( 2597 mods, name, typarams, extending, implementing, defs)); 2598 attach(result, dc); 2599 return result; 2600 } 2601 2602 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt 2603 * [EXTENDS TypeList] InterfaceBody 2604 * @param mods The modifiers starting the interface declaration 2605 * @param dc The documentation comment for the interface, or null. 2606 */ 2607 JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { 2608 int pos = S.pos(); 2609 accept(INTERFACE); 2610 Name name = ident(); 2611 2612 List<JCTypeParameter> typarams = typeParametersOpt(); 2613 2614 List<JCExpression> extending = List.nil(); 2615 if (S.token() == EXTENDS) { 2616 S.nextToken(); 2617 extending = typeList(); 2618 } 2619 List<JCTree> defs = classOrInterfaceBody(name, true); 2620 JCClassDecl result = toP(F.at(pos).ClassDef( 2621 mods, name, typarams, null, extending, defs)); 2622 attach(result, dc); 2623 return result; 2624 } 2625 2626 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody 2627 * @param mods The modifiers starting the enum declaration 2628 * @param dc The documentation comment for the enum, or null. 2629 */ 2630 JCClassDecl enumDeclaration(JCModifiers mods, String dc) { 2631 int pos = S.pos(); 2632 accept(ENUM); 2633 Name name = ident(); 2634 2635 List<JCExpression> implementing = List.nil(); 2636 if (S.token() == IMPLEMENTS) { 2637 S.nextToken(); 2638 implementing = typeList(); 2639 } 2640 2641 List<JCTree> defs = enumBody(name); 2642 mods.flags |= Flags.ENUM; 2643 JCClassDecl result = toP(F.at(pos). 2644 ClassDef(mods, name, List.<JCTypeParameter>nil(), 2645 null, implementing, defs)); 2646 attach(result, dc); 2647 return result; 2648 } 2649 2650 /** EnumBody = "{" { EnumeratorDeclarationList } [","] 2651 * [ ";" {ClassBodyDeclaration} ] "}" 2652 */ 2653 List<JCTree> enumBody(Name enumName) { 2654 accept(LBRACE); 2655 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2656 if (S.token() == COMMA) { 2657 S.nextToken(); 2658 } else if (S.token() != RBRACE && S.token() != SEMI) { 2659 defs.append(enumeratorDeclaration(enumName)); 2660 while (S.token() == COMMA) { 2661 S.nextToken(); 2662 if (S.token() == RBRACE || S.token() == SEMI) break; 2663 defs.append(enumeratorDeclaration(enumName)); 2664 } 2665 if (S.token() != SEMI && S.token() != RBRACE) { 2666 defs.append(syntaxError(S.pos(), "expected3", 2667 COMMA, RBRACE, SEMI)); 2668 S.nextToken(); 2669 } 2670 } 2671 if (S.token() == SEMI) { 2672 S.nextToken(); 2673 while (S.token() != RBRACE && S.token() != EOF) { 2674 defs.appendList(classOrInterfaceBodyDeclaration(enumName, 2675 false)); 2676 if (S.pos() <= errorEndPos) { 2677 // error recovery 2678 skip(false, true, true, false); 2679 } 2680 } 2681 } 2682 accept(RBRACE); 2683 return defs.toList(); 2684 } 2685 2686 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] 2687 */ 2688 JCTree enumeratorDeclaration(Name enumName) { 2689 String dc = S.docComment(); 2690 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; 2691 if (S.deprecatedFlag()) { 2692 flags |= Flags.DEPRECATED; 2693 S.resetDeprecatedFlag(); 2694 } 2695 int pos = S.pos(); 2696 List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.DEFAULT_ANNO); 2697 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 2698 List<JCExpression> typeArgs = typeArgumentsOpt(); 2699 int identPos = S.pos(); 2700 Name name = ident(); 2701 int createPos = S.pos(); 2702 List<JCExpression> args = (S.token() == LPAREN) 2703 ? arguments() : List.<JCExpression>nil(); 2704 JCClassDecl body = null; 2705 if (S.token() == LBRACE) { 2706 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); 2707 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 2708 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); 2709 } 2710 if (args.isEmpty() && body == null) 2711 createPos = identPos; 2712 JCIdent ident = F.at(identPos).Ident(enumName); 2713 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); 2714 if (createPos != identPos) 2715 storeEnd(create, S.prevEndPos()); 2716 ident = F.at(identPos).Ident(enumName); 2717 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); 2718 attach(result, dc); 2719 return result; 2720 } 2721 2722 /** TypeList = Type {"," Type} 2723 */ 2724 List<JCExpression> typeList() { 2725 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 2726 ts.append(parseType()); 2727 while (S.token() == COMMA) { 2728 S.nextToken(); 2729 ts.append(parseType()); 2730 } 2731 return ts.toList(); 2732 } 2733 2734 /** ClassBody = "{" {ClassBodyDeclaration} "}" 2735 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" 2736 */ 2737 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 2738 accept(LBRACE); 2739 if (S.pos() <= errorEndPos) { 2740 // error recovery 2741 skip(false, true, false, false); 2742 if (S.token() == LBRACE) 2743 S.nextToken(); 2744 } 2745 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 2746 while (S.token() != RBRACE && S.token() != EOF) { 2747 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 2748 if (S.pos() <= errorEndPos) { 2749 // error recovery 2750 skip(false, true, true, false); 2751 } 2752 } 2753 accept(RBRACE); 2754 return defs.toList(); 2755 } 2756 2757 /** ClassBodyDeclaration = 2758 * ";" 2759 * | [STATIC] Block 2760 * | ModifiersOpt 2761 * ( Type Ident 2762 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) 2763 * | VOID Ident MethodDeclaratorRest 2764 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest 2765 * | Ident ConstructorDeclaratorRest 2766 * | TypeParameters Ident ConstructorDeclaratorRest 2767 * | ClassOrInterfaceOrEnumDeclaration 2768 * ) 2769 * InterfaceBodyDeclaration = 2770 * ";" 2771 * | ModifiersOpt Type Ident 2772 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) 2773 */ 2774 List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { 2775 if (S.token() == SEMI) { 2776 S.nextToken(); 2777 return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil())); 2778 } else { 2779 String dc = S.docComment(); 2780 int pos = S.pos(); 2781 JCModifiers mods = modifiersOpt(); 2782 if (S.token() == CLASS || 2783 S.token() == INTERFACE || 2784 allowEnums && S.token() == ENUM) { 2785 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 2786 } else if (S.token() == LBRACE && !isInterface && 2787 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && 2788 mods.annotations.isEmpty()) { 2789 return List.<JCTree>of(block(pos, mods.flags)); 2790 } else { 2791 pos = S.pos(); 2792 List<JCTypeParameter> typarams = typeParametersOpt(); 2793 List<JCAnnotation> annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO); 2794 2795 Name name = S.name(); 2796 pos = S.pos(); 2797 JCExpression type; 2798 boolean isVoid = S.token() == VOID; 2799 if (isVoid) { 2800 if (annosAfterParams.nonEmpty()) 2801 illegal(annosAfterParams.head.pos); 2802 type = to(F.at(pos).TypeIdent(TypeTags.VOID)); 2803 S.nextToken(); 2804 } else { 2805 if (annosAfterParams.nonEmpty()) { 2806 mods.annotations = mods.annotations.appendList(annosAfterParams); 2807 if (mods.pos == Position.NOPOS) 2808 mods.pos = mods.annotations.head.pos; 2809 } 2810 // method returns types are un-annotated types 2811 type = unannotatedType(); 2812 } 2813 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { 2814 if (isInterface || name != className) 2815 log.error(pos, "invalid.meth.decl.ret.type.req"); 2816 return List.of(methodDeclaratorRest( 2817 pos, mods, null, names.init, typarams, 2818 isInterface, true, dc)); 2819 } else { 2820 pos = S.pos(); 2821 name = ident(); 2822 if (S.token() == LPAREN) { 2823 return List.of(methodDeclaratorRest( 2824 pos, mods, type, name, typarams, 2825 isInterface, isVoid, dc)); 2826 } else if (!isVoid && typarams.isEmpty()) { 2827 List<JCTree> defs = 2828 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, 2829 new ListBuffer<JCTree>()).toList(); 2830 storeEnd(defs.last(), S.endPos()); 2831 accept(SEMI); 2832 return defs; 2833 } else { 2834 pos = S.pos(); 2835 List<JCTree> err = isVoid 2836 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, 2837 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 2838 : null; 2839 return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN)); 2840 } 2841 } 2842 } 2843 } 2844 } 2845 2846 /** MethodDeclaratorRest = 2847 * FormalParameters BracketsOpt [Annotations] [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 2848 * VoidMethodDeclaratorRest = 2849 * FormalParameters [Annotations] [Throws TypeList] ( MethodBody | ";") 2850 * InterfaceMethodDeclaratorRest = 2851 * FormalParameters BracketsOpt [Annotations] [THROWS TypeList] ";" 2852 * VoidInterfaceMethodDeclaratorRest = 2853 * FormalParameters [Annotations] [THROWS TypeList] ";" 2854 * ConstructorDeclaratorRest = 2855 * "(" FormalParameterListOpt ")" [Annotations] [THROWS TypeList] MethodBody 2856 */ 2857 JCTree methodDeclaratorRest(int pos, 2858 JCModifiers mods, 2859 JCExpression type, 2860 Name name, 2861 List<JCTypeParameter> typarams, 2862 boolean isInterface, boolean isVoid, 2863 String dc) { 2864 List<JCVariableDecl> params = formalParameters(); 2865 2866 List<JCTypeAnnotation> receiverAnnotations; 2867 if (!isVoid) { 2868 // need to distinguish between receiver anno and array anno 2869 // look at typeAnnotationsPushedBack comment 2870 this.permitTypeAnnotationsPushBack = true; 2871 type = methodReturnArrayRest(type); 2872 this.permitTypeAnnotationsPushBack = false; 2873 if (typeAnnotationsPushedBack == null) 2874 receiverAnnotations = List.nil(); 2875 else 2876 receiverAnnotations = typeAnnotationsPushedBack; 2877 typeAnnotationsPushedBack = null; 2878 } else 2879 receiverAnnotations = typeAnnotationsOpt(); 2880 2881 List<JCExpression> thrown = List.nil(); 2882 if (S.token() == THROWS) { 2883 S.nextToken(); 2884 thrown = qualidentList(); 2885 } 2886 JCBlock body = null; 2887 JCExpression defaultValue; 2888 if (S.token() == LBRACE) { 2889 body = block(); 2890 defaultValue = null; 2891 } else { 2892 if (S.token() == DEFAULT) { 2893 accept(DEFAULT); 2894 defaultValue = annotationValue(); 2895 } else { 2896 defaultValue = null; 2897 } 2898 accept(SEMI); 2899 if (S.pos() <= errorEndPos) { 2900 // error recovery 2901 skip(false, true, false, false); 2902 if (S.token() == LBRACE) { 2903 body = block(); 2904 } 2905 } 2906 } 2907 2908 JCMethodDecl result = 2909 toP(F.at(pos).MethodDef(mods, name, type, typarams, 2910 params, receiverAnnotations, thrown, 2911 body, defaultValue)); 2912 attach(result, dc); 2913 return result; 2914 } 2915 2916 /** Parses the array levels after the format parameters list, and append 2917 * them to the return type, while preseving the order of type annotations 2918 */ 2919 private JCExpression methodReturnArrayRest(JCExpression type) { 2920 if (type.getTag() != JCTree.TYPEARRAY) 2921 return bracketsOpt(type); 2922 2923 JCArrayTypeTree baseArray = (JCArrayTypeTree)type; 2924 while (TreeInfo.typeIn(baseArray.elemtype) instanceof JCArrayTypeTree) 2925 baseArray = (JCArrayTypeTree)TreeInfo.typeIn(baseArray.elemtype); 2926 2927 if (baseArray.elemtype.getTag() == JCTree.ANNOTATED_TYPE) { 2928 JCAnnotatedType at = (JCAnnotatedType)baseArray.elemtype; 2929 at.underlyingType = bracketsOpt(at.underlyingType); 2930 } else { 2931 baseArray.elemtype = bracketsOpt(baseArray.elemtype); 2932 } 2933 2934 return type; 2935 } 2936 2937 /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident} 2938 */ 2939 List<JCExpression> qualidentList() { 2940 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 2941 2942 List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt(); 2943 if (!typeAnnos.isEmpty()) 2944 ts.append(F.AnnotatedType(typeAnnos, qualident())); 2945 else 2946 ts.append(qualident()); 2947 while (S.token() == COMMA) { 2948 S.nextToken(); 2949 2950 typeAnnos = typeAnnotationsOpt(); 2951 if (!typeAnnos.isEmpty()) 2952 ts.append(F.AnnotatedType(typeAnnos, qualident())); 2953 else 2954 ts.append(qualident()); 2955 } 2956 return ts.toList(); 2957 } 2958 2959 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] 2960 */ 2961 List<JCTypeParameter> typeParametersOpt() { 2962 if (S.token() == LT) { 2963 checkGenerics(); 2964 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>(); 2965 S.nextToken(); 2966 typarams.append(typeParameter()); 2967 while (S.token() == COMMA) { 2968 S.nextToken(); 2969 typarams.append(typeParameter()); 2970 } 2971 accept(GT); 2972 return typarams.toList(); 2973 } else { 2974 return List.nil(); 2975 } 2976 } 2977 2978 /** TypeParameter = [Annotations] TypeVariable [TypeParameterBound] 2979 * TypeParameterBound = EXTENDS Type {"&" Type} 2980 * TypeVariable = Ident 2981 */ 2982 JCTypeParameter typeParameter() { 2983 int pos = S.pos(); 2984 List<JCTypeAnnotation> annos = typeAnnotationsOpt(); 2985 Name name = ident(); 2986 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); 2987 if (S.token() == EXTENDS) { 2988 S.nextToken(); 2989 bounds.append(parseType()); 2990 while (S.token() == AMP) { 2991 S.nextToken(); 2992 bounds.append(parseType()); 2993 } 2994 } 2995 return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos)); 2996 } 2997 2998 /** FormalParameters = "(" [ FormalParameterList ] ")" 2999 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter 3000 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter 3001 */ 3002 List<JCVariableDecl> formalParameters() { 3003 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); 3004 JCVariableDecl lastParam = null; 3005 accept(LPAREN); 3006 if (S.token() != RPAREN) { 3007 params.append(lastParam = formalParameter()); 3008 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) { 3009 S.nextToken(); 3010 params.append(lastParam = formalParameter()); 3011 } 3012 } 3013 accept(RPAREN); 3014 return params.toList(); 3015 } 3016 3017 JCModifiers optFinal(long flags) { 3018 JCModifiers mods = modifiersOpt(); 3019 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); 3020 mods.flags |= flags; 3021 return mods; 3022 } 3023 3024 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId 3025 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter 3026 */ 3027 JCVariableDecl formalParameter() { 3028 JCModifiers mods = optFinal(Flags.PARAMETER); 3029 // need to distinguish between vararg annos and array annos 3030 // look at typeAnnotaitonsPushedBack comment 3031 this.permitTypeAnnotationsPushBack = true; 3032 JCExpression type = parseType(); 3033 this.permitTypeAnnotationsPushBack = false; 3034 3035 if (S.token() == ELLIPSIS) { 3036 List<JCTypeAnnotation> varargsAnnos = typeAnnotationsPushedBack; 3037 typeAnnotationsPushedBack = null; 3038 checkVarargs(); 3039 mods.flags |= Flags.VARARGS; 3040 // insert var arg type annotations 3041 if (varargsAnnos != null && varargsAnnos.nonEmpty()) 3042 type = F.at(S.pos()).AnnotatedType(varargsAnnos, type); 3043 type = to(F.at(S.pos()).TypeArray(type)); 3044 3045 S.nextToken(); 3046 } else { 3047 // if not a var arg, then typeAnnotationsPushedBack should be null 3048 if (typeAnnotationsPushedBack != null 3049 && !typeAnnotationsPushedBack.isEmpty()) { 3050 reportSyntaxError(typeAnnotationsPushedBack.head.pos, 3051 "illegal.start.of.type"); 3052 } 3053 typeAnnotationsPushedBack = null; 3054 } 3055 return variableDeclaratorId(mods, type); 3056 } 3057 3058 /* ---------- auxiliary methods -------------- */ 3059 3060 /** Check that given tree is a legal expression statement. 3061 */ 3062 protected JCExpression checkExprStat(JCExpression t) { 3063 switch(t.getTag()) { 3064 case JCTree.PREINC: case JCTree.PREDEC: 3065 case JCTree.POSTINC: case JCTree.POSTDEC: 3066 case JCTree.ASSIGN: 3067 case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG: 3068 case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG: 3069 case JCTree.PLUS_ASG: case JCTree.MINUS_ASG: 3070 case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG: 3071 case JCTree.APPLY: case JCTree.NEWCLASS: 3072 case JCTree.ERRONEOUS: 3073 return t; 3074 default: 3075 log.error(t.pos, "not.stmt"); 3076 return F.at(t.pos).Erroneous(List.<JCTree>of(t)); 3077 } 3078 } 3079 3080 /** Return precedence of operator represented by token, 3081 * -1 if token is not a binary operator. @see TreeInfo.opPrec 3082 */ 3083 static int prec(Token token) { 3084 int oc = optag(token); 3085 return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; 3086 } 3087 3088 /** 3089 * Return the lesser of two positions, making allowance for either one 3090 * being unset. 3091 */ 3092 static int earlier(int pos1, int pos2) { 3093 if (pos1 == Position.NOPOS) 3094 return pos2; 3095 if (pos2 == Position.NOPOS) 3096 return pos1; 3097 return (pos1 < pos2 ? pos1 : pos2); 3098 } 3099 3100 /** Return operation tag of binary operator represented by token, 3101 * -1 if token is not a binary operator. 3102 */ 3103 static int optag(Token token) { 3104 switch (token) { 3105 case BARBAR: 3106 return JCTree.OR; 3107 case AMPAMP: 3108 return JCTree.AND; 3109 case BAR: 3110 return JCTree.BITOR; 3111 case BAREQ: 3112 return JCTree.BITOR_ASG; 3113 case CARET: 3114 return JCTree.BITXOR; 3115 case CARETEQ: 3116 return JCTree.BITXOR_ASG; 3117 case AMP: 3118 return JCTree.BITAND; 3119 case AMPEQ: 3120 return JCTree.BITAND_ASG; 3121 case EQEQ: 3122 return JCTree.EQ; 3123 case BANGEQ: 3124 return JCTree.NE; 3125 case LT: 3126 return JCTree.LT; 3127 case GT: 3128 return JCTree.GT; 3129 case LTEQ: 3130 return JCTree.LE; 3131 case GTEQ: 3132 return JCTree.GE; 3133 case LTLT: 3134 return JCTree.SL; 3135 case LTLTEQ: 3136 return JCTree.SL_ASG; 3137 case GTGT: 3138 return JCTree.SR; 3139 case GTGTEQ: 3140 return JCTree.SR_ASG; 3141 case GTGTGT: 3142 return JCTree.USR; 3143 case GTGTGTEQ: 3144 return JCTree.USR_ASG; 3145 case PLUS: 3146 return JCTree.PLUS; 3147 case PLUSEQ: 3148 return JCTree.PLUS_ASG; 3149 case SUB: 3150 return JCTree.MINUS; 3151 case SUBEQ: 3152 return JCTree.MINUS_ASG; 3153 case STAR: 3154 return JCTree.MUL; 3155 case STAREQ: 3156 return JCTree.MUL_ASG; 3157 case SLASH: 3158 return JCTree.DIV; 3159 case SLASHEQ: 3160 return JCTree.DIV_ASG; 3161 case PERCENT: 3162 return JCTree.MOD; 3163 case PERCENTEQ: 3164 return JCTree.MOD_ASG; 3165 case INSTANCEOF: 3166 return JCTree.TYPETEST; 3167 default: 3168 return -1; 3169 } 3170 } 3171 3172 /** Return operation tag of unary operator represented by token, 3173 * -1 if token is not a binary operator. 3174 */ 3175 static int unoptag(Token token) { 3176 switch (token) { 3177 case PLUS: 3178 return JCTree.POS; 3179 case SUB: 3180 return JCTree.NEG; 3181 case BANG: 3182 return JCTree.NOT; 3183 case TILDE: 3184 return JCTree.COMPL; 3185 case PLUSPLUS: 3186 return JCTree.PREINC; 3187 case SUBSUB: 3188 return JCTree.PREDEC; 3189 default: 3190 return -1; 3191 } 3192 } 3193 3194 /** Return type tag of basic type represented by token, 3195 * -1 if token is not a basic type identifier. 3196 */ 3197 static int typetag(Token token) { 3198 switch (token) { 3199 case BYTE: 3200 return TypeTags.BYTE; 3201 case CHAR: 3202 return TypeTags.CHAR; 3203 case SHORT: 3204 return TypeTags.SHORT; 3205 case INT: 3206 return TypeTags.INT; 3207 case LONG: 3208 return TypeTags.LONG; 3209 case FLOAT: 3210 return TypeTags.FLOAT; 3211 case DOUBLE: 3212 return TypeTags.DOUBLE; 3213 case BOOLEAN: 3214 return TypeTags.BOOLEAN; 3215 default: 3216 return -1; 3217 } 3218 } 3219 3220 void checkGenerics() { 3221 if (!allowGenerics) { 3222 log.error(S.pos(), "generics.not.supported.in.source", source.name); 3223 allowGenerics = true; 3224 } 3225 } 3226 void checkVarargs() { 3227 if (!allowVarargs) { 3228 log.error(S.pos(), "varargs.not.supported.in.source", source.name); 3229 allowVarargs = true; 3230 } 3231 } 3232 void checkForeach() { 3233 if (!allowForeach) { 3234 log.error(S.pos(), "foreach.not.supported.in.source", source.name); 3235 allowForeach = true; 3236 } 3237 } 3238 void checkStaticImports() { 3239 if (!allowStaticImport) { 3240 log.error(S.pos(), "static.import.not.supported.in.source", source.name); 3241 allowStaticImport = true; 3242 } 3243 } 3244 void checkAnnotations() { 3245 if (!allowAnnotations) { 3246 log.error(S.pos(), "annotations.not.supported.in.source", source.name); 3247 allowAnnotations = true; 3248 } 3249 } 3250 void checkTypeAnnotations() { 3251 if (!allowTypeAnnotations) { 3252 log.error(S.pos(), "type.annotations.not.supported.in.source", source.name); 3253 allowTypeAnnotations = true; 3254 } 3255 } 3256 void checkDiamond() { 3257 if (!allowDiamond) { 3258 log.error(S.pos(), "diamond.not.supported.in.source", source.name); 3259 allowDiamond = true; 3260 } 3261 } 3262 void checkMulticatch() { 3263 if (!allowMulticatch) { 3264 log.error(S.pos(), "multicatch.not.supported.in.source", source.name); 3265 allowMulticatch = true; 3266 } 3267 } 3268 void checkAutomaticResourceManagement() { 3269 if (!allowARM) { 3270 log.error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name); 3271 allowARM = true; 3272 } 3273 } 3274 }