1 /* 2 * Copyright (c) 1999, 2013, 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.source.tree.MemberReferenceTree.ReferenceMode; 31 32 import com.sun.tools.javac.code.*; 33 import com.sun.tools.javac.parser.Tokens.*; 34 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; 35 import com.sun.tools.javac.tree.*; 36 import com.sun.tools.javac.tree.JCTree.*; 37 import com.sun.tools.javac.util.*; 38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 40 import com.sun.tools.javac.util.List; 41 42 import static com.sun.tools.javac.parser.Tokens.TokenKind.*; 43 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT; 44 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE; 45 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH; 46 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ; 47 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT; 48 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT; 49 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT; 50 import static com.sun.tools.javac.tree.JCTree.Tag.*; 51 import static com.sun.tools.javac.util.ListBuffer.lb; 52 53 /** The parser maps a token sequence into an abstract syntax 54 * tree. It operates by recursive descent, with code derived 55 * systematically from an LL(1) grammar. For efficiency reasons, an 56 * operator precedence scheme is used for parsing binary operation 57 * expressions. 58 * 59 * <p><b>This is NOT part of any supported API. 60 * If you write code that depends on this, you do so at your own risk. 61 * This code and its internal interfaces are subject to change or 62 * deletion without notice.</b> 63 */ 64 public class JavacParser implements Parser { 65 66 /** The number of precedence levels of infix operators. 67 */ 68 private static final int infixPrecedenceLevels = 10; 69 70 /** The scanner used for lexical analysis. 71 */ 72 protected Lexer S; 73 74 /** The factory to be used for abstract syntax tree construction. 75 */ 76 protected TreeMaker F; 77 78 /** The log to be used for error diagnostics. 79 */ 80 private Log log; 81 82 /** The Source language setting. */ 83 private Source source; 84 85 /** The name table. */ 86 private Names names; 87 88 /** End position mappings container */ 89 private final AbstractEndPosTable endPosTable; 90 91 // Because of javac's limited lookahead, some contexts are ambiguous in 92 // the presence of type annotations even though they are not ambiguous 93 // in the absence of type annotations. Consider this code: 94 // void m(String [] m) { } 95 // void m(String ... m) { } 96 // After parsing "String", javac calls bracketsOpt which immediately 97 // returns if the next character is not '['. Similarly, javac can see 98 // if the next token is ... and in that case parse an ellipsis. But in 99 // the presence of type annotations: 100 // void m(String @A [] m) { } 101 // void m(String @A ... m) { } 102 // no finite lookahead is enough to determine whether to read array 103 // levels or an ellipsis. Furthermore, if you call bracketsOpt, then 104 // bracketsOpt first reads all the leading annotations and only then 105 // discovers that it needs to fail. bracketsOpt needs a way to push 106 // back the extra annotations that it read. (But, bracketsOpt should 107 // not *always* be allowed to push back extra annotations that it finds 108 // -- in most contexts, any such extra annotation is an error. 109 // 110 // The following two variables permit type annotations that have 111 // already been read to be stored for later use. Alternate 112 // implementations are possible but would cause much larger changes to 113 // the parser. 114 115 /** Type annotations that have already been read but have not yet been used. **/ 116 private List<JCAnnotation> typeAnnotationsPushedBack = List.nil(); 117 118 /** 119 * If the parser notices extra annotations, then it either immediately 120 * issues an error (if this variable is false) or places the extra 121 * annotations in variable typeAnnotationsPushedBack (if this variable 122 * is true). 123 */ 124 private boolean permitTypeAnnotationsPushBack = false; 125 126 interface ErrorRecoveryAction { 127 JCTree doRecover(JavacParser parser); 128 } 129 130 enum BasicErrorRecoveryAction implements ErrorRecoveryAction { 131 BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }}, 132 CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }} 133 } 134 135 /** Construct a parser from a given scanner, tree factory and log. 136 */ 137 protected JavacParser(ParserFactory fac, 138 Lexer S, 139 boolean keepDocComments, 140 boolean keepLineMap, 141 boolean keepEndPositions) { 142 this.S = S; 143 nextToken(); // prime the pump 144 this.F = fac.F; 145 this.log = fac.log; 146 this.names = fac.names; 147 this.source = fac.source; 148 this.allowGenerics = source.allowGenerics(); 149 this.allowVarargs = source.allowVarargs(); 150 this.allowAsserts = source.allowAsserts(); 151 this.allowEnums = source.allowEnums(); 152 this.allowForeach = source.allowForeach(); 153 this.allowStaticImport = source.allowStaticImport(); 154 this.allowAnnotations = source.allowAnnotations(); 155 this.allowTWR = source.allowTryWithResources(); 156 this.allowDiamond = source.allowDiamond(); 157 this.allowMulticatch = source.allowMulticatch(); 158 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true); 159 this.allowLambda = source.allowLambda(); 160 this.allowMethodReferences = source.allowMethodReferences(); 161 this.allowDefaultMethods = source.allowDefaultMethods(); 162 this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); 163 this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast(); 164 this.allowTypeAnnotations = source.allowTypeAnnotations(); 165 this.keepDocComments = keepDocComments; 166 docComments = newDocCommentTable(keepDocComments, fac); 167 this.keepLineMap = keepLineMap; 168 this.errorTree = F.Erroneous(); 169 endPosTable = newEndPosTable(keepEndPositions); 170 } 171 172 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) { 173 return keepEndPositions 174 ? new SimpleEndPosTable(this) 175 : new EmptyEndPosTable(this); 176 } 177 178 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) { 179 return keepDocComments ? new LazyDocCommentTable(fac) : null; 180 } 181 182 /** Switch: Should generics be recognized? 183 */ 184 boolean allowGenerics; 185 186 /** Switch: Should diamond operator be recognized? 187 */ 188 boolean allowDiamond; 189 190 /** Switch: Should multicatch clause be accepted? 191 */ 192 boolean allowMulticatch; 193 194 /** Switch: Should varargs be recognized? 195 */ 196 boolean allowVarargs; 197 198 /** Switch: should we recognize assert statements, or just give a warning? 199 */ 200 boolean allowAsserts; 201 202 /** Switch: should we recognize enums, or just give a warning? 203 */ 204 boolean allowEnums; 205 206 /** Switch: should we recognize foreach? 207 */ 208 boolean allowForeach; 209 210 /** Switch: should we recognize foreach? 211 */ 212 boolean allowStaticImport; 213 214 /** Switch: should we recognize annotations? 215 */ 216 boolean allowAnnotations; 217 218 /** Switch: should we recognize try-with-resources? 219 */ 220 boolean allowTWR; 221 222 /** Switch: should we fold strings? 223 */ 224 boolean allowStringFolding; 225 226 /** Switch: should we recognize lambda expressions? 227 */ 228 boolean allowLambda; 229 230 /** Switch: should we allow method/constructor references? 231 */ 232 boolean allowMethodReferences; 233 234 /** Switch: should we allow default methods in interfaces? 235 */ 236 boolean allowDefaultMethods; 237 238 /** Switch: should we allow static methods in interfaces? 239 */ 240 boolean allowStaticInterfaceMethods; 241 242 /** Switch: should we allow intersection types in cast? 243 */ 244 boolean allowIntersectionTypesInCast; 245 246 /** Switch: should we keep docComments? 247 */ 248 boolean keepDocComments; 249 250 /** Switch: should we keep line table? 251 */ 252 boolean keepLineMap; 253 254 /** Switch: should we recognize type annotations? 255 */ 256 boolean allowTypeAnnotations; 257 258 /** Switch: is "this" allowed as an identifier? 259 * This is needed to parse receiver types. 260 */ 261 boolean allowThisIdent; 262 263 /** The type of the method receiver, as specified by a first "this" parameter. 264 */ 265 JCVariableDecl receiverParam; 266 267 268 /** When terms are parsed, the mode determines which is expected: 269 * mode = EXPR : an expression 270 * mode = TYPE : a type 271 * mode = NOPARAMS : no parameters allowed for type 272 * mode = TYPEARG : type argument 273 */ 274 static final int EXPR = 0x1; 275 static final int TYPE = 0x2; 276 static final int NOPARAMS = 0x4; 277 static final int TYPEARG = 0x8; 278 static final int DIAMOND = 0x10; 279 280 /** The current mode. 281 */ 282 private int mode = 0; 283 284 /** The mode of the term that was parsed last. 285 */ 286 private int lastmode = 0; 287 288 /* ---------- token management -------------- */ 289 290 protected Token token; 291 292 public Token token() { 293 return token; 294 } 295 296 public void nextToken() { 297 S.nextToken(); 298 token = S.token(); 299 } 300 301 protected boolean peekToken(Filter<TokenKind> tk) { 302 return peekToken(0, tk); 303 } 304 305 protected boolean peekToken(int lookahead, Filter<TokenKind> tk) { 306 return tk.accepts(S.token(lookahead + 1).kind); 307 } 308 309 protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2) { 310 return peekToken(0, tk1, tk2); 311 } 312 313 protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2) { 314 return tk1.accepts(S.token(lookahead + 1).kind) && 315 tk2.accepts(S.token(lookahead + 2).kind); 316 } 317 318 protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) { 319 return peekToken(0, tk1, tk2, tk3); 320 } 321 322 protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) { 323 return tk1.accepts(S.token(lookahead + 1).kind) && 324 tk2.accepts(S.token(lookahead + 2).kind) && 325 tk3.accepts(S.token(lookahead + 3).kind); 326 } 327 328 @SuppressWarnings("unchecked") 329 protected boolean peekToken(Filter<TokenKind>... kinds) { 330 return peekToken(0, kinds); 331 } 332 333 @SuppressWarnings("unchecked") 334 protected boolean peekToken(int lookahead, Filter<TokenKind>... kinds) { 335 for (; lookahead < kinds.length ; lookahead++) { 336 if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) { 337 return false; 338 } 339 } 340 return true; 341 } 342 343 /* ---------- error recovery -------------- */ 344 345 private JCErroneous errorTree; 346 347 /** Skip forward until a suitable stop token is found. 348 */ 349 private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { 350 while (true) { 351 switch (token.kind) { 352 case SEMI: 353 nextToken(); 354 return; 355 case PUBLIC: 356 case FINAL: 357 case ABSTRACT: 358 case MONKEYS_AT: 359 case EOF: 360 case CLASS: 361 case INTERFACE: 362 case ENUM: 363 return; 364 case IMPORT: 365 if (stopAtImport) 366 return; 367 break; 368 case LBRACE: 369 case RBRACE: 370 case PRIVATE: 371 case PROTECTED: 372 case STATIC: 373 case TRANSIENT: 374 case NATIVE: 375 case VOLATILE: 376 case SYNCHRONIZED: 377 case STRICTFP: 378 case LT: 379 case BYTE: 380 case SHORT: 381 case CHAR: 382 case INT: 383 case LONG: 384 case FLOAT: 385 case DOUBLE: 386 case BOOLEAN: 387 case VOID: 388 if (stopAtMemberDecl) 389 return; 390 break; 391 case UNDERSCORE: 392 case IDENTIFIER: 393 if (stopAtIdentifier) 394 return; 395 break; 396 case CASE: 397 case DEFAULT: 398 case IF: 399 case FOR: 400 case WHILE: 401 case DO: 402 case TRY: 403 case SWITCH: 404 case RETURN: 405 case THROW: 406 case BREAK: 407 case CONTINUE: 408 case ELSE: 409 case FINALLY: 410 case CATCH: 411 if (stopAtStatement) 412 return; 413 break; 414 } 415 nextToken(); 416 } 417 } 418 419 private JCErroneous syntaxError(int pos, String key, TokenKind... args) { 420 return syntaxError(pos, List.<JCTree>nil(), key, args); 421 } 422 423 private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) { 424 setErrorEndPos(pos); 425 JCErroneous err = F.at(pos).Erroneous(errs); 426 reportSyntaxError(err, key, (Object[])args); 427 if (errs != null) { 428 JCTree last = errs.last(); 429 if (last != null) 430 storeEnd(last, pos); 431 } 432 return toP(err); 433 } 434 435 private int errorPos = Position.NOPOS; 436 437 /** 438 * Report a syntax using the given the position parameter and arguments, 439 * unless one was already reported at the same position. 440 */ 441 private void reportSyntaxError(int pos, String key, Object... args) { 442 JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos); 443 reportSyntaxError(diag, key, args); 444 } 445 446 /** 447 * Report a syntax error using the given DiagnosticPosition object and 448 * arguments, unless one was already reported at the same position. 449 */ 450 private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) { 451 int pos = diagPos.getPreferredPosition(); 452 if (pos > S.errPos() || pos == Position.NOPOS) { 453 if (token.kind == EOF) { 454 error(diagPos, "premature.eof"); 455 } else { 456 error(diagPos, key, args); 457 } 458 } 459 S.errPos(pos); 460 if (token.pos == errorPos) 461 nextToken(); // guarantee progress 462 errorPos = token.pos; 463 } 464 465 466 /** Generate a syntax error at current position unless one was already 467 * reported at the same position. 468 */ 469 private JCErroneous syntaxError(String key) { 470 return syntaxError(token.pos, key); 471 } 472 473 /** Generate a syntax error at current position unless one was 474 * already reported at the same position. 475 */ 476 private JCErroneous syntaxError(String key, TokenKind arg) { 477 return syntaxError(token.pos, key, arg); 478 } 479 480 /** If next input token matches given token, skip it, otherwise report 481 * an error. 482 */ 483 public void accept(TokenKind tk) { 484 if (token.kind == tk) { 485 nextToken(); 486 } else { 487 setErrorEndPos(token.pos); 488 reportSyntaxError(S.prevToken().endPos, "expected", tk); 489 } 490 } 491 492 /** Report an illegal start of expression/type error at given position. 493 */ 494 JCExpression illegal(int pos) { 495 setErrorEndPos(pos); 496 if ((mode & EXPR) != 0) 497 return syntaxError(pos, "illegal.start.of.expr"); 498 else 499 return syntaxError(pos, "illegal.start.of.type"); 500 501 } 502 503 /** Report an illegal start of expression/type error at current position. 504 */ 505 JCExpression illegal() { 506 return illegal(token.pos); 507 } 508 509 /** Diagnose a modifier flag from the set, if any. */ 510 void checkNoMods(long mods) { 511 if (mods != 0) { 512 long lowestMod = mods & -mods; 513 error(token.pos, "mod.not.allowed.here", 514 Flags.asFlagSet(lowestMod)); 515 } 516 } 517 518 /* ---------- doc comments --------- */ 519 520 /** A table to store all documentation comments 521 * indexed by the tree nodes they refer to. 522 * defined only if option flag keepDocComment is set. 523 */ 524 private final DocCommentTable docComments; 525 526 /** Make an entry into docComments hashtable, 527 * provided flag keepDocComments is set and given doc comment is non-null. 528 * @param tree The tree to be used as index in the hashtable 529 * @param dc The doc comment to associate with the tree, or null. 530 */ 531 void attach(JCTree tree, Comment dc) { 532 if (keepDocComments && dc != null) { 533 // System.out.println("doc comment = ");System.out.println(dc);//DEBUG 534 docComments.putComment(tree, dc); 535 } 536 } 537 538 /* -------- source positions ------- */ 539 540 private void setErrorEndPos(int errPos) { 541 endPosTable.setErrorEndPos(errPos); 542 } 543 544 private void storeEnd(JCTree tree, int endpos) { 545 endPosTable.storeEnd(tree, endpos); 546 } 547 548 private <T extends JCTree> T to(T t) { 549 return endPosTable.to(t); 550 } 551 552 private <T extends JCTree> T toP(T t) { 553 return endPosTable.toP(t); 554 } 555 556 /** Get the start position for a tree node. The start position is 557 * defined to be the position of the first character of the first 558 * token of the node's source text. 559 * @param tree The tree node 560 */ 561 public int getStartPos(JCTree tree) { 562 return TreeInfo.getStartPos(tree); 563 } 564 565 /** 566 * Get the end position for a tree node. The end position is 567 * defined to be the position of the last character of the last 568 * token of the node's source text. Returns Position.NOPOS if end 569 * positions are not generated or the position is otherwise not 570 * found. 571 * @param tree The tree node 572 */ 573 public int getEndPos(JCTree tree) { 574 return endPosTable.getEndPos(tree); 575 } 576 577 578 579 /* ---------- parsing -------------- */ 580 581 /** 582 * Ident = IDENTIFIER 583 */ 584 Name ident() { 585 if (token.kind == IDENTIFIER) { 586 Name name = token.name(); 587 nextToken(); 588 return name; 589 } else if (token.kind == ASSERT) { 590 if (allowAsserts) { 591 error(token.pos, "assert.as.identifier"); 592 nextToken(); 593 return names.error; 594 } else { 595 warning(token.pos, "assert.as.identifier"); 596 Name name = token.name(); 597 nextToken(); 598 return name; 599 } 600 } else if (token.kind == ENUM) { 601 if (allowEnums) { 602 error(token.pos, "enum.as.identifier"); 603 nextToken(); 604 return names.error; 605 } else { 606 warning(token.pos, "enum.as.identifier"); 607 Name name = token.name(); 608 nextToken(); 609 return name; 610 } 611 } else if (token.kind == THIS) { 612 if (allowThisIdent) { 613 // Make sure we're using a supported source version. 614 checkTypeAnnotations(); 615 Name name = token.name(); 616 nextToken(); 617 return name; 618 } else { 619 error(token.pos, "this.as.identifier"); 620 nextToken(); 621 return names.error; 622 } 623 } else if (token.kind == UNDERSCORE) { 624 warning(token.pos, "underscore.as.identifier"); 625 Name name = token.name(); 626 nextToken(); 627 return name; 628 } else { 629 accept(IDENTIFIER); 630 return names.error; 631 } 632 } 633 634 /** 635 * Qualident = Ident { DOT [Annotations] Ident } 636 */ 637 public JCExpression qualident(boolean allowAnnos) { 638 JCExpression t = toP(F.at(token.pos).Ident(ident())); 639 while (token.kind == DOT) { 640 int pos = token.pos; 641 nextToken(); 642 List<JCAnnotation> tyannos = null; 643 if (allowAnnos) { 644 tyannos = typeAnnotationsOpt(); 645 } 646 t = toP(F.at(pos).Select(t, ident())); 647 if (tyannos != null && tyannos.nonEmpty()) { 648 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); 649 } 650 } 651 return t; 652 } 653 654 JCExpression literal(Name prefix) { 655 return literal(prefix, token.pos); 656 } 657 658 /** 659 * Literal = 660 * INTLITERAL 661 * | LONGLITERAL 662 * | FLOATLITERAL 663 * | DOUBLELITERAL 664 * | CHARLITERAL 665 * | STRINGLITERAL 666 * | TRUE 667 * | FALSE 668 * | NULL 669 */ 670 JCExpression literal(Name prefix, int pos) { 671 JCExpression t = errorTree; 672 switch (token.kind) { 673 case INTLITERAL: 674 try { 675 t = F.at(pos).Literal( 676 TypeTag.INT, 677 Convert.string2int(strval(prefix), token.radix())); 678 } catch (NumberFormatException ex) { 679 error(token.pos, "int.number.too.large", strval(prefix)); 680 } 681 break; 682 case LONGLITERAL: 683 try { 684 t = F.at(pos).Literal( 685 TypeTag.LONG, 686 new Long(Convert.string2long(strval(prefix), token.radix()))); 687 } catch (NumberFormatException ex) { 688 error(token.pos, "int.number.too.large", strval(prefix)); 689 } 690 break; 691 case FLOATLITERAL: { 692 String proper = token.radix() == 16 ? 693 ("0x"+ token.stringVal()) : 694 token.stringVal(); 695 Float n; 696 try { 697 n = Float.valueOf(proper); 698 } catch (NumberFormatException ex) { 699 // error already reported in scanner 700 n = Float.NaN; 701 } 702 if (n.floatValue() == 0.0f && !isZero(proper)) 703 error(token.pos, "fp.number.too.small"); 704 else if (n.floatValue() == Float.POSITIVE_INFINITY) 705 error(token.pos, "fp.number.too.large"); 706 else 707 t = F.at(pos).Literal(TypeTag.FLOAT, n); 708 break; 709 } 710 case DOUBLELITERAL: { 711 String proper = token.radix() == 16 ? 712 ("0x"+ token.stringVal()) : 713 token.stringVal(); 714 Double n; 715 try { 716 n = Double.valueOf(proper); 717 } catch (NumberFormatException ex) { 718 // error already reported in scanner 719 n = Double.NaN; 720 } 721 if (n.doubleValue() == 0.0d && !isZero(proper)) 722 error(token.pos, "fp.number.too.small"); 723 else if (n.doubleValue() == Double.POSITIVE_INFINITY) 724 error(token.pos, "fp.number.too.large"); 725 else 726 t = F.at(pos).Literal(TypeTag.DOUBLE, n); 727 break; 728 } 729 case CHARLITERAL: 730 t = F.at(pos).Literal( 731 TypeTag.CHAR, 732 token.stringVal().charAt(0) + 0); 733 break; 734 case STRINGLITERAL: 735 t = F.at(pos).Literal( 736 TypeTag.CLASS, 737 token.stringVal()); 738 break; 739 case TRUE: case FALSE: 740 t = F.at(pos).Literal( 741 TypeTag.BOOLEAN, 742 (token.kind == TRUE ? 1 : 0)); 743 break; 744 case NULL: 745 t = F.at(pos).Literal( 746 TypeTag.BOT, 747 null); 748 break; 749 default: 750 Assert.error(); 751 } 752 if (t == errorTree) 753 t = F.at(pos).Erroneous(); 754 storeEnd(t, token.endPos); 755 nextToken(); 756 return t; 757 } 758 //where 759 boolean isZero(String s) { 760 char[] cs = s.toCharArray(); 761 int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10); 762 int i = ((base==16) ? 2 : 0); 763 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++; 764 return !(i < cs.length && (Character.digit(cs[i], base) > 0)); 765 } 766 767 String strval(Name prefix) { 768 String s = token.stringVal(); 769 return prefix.isEmpty() ? s : prefix + s; 770 } 771 772 /** terms can be either expressions or types. 773 */ 774 public JCExpression parseExpression() { 775 return term(EXPR); 776 } 777 778 /** 779 * parses (optional) type annotations followed by a type. If the 780 * annotations are present before the type and are not consumed during array 781 * parsing, this method returns a {@link JCAnnotatedType} consisting of 782 * these annotations and the underlying type. Otherwise, it returns the 783 * underlying type. 784 * 785 * <p> 786 * 787 * Note that this method sets {@code mode} to {@code TYPE} first, before 788 * parsing annotations. 789 */ 790 public JCExpression parseType() { 791 List<JCAnnotation> annotations = typeAnnotationsOpt(); 792 return parseType(annotations); 793 } 794 795 public JCExpression parseType(List<JCAnnotation> annotations) { 796 JCExpression result = unannotatedType(); 797 798 if (annotations.nonEmpty()) { 799 result = insertAnnotationsToMostInner(result, annotations, false); 800 } 801 802 return result; 803 } 804 805 public JCExpression unannotatedType() { 806 return term(TYPE); 807 } 808 809 JCExpression term(int newmode) { 810 int prevmode = mode; 811 mode = newmode; 812 JCExpression t = term(); 813 lastmode = mode; 814 mode = prevmode; 815 return t; 816 } 817 818 /** 819 * {@literal 820 * Expression = Expression1 [ExpressionRest] 821 * ExpressionRest = [AssignmentOperator Expression1] 822 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | 823 * "&=" | "|=" | "^=" | 824 * "%=" | "<<=" | ">>=" | ">>>=" 825 * Type = Type1 826 * TypeNoParams = TypeNoParams1 827 * StatementExpression = Expression 828 * ConstantExpression = Expression 829 * } 830 */ 831 JCExpression term() { 832 JCExpression t = term1(); 833 if ((mode & EXPR) != 0 && 834 token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0) 835 return termRest(t); 836 else 837 return t; 838 } 839 840 JCExpression termRest(JCExpression t) { 841 switch (token.kind) { 842 case EQ: { 843 int pos = token.pos; 844 nextToken(); 845 mode = EXPR; 846 JCExpression t1 = term(); 847 return toP(F.at(pos).Assign(t, t1)); 848 } 849 case PLUSEQ: 850 case SUBEQ: 851 case STAREQ: 852 case SLASHEQ: 853 case PERCENTEQ: 854 case AMPEQ: 855 case BAREQ: 856 case CARETEQ: 857 case LTLTEQ: 858 case GTGTEQ: 859 case GTGTGTEQ: 860 int pos = token.pos; 861 TokenKind tk = token.kind; 862 nextToken(); 863 mode = EXPR; 864 JCExpression t1 = term(); 865 return F.at(pos).Assignop(optag(tk), t, t1); 866 default: 867 return t; 868 } 869 } 870 871 /** Expression1 = Expression2 [Expression1Rest] 872 * Type1 = Type2 873 * TypeNoParams1 = TypeNoParams2 874 */ 875 JCExpression term1() { 876 JCExpression t = term2(); 877 if ((mode & EXPR) != 0 && token.kind == QUES) { 878 mode = EXPR; 879 return term1Rest(t); 880 } else { 881 return t; 882 } 883 } 884 885 /** Expression1Rest = ["?" Expression ":" Expression1] 886 */ 887 JCExpression term1Rest(JCExpression t) { 888 if (token.kind == QUES) { 889 int pos = token.pos; 890 nextToken(); 891 JCExpression t1 = term(); 892 accept(COLON); 893 JCExpression t2 = term1(); 894 return F.at(pos).Conditional(t, t1, t2); 895 } else { 896 return t; 897 } 898 } 899 900 /** Expression2 = Expression3 [Expression2Rest] 901 * Type2 = Type3 902 * TypeNoParams2 = TypeNoParams3 903 */ 904 JCExpression term2() { 905 JCExpression t = term3(); 906 if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) { 907 mode = EXPR; 908 return term2Rest(t, TreeInfo.orPrec); 909 } else { 910 return t; 911 } 912 } 913 914 /* Expression2Rest = {infixop Expression3} 915 * | Expression3 instanceof Type 916 * infixop = "||" 917 * | "&&" 918 * | "|" 919 * | "^" 920 * | "&" 921 * | "==" | "!=" 922 * | "<" | ">" | "<=" | ">=" 923 * | "<<" | ">>" | ">>>" 924 * | "+" | "-" 925 * | "*" | "/" | "%" 926 */ 927 JCExpression term2Rest(JCExpression t, int minprec) { 928 JCExpression[] odStack = newOdStack(); 929 Token[] opStack = newOpStack(); 930 931 // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; 932 int top = 0; 933 odStack[0] = t; 934 int startPos = token.pos; 935 Token topOp = Tokens.DUMMY; 936 while (prec(token.kind) >= minprec) { 937 opStack[top] = topOp; 938 top++; 939 topOp = token; 940 nextToken(); 941 odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3(); 942 while (top > 0 && prec(topOp.kind) >= prec(token.kind)) { 943 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1], 944 odStack[top]); 945 top--; 946 topOp = opStack[top]; 947 } 948 } 949 Assert.check(top == 0); 950 t = odStack[0]; 951 952 if (t.hasTag(JCTree.Tag.PLUS)) { 953 StringBuilder buf = foldStrings(t); 954 if (buf != null) { 955 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString())); 956 } 957 } 958 959 odStackSupply.add(odStack); 960 opStackSupply.add(opStack); 961 return t; 962 } 963 //where 964 /** Construct a binary or type test node. 965 */ 966 private JCExpression makeOp(int pos, 967 TokenKind topOp, 968 JCExpression od1, 969 JCExpression od2) 970 { 971 if (topOp == INSTANCEOF) { 972 return F.at(pos).TypeTest(od1, od2); 973 } else { 974 return F.at(pos).Binary(optag(topOp), od1, od2); 975 } 976 } 977 /** If tree is a concatenation of string literals, replace it 978 * by a single literal representing the concatenated string. 979 */ 980 protected StringBuilder foldStrings(JCTree tree) { 981 if (!allowStringFolding) 982 return null; 983 List<String> buf = List.nil(); 984 while (true) { 985 if (tree.hasTag(LITERAL)) { 986 JCLiteral lit = (JCLiteral) tree; 987 if (lit.typetag == TypeTag.CLASS) { 988 StringBuilder sbuf = 989 new StringBuilder((String)lit.value); 990 while (buf.nonEmpty()) { 991 sbuf.append(buf.head); 992 buf = buf.tail; 993 } 994 return sbuf; 995 } 996 } else if (tree.hasTag(JCTree.Tag.PLUS)) { 997 JCBinary op = (JCBinary)tree; 998 if (op.rhs.hasTag(LITERAL)) { 999 JCLiteral lit = (JCLiteral) op.rhs; 1000 if (lit.typetag == TypeTag.CLASS) { 1001 buf = buf.prepend((String) lit.value); 1002 tree = op.lhs; 1003 continue; 1004 } 1005 } 1006 } 1007 return null; 1008 } 1009 } 1010 1011 /** optimization: To save allocating a new operand/operator stack 1012 * for every binary operation, we use supplys. 1013 */ 1014 ArrayList<JCExpression[]> odStackSupply = new ArrayList<JCExpression[]>(); 1015 ArrayList<Token[]> opStackSupply = new ArrayList<Token[]>(); 1016 1017 private JCExpression[] newOdStack() { 1018 if (odStackSupply.isEmpty()) 1019 return new JCExpression[infixPrecedenceLevels + 1]; 1020 return odStackSupply.remove(odStackSupply.size() - 1); 1021 } 1022 1023 private Token[] newOpStack() { 1024 if (opStackSupply.isEmpty()) 1025 return new Token[infixPrecedenceLevels + 1]; 1026 return opStackSupply.remove(opStackSupply.size() - 1); 1027 } 1028 1029 /** 1030 * Expression3 = PrefixOp Expression3 1031 * | "(" Expr | TypeNoParams ")" Expression3 1032 * | Primary {Selector} {PostfixOp} 1033 * 1034 * {@literal 1035 * Primary = "(" Expression ")" 1036 * | Literal 1037 * | [TypeArguments] THIS [Arguments] 1038 * | [TypeArguments] SUPER SuperSuffix 1039 * | NEW [TypeArguments] Creator 1040 * | "(" Arguments ")" "->" ( Expression | Block ) 1041 * | Ident "->" ( Expression | Block ) 1042 * | [Annotations] Ident { "." [Annotations] Ident } 1043 * | Expression3 MemberReferenceSuffix 1044 * [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) 1045 * | Arguments 1046 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) 1047 * ] 1048 * | BasicType BracketsOpt "." CLASS 1049 * } 1050 * 1051 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-" 1052 * PostfixOp = "++" | "--" 1053 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt 1054 * | BasicType 1055 * TypeNoParams3 = Ident { "." Ident } BracketsOpt 1056 * Selector = "." [TypeArguments] Ident [Arguments] 1057 * | "." THIS 1058 * | "." [TypeArguments] SUPER SuperSuffix 1059 * | "." NEW [TypeArguments] InnerCreator 1060 * | "[" Expression "]" 1061 * TypeSelector = "." Ident [TypeArguments] 1062 * SuperSuffix = Arguments | "." Ident [Arguments] 1063 */ 1064 protected JCExpression term3() { 1065 int pos = token.pos; 1066 JCExpression t; 1067 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR); 1068 switch (token.kind) { 1069 case QUES: 1070 if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) { 1071 mode = TYPE; 1072 return typeArgument(); 1073 } else 1074 return illegal(); 1075 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB: 1076 if (typeArgs == null && (mode & EXPR) != 0) { 1077 TokenKind tk = token.kind; 1078 nextToken(); 1079 mode = EXPR; 1080 if (tk == SUB && 1081 (token.kind == INTLITERAL || token.kind == LONGLITERAL) && 1082 token.radix() == 10) { 1083 mode = EXPR; 1084 t = literal(names.hyphen, pos); 1085 } else { 1086 t = term3(); 1087 return F.at(pos).Unary(unoptag(tk), t); 1088 } 1089 } else return illegal(); 1090 break; 1091 case LPAREN: 1092 if (typeArgs == null && (mode & EXPR) != 0) { 1093 ParensResult pres = analyzeParens(); 1094 switch (pres) { 1095 case CAST: 1096 accept(LPAREN); 1097 mode = TYPE; 1098 int pos1 = pos; 1099 List<JCExpression> targets = List.of(t = term3()); 1100 while (token.kind == AMP) { 1101 checkIntersectionTypesInCast(); 1102 accept(AMP); 1103 targets = targets.prepend(term3()); 1104 } 1105 if (targets.length() > 1) { 1106 t = toP(F.at(pos1).TypeIntersection(targets.reverse())); 1107 } 1108 accept(RPAREN); 1109 mode = EXPR; 1110 JCExpression t1 = term3(); 1111 return F.at(pos).TypeCast(t, t1); 1112 case IMPLICIT_LAMBDA: 1113 case EXPLICIT_LAMBDA: 1114 t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos); 1115 break; 1116 default: //PARENS 1117 accept(LPAREN); 1118 mode = EXPR; 1119 t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec))); 1120 accept(RPAREN); 1121 t = toP(F.at(pos).Parens(t)); 1122 break; 1123 } 1124 } else { 1125 return illegal(); 1126 } 1127 break; 1128 case THIS: 1129 if ((mode & EXPR) != 0) { 1130 mode = EXPR; 1131 t = to(F.at(pos).Ident(names._this)); 1132 nextToken(); 1133 if (typeArgs == null) 1134 t = argumentsOpt(null, t); 1135 else 1136 t = arguments(typeArgs, t); 1137 typeArgs = null; 1138 } else return illegal(); 1139 break; 1140 case SUPER: 1141 if ((mode & EXPR) != 0) { 1142 mode = EXPR; 1143 t = to(F.at(pos).Ident(names._super)); 1144 t = superSuffix(typeArgs, t); 1145 typeArgs = null; 1146 } else return illegal(); 1147 break; 1148 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL: 1149 case CHARLITERAL: case STRINGLITERAL: 1150 case TRUE: case FALSE: case NULL: 1151 if (typeArgs == null && (mode & EXPR) != 0) { 1152 mode = EXPR; 1153 t = literal(names.empty); 1154 } else return illegal(); 1155 break; 1156 case NEW: 1157 if (typeArgs != null) return illegal(); 1158 if ((mode & EXPR) != 0) { 1159 mode = EXPR; 1160 nextToken(); 1161 if (token.kind == LT) typeArgs = typeArguments(false); 1162 t = creator(pos, typeArgs); 1163 typeArgs = null; 1164 } else return illegal(); 1165 break; 1166 case MONKEYS_AT: 1167 // Only annotated cast types and method references are valid 1168 List<JCAnnotation> typeAnnos = typeAnnotationsOpt(); 1169 if (typeAnnos.isEmpty()) { 1170 // else there would be no '@' 1171 throw new AssertionError("Expected type annotations, but found none!"); 1172 } 1173 1174 JCExpression expr = term3(); 1175 1176 if ((mode & TYPE) == 0) { 1177 // Type annotations on class literals no longer legal 1178 switch (expr.getTag()) { 1179 case REFERENCE: { 1180 JCMemberReference mref = (JCMemberReference) expr; 1181 mref.expr = toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr)); 1182 t = mref; 1183 break; 1184 } 1185 case SELECT: { 1186 JCFieldAccess sel = (JCFieldAccess) expr; 1187 1188 if (sel.name != names._class) { 1189 return illegal(); 1190 } else { 1191 log.error(token.pos, "no.annotations.on.dot.class"); 1192 return expr; 1193 } 1194 } 1195 default: 1196 return illegal(typeAnnos.head.pos); 1197 } 1198 1199 } else { 1200 // Type annotations targeting a cast 1201 t = insertAnnotationsToMostInner(expr, typeAnnos, false); 1202 } 1203 break; 1204 case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM: 1205 if (typeArgs != null) return illegal(); 1206 if ((mode & EXPR) != 0 && peekToken(ARROW)) { 1207 t = lambdaExpressionOrStatement(false, false, pos); 1208 } else { 1209 t = toP(F.at(token.pos).Ident(ident())); 1210 loop: while (true) { 1211 pos = token.pos; 1212 final List<JCAnnotation> annos = typeAnnotationsOpt(); 1213 1214 // need to report an error later if LBRACKET is for array 1215 // index access rather than array creation level 1216 if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS) 1217 return illegal(annos.head.pos); 1218 1219 switch (token.kind) { 1220 case LBRACKET: 1221 nextToken(); 1222 if (token.kind == RBRACKET) { 1223 nextToken(); 1224 t = bracketsOpt(t); 1225 t = toP(F.at(pos).TypeArray(t)); 1226 if (annos.nonEmpty()) { 1227 t = toP(F.at(pos).AnnotatedType(annos, t)); 1228 } 1229 // .class is only allowed if there were no annotations 1230 JCExpression nt = bracketsSuffix(t); 1231 if (nt != t && (annos.nonEmpty() || TreeInfo.containsTypeAnnotation(t))) { 1232 // t and nt are different if bracketsSuffix parsed a .class. 1233 // The check for nonEmpty covers the case when the whole array is annotated. 1234 // Helper method isAnnotated looks for annos deeply within t. 1235 syntaxError("no.annotations.on.dot.class"); 1236 } 1237 t = nt; 1238 } else { 1239 if ((mode & EXPR) != 0) { 1240 mode = EXPR; 1241 JCExpression t1 = term(); 1242 if (!annos.isEmpty()) t = illegal(annos.head.pos); 1243 t = to(F.at(pos).Indexed(t, t1)); 1244 } 1245 accept(RBRACKET); 1246 } 1247 break loop; 1248 case LPAREN: 1249 if ((mode & EXPR) != 0) { 1250 mode = EXPR; 1251 t = arguments(typeArgs, t); 1252 if (!annos.isEmpty()) t = illegal(annos.head.pos); 1253 typeArgs = null; 1254 } 1255 break loop; 1256 case DOT: 1257 nextToken(); 1258 int oldmode = mode; 1259 mode &= ~NOPARAMS; 1260 typeArgs = typeArgumentsOpt(EXPR); 1261 mode = oldmode; 1262 if ((mode & EXPR) != 0) { 1263 switch (token.kind) { 1264 case CLASS: 1265 if (typeArgs != null) return illegal(); 1266 mode = EXPR; 1267 t = to(F.at(pos).Select(t, names._class)); 1268 nextToken(); 1269 break loop; 1270 case THIS: 1271 if (typeArgs != null) return illegal(); 1272 mode = EXPR; 1273 t = to(F.at(pos).Select(t, names._this)); 1274 nextToken(); 1275 break loop; 1276 case SUPER: 1277 mode = EXPR; 1278 t = to(F.at(pos).Select(t, names._super)); 1279 t = superSuffix(typeArgs, t); 1280 typeArgs = null; 1281 break loop; 1282 case NEW: 1283 if (typeArgs != null) return illegal(); 1284 mode = EXPR; 1285 int pos1 = token.pos; 1286 nextToken(); 1287 if (token.kind == LT) typeArgs = typeArguments(false); 1288 t = innerCreator(pos1, typeArgs, t); 1289 typeArgs = null; 1290 break loop; 1291 } 1292 } 1293 1294 List<JCAnnotation> tyannos = null; 1295 if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) { 1296 tyannos = typeAnnotationsOpt(); 1297 } 1298 // typeArgs saved for next loop iteration. 1299 t = toP(F.at(pos).Select(t, ident())); 1300 if (tyannos != null && tyannos.nonEmpty()) { 1301 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); 1302 } 1303 break; 1304 case ELLIPSIS: 1305 if (this.permitTypeAnnotationsPushBack) { 1306 this.typeAnnotationsPushedBack = annos; 1307 } else if (annos.nonEmpty()) { 1308 // Don't return here -- error recovery attempt 1309 illegal(annos.head.pos); 1310 } 1311 break loop; 1312 case LT: 1313 if ((mode & TYPE) == 0 && isUnboundMemberRef()) { 1314 //this is an unbound method reference whose qualifier 1315 //is a generic type i.e. A<S>::m 1316 int pos1 = token.pos; 1317 accept(LT); 1318 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); 1319 args.append(typeArgument()); 1320 while (token.kind == COMMA) { 1321 nextToken(); 1322 args.append(typeArgument()); 1323 } 1324 accept(GT); 1325 t = toP(F.at(pos1).TypeApply(t, args.toList())); 1326 checkGenerics(); 1327 while (token.kind == DOT) { 1328 nextToken(); 1329 mode = TYPE; 1330 t = toP(F.at(token.pos).Select(t, ident())); 1331 t = typeArgumentsOpt(t); 1332 } 1333 t = bracketsOpt(t); 1334 if (token.kind != COLCOL) { 1335 //method reference expected here 1336 t = illegal(); 1337 } 1338 mode = EXPR; 1339 return term3Rest(t, typeArgs); 1340 } 1341 break loop; 1342 default: 1343 break loop; 1344 } 1345 } 1346 } 1347 if (typeArgs != null) illegal(); 1348 t = typeArgumentsOpt(t); 1349 break; 1350 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 1351 case DOUBLE: case BOOLEAN: 1352 if (typeArgs != null) illegal(); 1353 t = bracketsSuffix(bracketsOpt(basicType())); 1354 break; 1355 case VOID: 1356 if (typeArgs != null) illegal(); 1357 if ((mode & EXPR) != 0) { 1358 nextToken(); 1359 if (token.kind == DOT) { 1360 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID)); 1361 t = bracketsSuffix(ti); 1362 } else { 1363 return illegal(pos); 1364 } 1365 } else { 1366 // Support the corner case of myMethodHandle.<void>invoke() by passing 1367 // a void type (like other primitive types) to the next phase. 1368 // The error will be reported in Attr.attribTypes or Attr.visitApply. 1369 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID)); 1370 nextToken(); 1371 return ti; 1372 //return illegal(); 1373 } 1374 break; 1375 default: 1376 return illegal(); 1377 } 1378 return term3Rest(t, typeArgs); 1379 } 1380 1381 JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) { 1382 if (typeArgs != null) illegal(); 1383 while (true) { 1384 int pos1 = token.pos; 1385 final List<JCAnnotation> annos = typeAnnotationsOpt(); 1386 1387 if (token.kind == LBRACKET) { 1388 nextToken(); 1389 if ((mode & TYPE) != 0) { 1390 int oldmode = mode; 1391 mode = TYPE; 1392 if (token.kind == RBRACKET) { 1393 nextToken(); 1394 t = bracketsOpt(t); 1395 t = toP(F.at(pos1).TypeArray(t)); 1396 if (token.kind == COLCOL) { 1397 mode = EXPR; 1398 continue; 1399 } 1400 if (annos.nonEmpty()) { 1401 t = toP(F.at(pos1).AnnotatedType(annos, t)); 1402 } 1403 return t; 1404 } 1405 mode = oldmode; 1406 } 1407 if ((mode & EXPR) != 0) { 1408 mode = EXPR; 1409 JCExpression t1 = term(); 1410 t = to(F.at(pos1).Indexed(t, t1)); 1411 } 1412 accept(RBRACKET); 1413 } else if (token.kind == DOT) { 1414 nextToken(); 1415 typeArgs = typeArgumentsOpt(EXPR); 1416 if (token.kind == SUPER && (mode & EXPR) != 0) { 1417 mode = EXPR; 1418 t = to(F.at(pos1).Select(t, names._super)); 1419 nextToken(); 1420 t = arguments(typeArgs, t); 1421 typeArgs = null; 1422 } else if (token.kind == NEW && (mode & EXPR) != 0) { 1423 if (typeArgs != null) return illegal(); 1424 mode = EXPR; 1425 int pos2 = token.pos; 1426 nextToken(); 1427 if (token.kind == LT) typeArgs = typeArguments(false); 1428 t = innerCreator(pos2, typeArgs, t); 1429 typeArgs = null; 1430 } else { 1431 List<JCAnnotation> tyannos = null; 1432 if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) { 1433 // is the mode check needed? 1434 tyannos = typeAnnotationsOpt(); 1435 } 1436 t = toP(F.at(pos1).Select(t, ident())); 1437 if (tyannos != null && tyannos.nonEmpty()) { 1438 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); 1439 } 1440 t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); 1441 typeArgs = null; 1442 } 1443 } else if ((mode & EXPR) != 0 && token.kind == COLCOL) { 1444 mode = EXPR; 1445 if (typeArgs != null) return illegal(); 1446 accept(COLCOL); 1447 t = memberReferenceSuffix(pos1, t); 1448 } else { 1449 if (!annos.isEmpty()) { 1450 if (permitTypeAnnotationsPushBack) 1451 typeAnnotationsPushedBack = annos; 1452 else 1453 return illegal(annos.head.pos); 1454 } 1455 break; 1456 } 1457 } 1458 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) { 1459 mode = EXPR; 1460 t = to(F.at(token.pos).Unary( 1461 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t)); 1462 nextToken(); 1463 } 1464 return toP(t); 1465 } 1466 1467 /** 1468 * If we see an identifier followed by a '<' it could be an unbound 1469 * method reference or a binary expression. To disambiguate, look for a 1470 * matching '>' and see if the subsequent terminal is either '.' or '::'. 1471 */ 1472 @SuppressWarnings("fallthrough") 1473 boolean isUnboundMemberRef() { 1474 int pos = 0, depth = 0; 1475 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) { 1476 switch (t.kind) { 1477 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER: 1478 case DOT: case RBRACKET: case LBRACKET: case COMMA: 1479 case BYTE: case SHORT: case INT: case LONG: case FLOAT: 1480 case DOUBLE: case BOOLEAN: case CHAR: 1481 case MONKEYS_AT: 1482 break; 1483 1484 case LPAREN: 1485 // skip annotation values 1486 int nesting = 0; 1487 for (; ; pos++) { 1488 TokenKind tk2 = S.token(pos).kind; 1489 switch (tk2) { 1490 case EOF: 1491 return false; 1492 case LPAREN: 1493 nesting++; 1494 break; 1495 case RPAREN: 1496 nesting--; 1497 if (nesting == 0) { 1498 continue outer; 1499 } 1500 break; 1501 } 1502 } 1503 1504 case LT: 1505 depth++; break; 1506 case GTGTGT: 1507 depth--; 1508 case GTGT: 1509 depth--; 1510 case GT: 1511 depth--; 1512 if (depth == 0) { 1513 TokenKind nextKind = S.token(pos + 1).kind; 1514 return 1515 nextKind == TokenKind.DOT || 1516 nextKind == TokenKind.LBRACKET || 1517 nextKind == TokenKind.COLCOL; 1518 } 1519 break; 1520 default: 1521 return false; 1522 } 1523 } 1524 } 1525 1526 /** 1527 * If we see an identifier followed by a '<' it could be an unbound 1528 * method reference or a binary expression. To disambiguate, look for a 1529 * matching '>' and see if the subsequent terminal is either '.' or '::'. 1530 */ 1531 @SuppressWarnings("fallthrough") 1532 ParensResult analyzeParens() { 1533 int depth = 0; 1534 boolean type = false; 1535 outer: for (int lookahead = 0 ; ; lookahead++) { 1536 TokenKind tk = S.token(lookahead).kind; 1537 switch (tk) { 1538 case COMMA: 1539 type = true; 1540 case EXTENDS: case SUPER: case DOT: case AMP: 1541 //skip 1542 break; 1543 case QUES: 1544 if (peekToken(lookahead, EXTENDS) || 1545 peekToken(lookahead, SUPER)) { 1546 //wildcards 1547 type = true; 1548 } 1549 break; 1550 case BYTE: case SHORT: case INT: case LONG: case FLOAT: 1551 case DOUBLE: case BOOLEAN: case CHAR: 1552 if (peekToken(lookahead, RPAREN)) { 1553 //Type, ')' -> cast 1554 return ParensResult.CAST; 1555 } else if (peekToken(lookahead, LAX_IDENTIFIER)) { 1556 //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda 1557 return ParensResult.EXPLICIT_LAMBDA; 1558 } 1559 break; 1560 case LPAREN: 1561 if (lookahead != 0) { 1562 // '(' in a non-starting position -> parens 1563 return ParensResult.PARENS; 1564 } else if (peekToken(lookahead, RPAREN)) { 1565 // '(', ')' -> explicit lambda 1566 return ParensResult.EXPLICIT_LAMBDA; 1567 } 1568 break; 1569 case RPAREN: 1570 // if we have seen something that looks like a type, 1571 // then it's a cast expression 1572 if (type) return ParensResult.CAST; 1573 // otherwise, disambiguate cast vs. parenthesized expression 1574 // based on subsequent token. 1575 switch (S.token(lookahead + 1).kind) { 1576 /*case PLUSPLUS: case SUBSUB: */ 1577 case BANG: case TILDE: 1578 case LPAREN: case THIS: case SUPER: 1579 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: 1580 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: 1581 case TRUE: case FALSE: case NULL: 1582 case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE: 1583 case BYTE: case SHORT: case CHAR: case INT: 1584 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: 1585 return ParensResult.CAST; 1586 default: 1587 return ParensResult.PARENS; 1588 } 1589 case UNDERSCORE: 1590 case ASSERT: 1591 case ENUM: 1592 case IDENTIFIER: 1593 if (peekToken(lookahead, LAX_IDENTIFIER)) { 1594 // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda 1595 return ParensResult.EXPLICIT_LAMBDA; 1596 } else if (peekToken(lookahead, RPAREN, ARROW)) { 1597 // Identifier, ')' '->' -> implicit lambda 1598 return ParensResult.IMPLICIT_LAMBDA; 1599 } 1600 break; 1601 case FINAL: 1602 case ELLIPSIS: 1603 //those can only appear in explicit lambdas 1604 return ParensResult.EXPLICIT_LAMBDA; 1605 case MONKEYS_AT: 1606 type = true; 1607 lookahead += 1; //skip '@' 1608 while (peekToken(lookahead, DOT)) { 1609 lookahead += 2; 1610 } 1611 if (peekToken(lookahead, LPAREN)) { 1612 lookahead++; 1613 //skip annotation values 1614 int nesting = 0; 1615 for (; ; lookahead++) { 1616 TokenKind tk2 = S.token(lookahead).kind; 1617 switch (tk2) { 1618 case EOF: 1619 return ParensResult.PARENS; 1620 case LPAREN: 1621 nesting++; 1622 break; 1623 case RPAREN: 1624 nesting--; 1625 if (nesting == 0) { 1626 continue outer; 1627 } 1628 break; 1629 } 1630 } 1631 } 1632 break; 1633 case LBRACKET: 1634 if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) { 1635 // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda 1636 return ParensResult.EXPLICIT_LAMBDA; 1637 } else if (peekToken(lookahead, RBRACKET, RPAREN) || 1638 peekToken(lookahead, RBRACKET, AMP)) { 1639 // '[', ']', ')' -> cast 1640 // '[', ']', '&' -> cast (intersection type) 1641 return ParensResult.CAST; 1642 } else if (peekToken(lookahead, RBRACKET)) { 1643 //consume the ']' and skip 1644 type = true; 1645 lookahead++; 1646 break; 1647 } else { 1648 return ParensResult.PARENS; 1649 } 1650 case LT: 1651 depth++; break; 1652 case GTGTGT: 1653 depth--; 1654 case GTGT: 1655 depth--; 1656 case GT: 1657 depth--; 1658 if (depth == 0) { 1659 if (peekToken(lookahead, RPAREN) || 1660 peekToken(lookahead, AMP)) { 1661 // '>', ')' -> cast 1662 // '>', '&' -> cast 1663 return ParensResult.CAST; 1664 } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) || 1665 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) || 1666 peekToken(lookahead, ELLIPSIS)) { 1667 // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda 1668 // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda 1669 // '>', '...' -> explicit lambda 1670 return ParensResult.EXPLICIT_LAMBDA; 1671 } 1672 //it looks a type, but could still be (i) a cast to generic type, 1673 //(ii) an unbound method reference or (iii) an explicit lambda 1674 type = true; 1675 break; 1676 } else if (depth < 0) { 1677 //unbalanced '<', '>' - not a generic type 1678 return ParensResult.PARENS; 1679 } 1680 break; 1681 default: 1682 //this includes EOF 1683 return ParensResult.PARENS; 1684 } 1685 } 1686 } 1687 1688 /** Accepts all identifier-like tokens */ 1689 Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() { 1690 public boolean accepts(TokenKind t) { 1691 return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM; 1692 } 1693 }; 1694 1695 enum ParensResult { 1696 CAST, 1697 EXPLICIT_LAMBDA, 1698 IMPLICIT_LAMBDA, 1699 PARENS; 1700 } 1701 1702 JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) { 1703 List<JCVariableDecl> params = explicitParams ? 1704 formalParameters(true) : 1705 implicitParameters(hasParens); 1706 1707 return lambdaExpressionOrStatementRest(params, pos); 1708 } 1709 1710 JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) { 1711 checkLambda(); 1712 accept(ARROW); 1713 1714 return token.kind == LBRACE ? 1715 lambdaStatement(args, pos, pos) : 1716 lambdaExpression(args, pos); 1717 } 1718 1719 JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) { 1720 JCBlock block = block(pos2, 0); 1721 return toP(F.at(pos).Lambda(args, block)); 1722 } 1723 1724 JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) { 1725 JCTree expr = parseExpression(); 1726 return toP(F.at(pos).Lambda(args, expr)); 1727 } 1728 1729 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments] 1730 */ 1731 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { 1732 nextToken(); 1733 if (token.kind == LPAREN || typeArgs != null) { 1734 t = arguments(typeArgs, t); 1735 } else if (token.kind == COLCOL) { 1736 if (typeArgs != null) return illegal(); 1737 t = memberReferenceSuffix(t); 1738 } else { 1739 int pos = token.pos; 1740 accept(DOT); 1741 typeArgs = (token.kind == LT) ? typeArguments(false) : null; 1742 t = toP(F.at(pos).Select(t, ident())); 1743 t = argumentsOpt(typeArgs, t); 1744 } 1745 return t; 1746 } 1747 1748 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN 1749 */ 1750 JCPrimitiveTypeTree basicType() { 1751 JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind))); 1752 nextToken(); 1753 return t; 1754 } 1755 1756 /** ArgumentsOpt = [ Arguments ] 1757 */ 1758 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) { 1759 if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) { 1760 mode = EXPR; 1761 return arguments(typeArgs, t); 1762 } else { 1763 return t; 1764 } 1765 } 1766 1767 /** Arguments = "(" [Expression { COMMA Expression }] ")" 1768 */ 1769 List<JCExpression> arguments() { 1770 ListBuffer<JCExpression> args = lb(); 1771 if (token.kind == LPAREN) { 1772 nextToken(); 1773 if (token.kind != RPAREN) { 1774 args.append(parseExpression()); 1775 while (token.kind == COMMA) { 1776 nextToken(); 1777 args.append(parseExpression()); 1778 } 1779 } 1780 accept(RPAREN); 1781 } else { 1782 syntaxError(token.pos, "expected", LPAREN); 1783 } 1784 return args.toList(); 1785 } 1786 1787 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) { 1788 int pos = token.pos; 1789 List<JCExpression> args = arguments(); 1790 return toP(F.at(pos).Apply(typeArgs, t, args)); 1791 } 1792 1793 /** TypeArgumentsOpt = [ TypeArguments ] 1794 */ 1795 JCExpression typeArgumentsOpt(JCExpression t) { 1796 if (token.kind == LT && 1797 (mode & TYPE) != 0 && 1798 (mode & NOPARAMS) == 0) { 1799 mode = TYPE; 1800 checkGenerics(); 1801 return typeArguments(t, false); 1802 } else { 1803 return t; 1804 } 1805 } 1806 List<JCExpression> typeArgumentsOpt() { 1807 return typeArgumentsOpt(TYPE); 1808 } 1809 1810 List<JCExpression> typeArgumentsOpt(int useMode) { 1811 if (token.kind == LT) { 1812 checkGenerics(); 1813 if ((mode & useMode) == 0 || 1814 (mode & NOPARAMS) != 0) { 1815 illegal(); 1816 } 1817 mode = useMode; 1818 return typeArguments(false); 1819 } 1820 return null; 1821 } 1822 1823 /** 1824 * {@literal 1825 * TypeArguments = "<" TypeArgument {"," TypeArgument} ">" 1826 * } 1827 */ 1828 List<JCExpression> typeArguments(boolean diamondAllowed) { 1829 if (token.kind == LT) { 1830 nextToken(); 1831 if (token.kind == GT && diamondAllowed) { 1832 checkDiamond(); 1833 mode |= DIAMOND; 1834 nextToken(); 1835 return List.nil(); 1836 } else { 1837 ListBuffer<JCExpression> args = ListBuffer.lb(); 1838 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 1839 while (token.kind == COMMA) { 1840 nextToken(); 1841 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 1842 } 1843 switch (token.kind) { 1844 1845 case GTGTGTEQ: case GTGTEQ: case GTEQ: 1846 case GTGTGT: case GTGT: 1847 token = S.split(); 1848 break; 1849 case GT: 1850 nextToken(); 1851 break; 1852 default: 1853 args.append(syntaxError(token.pos, "expected", GT)); 1854 break; 1855 } 1856 return args.toList(); 1857 } 1858 } else { 1859 return List.<JCExpression>of(syntaxError(token.pos, "expected", LT)); 1860 } 1861 } 1862 1863 /** 1864 * {@literal 1865 * TypeArgument = Type 1866 * | [Annotations] "?" 1867 * | [Annotations] "?" EXTENDS Type {"&" Type} 1868 * | [Annotations] "?" SUPER Type 1869 * } 1870 */ 1871 JCExpression typeArgument() { 1872 List<JCAnnotation> annotations = typeAnnotationsOpt(); 1873 if (token.kind != QUES) return parseType(annotations); 1874 int pos = token.pos; 1875 nextToken(); 1876 JCExpression result; 1877 if (token.kind == EXTENDS) { 1878 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); 1879 nextToken(); 1880 JCExpression bound = parseType(); 1881 result = F.at(pos).Wildcard(t, bound); 1882 } else if (token.kind == SUPER) { 1883 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); 1884 nextToken(); 1885 JCExpression bound = parseType(); 1886 result = F.at(pos).Wildcard(t, bound); 1887 } else if (LAX_IDENTIFIER.accepts(token.kind)) { 1888 //error recovery 1889 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 1890 JCExpression wc = toP(F.at(pos).Wildcard(t, null)); 1891 JCIdent id = toP(F.at(token.pos).Ident(ident())); 1892 JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id)); 1893 reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER); 1894 result = err; 1895 } else { 1896 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); 1897 result = toP(F.at(pos).Wildcard(t, null)); 1898 } 1899 if (!annotations.isEmpty()) { 1900 result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result)); 1901 } 1902 return result; 1903 } 1904 1905 JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) { 1906 int pos = token.pos; 1907 List<JCExpression> args = typeArguments(diamondAllowed); 1908 return toP(F.at(pos).TypeApply(t, args)); 1909 } 1910 1911 /** 1912 * BracketsOpt = { [Annotations] "[" "]" }* 1913 * 1914 * <p> 1915 * 1916 * <code>annotations</code> is the list of annotations targeting 1917 * the expression <code>t</code>. 1918 */ 1919 private JCExpression bracketsOpt(JCExpression t, 1920 List<JCAnnotation> annotations) { 1921 List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt(); 1922 1923 if (token.kind == LBRACKET) { 1924 int pos = token.pos; 1925 nextToken(); 1926 t = bracketsOptCont(t, pos, nextLevelAnnotations); 1927 } else if (!nextLevelAnnotations.isEmpty()) { 1928 if (permitTypeAnnotationsPushBack) { 1929 this.typeAnnotationsPushedBack = nextLevelAnnotations; 1930 } else { 1931 return illegal(nextLevelAnnotations.head.pos); 1932 } 1933 } 1934 1935 if (!annotations.isEmpty()) { 1936 t = toP(F.at(token.pos).AnnotatedType(annotations, t)); 1937 } 1938 return t; 1939 } 1940 1941 /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ] 1942 */ 1943 private JCExpression bracketsOpt(JCExpression t) { 1944 return bracketsOpt(t, List.<JCAnnotation>nil()); 1945 } 1946 1947 private JCExpression bracketsOptCont(JCExpression t, int pos, 1948 List<JCAnnotation> annotations) { 1949 accept(RBRACKET); 1950 t = bracketsOpt(t); 1951 t = toP(F.at(pos).TypeArray(t)); 1952 if (annotations.nonEmpty()) { 1953 t = toP(F.at(pos).AnnotatedType(annotations, t)); 1954 } 1955 return t; 1956 } 1957 1958 /** BracketsSuffixExpr = "." CLASS 1959 * BracketsSuffixType = 1960 */ 1961 JCExpression bracketsSuffix(JCExpression t) { 1962 if ((mode & EXPR) != 0 && token.kind == DOT) { 1963 mode = EXPR; 1964 int pos = token.pos; 1965 nextToken(); 1966 accept(CLASS); 1967 if (token.pos == endPosTable.errorEndPos) { 1968 // error recovery 1969 Name name; 1970 if (LAX_IDENTIFIER.accepts(token.kind)) { 1971 name = token.name(); 1972 nextToken(); 1973 } else { 1974 name = names.error; 1975 } 1976 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name)))); 1977 } else { 1978 t = toP(F.at(pos).Select(t, names._class)); 1979 } 1980 } else if ((mode & TYPE) != 0) { 1981 if (token.kind != COLCOL) { 1982 mode = TYPE; 1983 } 1984 } else if (token.kind != COLCOL) { 1985 syntaxError(token.pos, "dot.class.expected"); 1986 } 1987 return t; 1988 } 1989 1990 /** 1991 * MemberReferenceSuffix = "::" [TypeArguments] Ident 1992 * | "::" [TypeArguments] "new" 1993 */ 1994 JCExpression memberReferenceSuffix(JCExpression t) { 1995 int pos1 = token.pos; 1996 accept(COLCOL); 1997 return memberReferenceSuffix(pos1, t); 1998 } 1999 2000 JCExpression memberReferenceSuffix(int pos1, JCExpression t) { 2001 checkMethodReferences(); 2002 mode = EXPR; 2003 List<JCExpression> typeArgs = null; 2004 if (token.kind == LT) { 2005 typeArgs = typeArguments(false); 2006 } 2007 Name refName; 2008 ReferenceMode refMode; 2009 if (token.kind == NEW) { 2010 refMode = ReferenceMode.NEW; 2011 refName = names.init; 2012 nextToken(); 2013 } else { 2014 refMode = ReferenceMode.INVOKE; 2015 refName = ident(); 2016 } 2017 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs)); 2018 } 2019 2020 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) 2021 */ 2022 JCExpression creator(int newpos, List<JCExpression> typeArgs) { 2023 List<JCAnnotation> newAnnotations = annotationsOpt(Tag.ANNOTATION); 2024 2025 switch (token.kind) { 2026 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 2027 case DOUBLE: case BOOLEAN: 2028 if (typeArgs == null) { 2029 if (newAnnotations.isEmpty()) { 2030 return arrayCreatorRest(newpos, basicType()); 2031 } else { 2032 return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType()))); 2033 } 2034 } 2035 break; 2036 default: 2037 } 2038 JCExpression t = qualident(true); 2039 2040 int oldmode = mode; 2041 mode = TYPE; 2042 boolean diamondFound = false; 2043 int lastTypeargsPos = -1; 2044 if (token.kind == LT) { 2045 checkGenerics(); 2046 lastTypeargsPos = token.pos; 2047 t = typeArguments(t, true); 2048 diamondFound = (mode & DIAMOND) != 0; 2049 } 2050 while (token.kind == DOT) { 2051 if (diamondFound) { 2052 //cannot select after a diamond 2053 illegal(); 2054 } 2055 int pos = token.pos; 2056 nextToken(); 2057 List<JCAnnotation> tyannos = typeAnnotationsOpt(); 2058 t = toP(F.at(pos).Select(t, ident())); 2059 2060 if (tyannos != null && tyannos.nonEmpty()) { 2061 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); 2062 } 2063 2064 if (token.kind == LT) { 2065 lastTypeargsPos = token.pos; 2066 checkGenerics(); 2067 t = typeArguments(t, true); 2068 diamondFound = (mode & DIAMOND) != 0; 2069 } 2070 } 2071 mode = oldmode; 2072 if (token.kind == LBRACKET || token.kind == MONKEYS_AT) { 2073 // handle type annotations for non primitive arrays 2074 if (newAnnotations.nonEmpty()) { 2075 t = insertAnnotationsToMostInner(t, newAnnotations, false); 2076 } 2077 2078 JCExpression e = arrayCreatorRest(newpos, t); 2079 if (diamondFound) { 2080 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond"); 2081 return toP(F.at(newpos).Erroneous(List.of(e))); 2082 } 2083 else if (typeArgs != null) { 2084 int pos = newpos; 2085 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) { 2086 // note: this should always happen but we should 2087 // not rely on this as the parser is continuously 2088 // modified to improve error recovery. 2089 pos = typeArgs.head.pos; 2090 } 2091 setErrorEndPos(S.prevToken().endPos); 2092 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e)); 2093 reportSyntaxError(err, "cannot.create.array.with.type.arguments"); 2094 return toP(err); 2095 } 2096 return e; 2097 } else if (token.kind == LPAREN) { 2098 JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t); 2099 if (newClass.def != null) { 2100 assert newClass.def.mods.annotations.isEmpty(); 2101 if (newAnnotations.nonEmpty()) { 2102 // Add type and declaration annotations to the new class; 2103 // com.sun.tools.javac.code.TypeAnnotations.TypeAnnotationPositions.visitNewClass(JCNewClass) 2104 // will later remove all type annotations and only leave the 2105 // declaration annotations. 2106 newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos); 2107 newClass.def.mods.annotations = newAnnotations; 2108 } 2109 } else { 2110 // handle type annotations for instantiations 2111 if (newAnnotations.nonEmpty()) { 2112 t = insertAnnotationsToMostInner(t, newAnnotations, false); 2113 newClass.clazz = t; 2114 } 2115 } 2116 return newClass; 2117 } else { 2118 setErrorEndPos(token.pos); 2119 reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET); 2120 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null)); 2121 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t))); 2122 } 2123 } 2124 2125 /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest 2126 */ 2127 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) { 2128 List<JCAnnotation> newAnnotations = typeAnnotationsOpt(); 2129 2130 JCExpression t = toP(F.at(token.pos).Ident(ident())); 2131 2132 if (newAnnotations.nonEmpty()) { 2133 t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t)); 2134 } 2135 2136 if (token.kind == LT) { 2137 int oldmode = mode; 2138 checkGenerics(); 2139 t = typeArguments(t, true); 2140 mode = oldmode; 2141 } 2142 return classCreatorRest(newpos, encl, typeArgs, t); 2143 } 2144 2145 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer 2146 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt ) 2147 */ 2148 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { 2149 List<JCAnnotation> annos = typeAnnotationsOpt(); 2150 2151 accept(LBRACKET); 2152 if (token.kind == RBRACKET) { 2153 accept(RBRACKET); 2154 elemtype = bracketsOpt(elemtype, annos); 2155 if (token.kind == LBRACE) { 2156 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype); 2157 if (annos.nonEmpty()) { 2158 // when an array initializer is present then 2159 // the parsed annotations should target the 2160 // new array tree 2161 // bracketsOpt inserts the annotation in 2162 // elemtype, and it needs to be corrected 2163 // 2164 JCAnnotatedType annotated = (JCAnnotatedType)elemtype; 2165 assert annotated.annotations == annos; 2166 na.annotations = annotated.annotations; 2167 na.elemtype = annotated.underlyingType; 2168 } 2169 return na; 2170 } else { 2171 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null)); 2172 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing"); 2173 } 2174 } else { 2175 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>(); 2176 2177 // maintain array dimension type annotations 2178 ListBuffer<List<JCAnnotation>> dimAnnotations = ListBuffer.lb(); 2179 dimAnnotations.append(annos); 2180 2181 dims.append(parseExpression()); 2182 accept(RBRACKET); 2183 while (token.kind == LBRACKET 2184 || token.kind == MONKEYS_AT) { 2185 List<JCAnnotation> maybeDimAnnos = typeAnnotationsOpt(); 2186 int pos = token.pos; 2187 nextToken(); 2188 if (token.kind == RBRACKET) { 2189 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); 2190 } else { 2191 if (token.kind == RBRACKET) { // no dimension 2192 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); 2193 } else { 2194 dimAnnotations.append(maybeDimAnnos); 2195 dims.append(parseExpression()); 2196 accept(RBRACKET); 2197 } 2198 } 2199 } 2200 2201 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); 2202 na.dimAnnotations = dimAnnotations.toList(); 2203 return na; 2204 } 2205 } 2206 2207 /** ClassCreatorRest = Arguments [ClassBody] 2208 */ 2209 JCNewClass classCreatorRest(int newpos, 2210 JCExpression encl, 2211 List<JCExpression> typeArgs, 2212 JCExpression t) 2213 { 2214 List<JCExpression> args = arguments(); 2215 JCClassDecl body = null; 2216 if (token.kind == LBRACE) { 2217 int pos = token.pos; 2218 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 2219 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 2220 body = toP(F.at(pos).AnonymousClassDef(mods, defs)); 2221 } 2222 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); 2223 } 2224 2225 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" 2226 */ 2227 JCExpression arrayInitializer(int newpos, JCExpression t) { 2228 accept(LBRACE); 2229 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>(); 2230 if (token.kind == COMMA) { 2231 nextToken(); 2232 } else if (token.kind != RBRACE) { 2233 elems.append(variableInitializer()); 2234 while (token.kind == COMMA) { 2235 nextToken(); 2236 if (token.kind == RBRACE) break; 2237 elems.append(variableInitializer()); 2238 } 2239 } 2240 accept(RBRACE); 2241 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList())); 2242 } 2243 2244 /** VariableInitializer = ArrayInitializer | Expression 2245 */ 2246 public JCExpression variableInitializer() { 2247 return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression(); 2248 } 2249 2250 /** ParExpression = "(" Expression ")" 2251 */ 2252 JCExpression parExpression() { 2253 int pos = token.pos; 2254 accept(LPAREN); 2255 JCExpression t = parseExpression(); 2256 accept(RPAREN); 2257 return toP(F.at(pos).Parens(t)); 2258 } 2259 2260 /** Block = "{" BlockStatements "}" 2261 */ 2262 JCBlock block(int pos, long flags) { 2263 accept(LBRACE); 2264 List<JCStatement> stats = blockStatements(); 2265 JCBlock t = F.at(pos).Block(flags, stats); 2266 while (token.kind == CASE || token.kind == DEFAULT) { 2267 syntaxError("orphaned", token.kind); 2268 switchBlockStatementGroups(); 2269 } 2270 // the Block node has a field "endpos" for first char of last token, which is 2271 // usually but not necessarily the last char of the last token. 2272 t.endpos = token.pos; 2273 accept(RBRACE); 2274 return toP(t); 2275 } 2276 2277 public JCBlock block() { 2278 return block(token.pos, 0); 2279 } 2280 2281 /** BlockStatements = { BlockStatement } 2282 * BlockStatement = LocalVariableDeclarationStatement 2283 * | ClassOrInterfaceOrEnumDeclaration 2284 * | [Ident ":"] Statement 2285 * LocalVariableDeclarationStatement 2286 * = { FINAL | '@' Annotation } Type VariableDeclarators ";" 2287 */ 2288 @SuppressWarnings("fallthrough") 2289 List<JCStatement> blockStatements() { 2290 //todo: skip to anchor on error(?) 2291 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); 2292 while (true) { 2293 List<JCStatement> stat = blockStatement(); 2294 if (stat.isEmpty()) { 2295 return stats.toList(); 2296 } else { 2297 if (token.pos <= endPosTable.errorEndPos) { 2298 skip(false, true, true, true); 2299 } 2300 stats.addAll(stat); 2301 } 2302 } 2303 } 2304 2305 /* 2306 * This method parses a statement treating it as a block, relaxing the 2307 * JLS restrictions, allows us to parse more faulty code, doing so 2308 * enables us to provide better and accurate diagnostics to the user. 2309 */ 2310 JCStatement parseStatementAsBlock() { 2311 int pos = token.pos; 2312 List<JCStatement> stats = blockStatement(); 2313 if (stats.isEmpty()) { 2314 JCErroneous e = F.at(pos).Erroneous(); 2315 error(e, "illegal.start.of.stmt"); 2316 return F.at(pos).Exec(e); 2317 } else { 2318 JCStatement first = stats.head; 2319 String error = null; 2320 switch (first.getTag()) { 2321 case CLASSDEF: 2322 error = "class.not.allowed"; 2323 break; 2324 case VARDEF: 2325 error = "variable.not.allowed"; 2326 break; 2327 } 2328 if (error != null) { 2329 error(first, error); 2330 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats)); 2331 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist))); 2332 } 2333 return first; 2334 } 2335 } 2336 2337 @SuppressWarnings("fallthrough") 2338 List<JCStatement> blockStatement() { 2339 //todo: skip to anchor on error(?) 2340 int pos = token.pos; 2341 switch (token.kind) { 2342 case RBRACE: case CASE: case DEFAULT: case EOF: 2343 return List.nil(); 2344 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: 2345 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: 2346 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: 2347 return List.of(parseStatement()); 2348 case MONKEYS_AT: 2349 case FINAL: { 2350 Comment dc = token.comment(CommentStyle.JAVADOC); 2351 JCModifiers mods = modifiersOpt(); 2352 if (token.kind == INTERFACE || 2353 token.kind == CLASS || 2354 allowEnums && token.kind == ENUM) { 2355 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); 2356 } else { 2357 JCExpression t = parseType(); 2358 ListBuffer<JCStatement> stats = 2359 variableDeclarators(mods, t, new ListBuffer<JCStatement>()); 2360 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 2361 storeEnd(stats.last(), token.endPos); 2362 accept(SEMI); 2363 return stats.toList(); 2364 } 2365 } 2366 case ABSTRACT: case STRICTFP: { 2367 Comment dc = token.comment(CommentStyle.JAVADOC); 2368 JCModifiers mods = modifiersOpt(); 2369 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); 2370 } 2371 case INTERFACE: 2372 case CLASS: 2373 Comment dc = token.comment(CommentStyle.JAVADOC); 2374 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); 2375 case ENUM: 2376 case ASSERT: 2377 if (allowEnums && token.kind == ENUM) { 2378 error(token.pos, "local.enum"); 2379 dc = token.comment(CommentStyle.JAVADOC); 2380 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); 2381 } else if (allowAsserts && token.kind == ASSERT) { 2382 return List.of(parseStatement()); 2383 } 2384 /* fall through to default */ 2385 default: 2386 Token prevToken = token; 2387 JCExpression t = term(EXPR | TYPE); 2388 if (token.kind == COLON && t.hasTag(IDENT)) { 2389 nextToken(); 2390 JCStatement stat = parseStatement(); 2391 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat)); 2392 } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { 2393 pos = token.pos; 2394 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 2395 F.at(pos); 2396 ListBuffer<JCStatement> stats = 2397 variableDeclarators(mods, t, new ListBuffer<JCStatement>()); 2398 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 2399 storeEnd(stats.last(), token.endPos); 2400 accept(SEMI); 2401 return stats.toList(); 2402 } else { 2403 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 2404 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t))); 2405 accept(SEMI); 2406 return List.<JCStatement>of(expr); 2407 } 2408 } 2409 } 2410 2411 /** Statement = 2412 * Block 2413 * | IF ParExpression Statement [ELSE Statement] 2414 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement 2415 * | FOR "(" FormalParameter : Expression ")" Statement 2416 * | WHILE ParExpression Statement 2417 * | DO Statement WHILE ParExpression ";" 2418 * | TRY Block ( Catches | [Catches] FinallyPart ) 2419 * | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart] 2420 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" 2421 * | SYNCHRONIZED ParExpression Block 2422 * | RETURN [Expression] ";" 2423 * | THROW Expression ";" 2424 * | BREAK [Ident] ";" 2425 * | CONTINUE [Ident] ";" 2426 * | ASSERT Expression [ ":" Expression ] ";" 2427 * | ";" 2428 * | ExpressionStatement 2429 * | Ident ":" Statement 2430 */ 2431 @SuppressWarnings("fallthrough") 2432 public JCStatement parseStatement() { 2433 int pos = token.pos; 2434 switch (token.kind) { 2435 case LBRACE: 2436 return block(); 2437 case IF: { 2438 nextToken(); 2439 JCExpression cond = parExpression(); 2440 JCStatement thenpart = parseStatementAsBlock(); 2441 JCStatement elsepart = null; 2442 if (token.kind == ELSE) { 2443 nextToken(); 2444 elsepart = parseStatementAsBlock(); 2445 } 2446 return F.at(pos).If(cond, thenpart, elsepart); 2447 } 2448 case FOR: { 2449 nextToken(); 2450 accept(LPAREN); 2451 List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit(); 2452 if (inits.length() == 1 && 2453 inits.head.hasTag(VARDEF) && 2454 ((JCVariableDecl) inits.head).init == null && 2455 token.kind == COLON) { 2456 checkForeach(); 2457 JCVariableDecl var = (JCVariableDecl)inits.head; 2458 accept(COLON); 2459 JCExpression expr = parseExpression(); 2460 accept(RPAREN); 2461 JCStatement body = parseStatementAsBlock(); 2462 return F.at(pos).ForeachLoop(var, expr, body); 2463 } else { 2464 accept(SEMI); 2465 JCExpression cond = token.kind == SEMI ? null : parseExpression(); 2466 accept(SEMI); 2467 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); 2468 accept(RPAREN); 2469 JCStatement body = parseStatementAsBlock(); 2470 return F.at(pos).ForLoop(inits, cond, steps, body); 2471 } 2472 } 2473 case WHILE: { 2474 nextToken(); 2475 JCExpression cond = parExpression(); 2476 JCStatement body = parseStatementAsBlock(); 2477 return F.at(pos).WhileLoop(cond, body); 2478 } 2479 case DO: { 2480 nextToken(); 2481 JCStatement body = parseStatementAsBlock(); 2482 accept(WHILE); 2483 JCExpression cond = parExpression(); 2484 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond)); 2485 accept(SEMI); 2486 return t; 2487 } 2488 case TRY: { 2489 nextToken(); 2490 List<JCTree> resources = List.<JCTree>nil(); 2491 if (token.kind == LPAREN) { 2492 checkTryWithResources(); 2493 nextToken(); 2494 resources = resources(); 2495 accept(RPAREN); 2496 } 2497 JCBlock body = block(); 2498 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>(); 2499 JCBlock finalizer = null; 2500 if (token.kind == CATCH || token.kind == FINALLY) { 2501 while (token.kind == CATCH) catchers.append(catchClause()); 2502 if (token.kind == FINALLY) { 2503 nextToken(); 2504 finalizer = block(); 2505 } 2506 } else { 2507 if (allowTWR) { 2508 if (resources.isEmpty()) 2509 error(pos, "try.without.catch.finally.or.resource.decls"); 2510 } else 2511 error(pos, "try.without.catch.or.finally"); 2512 } 2513 return F.at(pos).Try(resources, body, catchers.toList(), finalizer); 2514 } 2515 case SWITCH: { 2516 nextToken(); 2517 JCExpression selector = parExpression(); 2518 accept(LBRACE); 2519 List<JCCase> cases = switchBlockStatementGroups(); 2520 JCSwitch t = to(F.at(pos).Switch(selector, cases)); 2521 accept(RBRACE); 2522 return t; 2523 } 2524 case SYNCHRONIZED: { 2525 nextToken(); 2526 JCExpression lock = parExpression(); 2527 JCBlock body = block(); 2528 return F.at(pos).Synchronized(lock, body); 2529 } 2530 case RETURN: { 2531 nextToken(); 2532 JCExpression result = token.kind == SEMI ? null : parseExpression(); 2533 JCReturn t = to(F.at(pos).Return(result)); 2534 accept(SEMI); 2535 return t; 2536 } 2537 case THROW: { 2538 nextToken(); 2539 JCExpression exc = parseExpression(); 2540 JCThrow t = to(F.at(pos).Throw(exc)); 2541 accept(SEMI); 2542 return t; 2543 } 2544 case BREAK: { 2545 nextToken(); 2546 Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null; 2547 JCBreak t = to(F.at(pos).Break(label)); 2548 accept(SEMI); 2549 return t; 2550 } 2551 case CONTINUE: { 2552 nextToken(); 2553 Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null; 2554 JCContinue t = to(F.at(pos).Continue(label)); 2555 accept(SEMI); 2556 return t; 2557 } 2558 case SEMI: 2559 nextToken(); 2560 return toP(F.at(pos).Skip()); 2561 case ELSE: 2562 int elsePos = token.pos; 2563 nextToken(); 2564 return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if"); 2565 case FINALLY: 2566 int finallyPos = token.pos; 2567 nextToken(); 2568 return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try"); 2569 case CATCH: 2570 return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try"); 2571 case ASSERT: { 2572 if (allowAsserts && token.kind == ASSERT) { 2573 nextToken(); 2574 JCExpression assertion = parseExpression(); 2575 JCExpression message = null; 2576 if (token.kind == COLON) { 2577 nextToken(); 2578 message = parseExpression(); 2579 } 2580 JCAssert t = to(F.at(pos).Assert(assertion, message)); 2581 accept(SEMI); 2582 return t; 2583 } 2584 /* else fall through to default case */ 2585 } 2586 case ENUM: 2587 default: 2588 Token prevToken = token; 2589 JCExpression expr = parseExpression(); 2590 if (token.kind == COLON && expr.hasTag(IDENT)) { 2591 nextToken(); 2592 JCStatement stat = parseStatement(); 2593 return F.at(pos).Labelled(prevToken.name(), stat); 2594 } else { 2595 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 2596 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr))); 2597 accept(SEMI); 2598 return stat; 2599 } 2600 } 2601 } 2602 2603 private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) { 2604 int errPos = S.errPos(); 2605 JCTree stm = action.doRecover(this); 2606 S.errPos(errPos); 2607 return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key))); 2608 } 2609 2610 /** CatchClause = CATCH "(" FormalParameter ")" Block 2611 * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below. 2612 */ 2613 protected JCCatch catchClause() { 2614 int pos = token.pos; 2615 accept(CATCH); 2616 accept(LPAREN); 2617 JCModifiers mods = optFinal(Flags.PARAMETER); 2618 List<JCExpression> catchTypes = catchTypes(); 2619 JCExpression paramType = catchTypes.size() > 1 ? 2620 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) : 2621 catchTypes.head; 2622 JCVariableDecl formal = variableDeclaratorId(mods, paramType); 2623 accept(RPAREN); 2624 JCBlock body = block(); 2625 return F.at(pos).Catch(formal, body); 2626 } 2627 2628 List<JCExpression> catchTypes() { 2629 ListBuffer<JCExpression> catchTypes = ListBuffer.lb(); 2630 catchTypes.add(parseType()); 2631 while (token.kind == BAR) { 2632 checkMulticatch(); 2633 nextToken(); 2634 // Instead of qualident this is now parseType. 2635 // But would that allow too much, e.g. arrays or generics? 2636 catchTypes.add(parseType()); 2637 } 2638 return catchTypes.toList(); 2639 } 2640 2641 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup } 2642 * SwitchBlockStatementGroup = SwitchLabel BlockStatements 2643 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" 2644 */ 2645 List<JCCase> switchBlockStatementGroups() { 2646 ListBuffer<JCCase> cases = new ListBuffer<JCCase>(); 2647 while (true) { 2648 int pos = token.pos; 2649 switch (token.kind) { 2650 case CASE: 2651 case DEFAULT: 2652 cases.append(switchBlockStatementGroup()); 2653 break; 2654 case RBRACE: case EOF: 2655 return cases.toList(); 2656 default: 2657 nextToken(); // to ensure progress 2658 syntaxError(pos, "expected3", 2659 CASE, DEFAULT, RBRACE); 2660 } 2661 } 2662 } 2663 2664 protected JCCase switchBlockStatementGroup() { 2665 int pos = token.pos; 2666 List<JCStatement> stats; 2667 JCCase c; 2668 switch (token.kind) { 2669 case CASE: 2670 nextToken(); 2671 JCExpression pat = parseExpression(); 2672 accept(COLON); 2673 stats = blockStatements(); 2674 c = F.at(pos).Case(pat, stats); 2675 if (stats.isEmpty()) 2676 storeEnd(c, S.prevToken().endPos); 2677 return c; 2678 case DEFAULT: 2679 nextToken(); 2680 accept(COLON); 2681 stats = blockStatements(); 2682 c = F.at(pos).Case(null, stats); 2683 if (stats.isEmpty()) 2684 storeEnd(c, S.prevToken().endPos); 2685 return c; 2686 } 2687 throw new AssertionError("should not reach here"); 2688 } 2689 2690 /** MoreStatementExpressions = { COMMA StatementExpression } 2691 */ 2692 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos, 2693 JCExpression first, 2694 T stats) { 2695 // This Exec is a "StatementExpression"; it subsumes no terminating token 2696 stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); 2697 while (token.kind == COMMA) { 2698 nextToken(); 2699 pos = token.pos; 2700 JCExpression t = parseExpression(); 2701 // This Exec is a "StatementExpression"; it subsumes no terminating token 2702 stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); 2703 } 2704 return stats; 2705 } 2706 2707 /** ForInit = StatementExpression MoreStatementExpressions 2708 * | { FINAL | '@' Annotation } Type VariableDeclarators 2709 */ 2710 List<JCStatement> forInit() { 2711 ListBuffer<JCStatement> stats = lb(); 2712 int pos = token.pos; 2713 if (token.kind == FINAL || token.kind == MONKEYS_AT) { 2714 return variableDeclarators(optFinal(0), parseType(), stats).toList(); 2715 } else { 2716 JCExpression t = term(EXPR | TYPE); 2717 if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { 2718 return variableDeclarators(modifiersOpt(), t, stats).toList(); 2719 } else if ((lastmode & TYPE) != 0 && token.kind == COLON) { 2720 error(pos, "bad.initializer", "for-loop"); 2721 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null)); 2722 } else { 2723 return moreStatementExpressions(pos, t, stats).toList(); 2724 } 2725 } 2726 } 2727 2728 /** ForUpdate = StatementExpression MoreStatementExpressions 2729 */ 2730 List<JCExpressionStatement> forUpdate() { 2731 return moreStatementExpressions(token.pos, 2732 parseExpression(), 2733 new ListBuffer<JCExpressionStatement>()).toList(); 2734 } 2735 2736 /** AnnotationsOpt = { '@' Annotation } 2737 * 2738 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION 2739 */ 2740 List<JCAnnotation> annotationsOpt(Tag kind) { 2741 if (token.kind != MONKEYS_AT) return List.nil(); // optimization 2742 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>(); 2743 int prevmode = mode; 2744 while (token.kind == MONKEYS_AT) { 2745 int pos = token.pos; 2746 nextToken(); 2747 buf.append(annotation(pos, kind)); 2748 } 2749 lastmode = mode; 2750 mode = prevmode; 2751 List<JCAnnotation> annotations = buf.toList(); 2752 2753 return annotations; 2754 } 2755 2756 List<JCAnnotation> typeAnnotationsOpt() { 2757 List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION); 2758 return annotations; 2759 } 2760 2761 /** ModifiersOpt = { Modifier } 2762 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL 2763 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" 2764 * | "@" Annotation 2765 */ 2766 JCModifiers modifiersOpt() { 2767 return modifiersOpt(null); 2768 } 2769 protected JCModifiers modifiersOpt(JCModifiers partial) { 2770 long flags; 2771 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>(); 2772 int pos; 2773 if (partial == null) { 2774 flags = 0; 2775 pos = token.pos; 2776 } else { 2777 flags = partial.flags; 2778 annotations.appendList(partial.annotations); 2779 pos = partial.pos; 2780 } 2781 if (token.deprecatedFlag()) { 2782 flags |= Flags.DEPRECATED; 2783 } 2784 int lastPos; 2785 loop: 2786 while (true) { 2787 long flag; 2788 switch (token.kind) { 2789 case PRIVATE : flag = Flags.PRIVATE; break; 2790 case PROTECTED : flag = Flags.PROTECTED; break; 2791 case PUBLIC : flag = Flags.PUBLIC; break; 2792 case STATIC : flag = Flags.STATIC; break; 2793 case TRANSIENT : flag = Flags.TRANSIENT; break; 2794 case FINAL : flag = Flags.FINAL; break; 2795 case ABSTRACT : flag = Flags.ABSTRACT; break; 2796 case NATIVE : flag = Flags.NATIVE; break; 2797 case VOLATILE : flag = Flags.VOLATILE; break; 2798 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; 2799 case STRICTFP : flag = Flags.STRICTFP; break; 2800 case MONKEYS_AT : flag = Flags.ANNOTATION; break; 2801 case DEFAULT : checkDefaultMethods(); flag = Flags.DEFAULT; break; 2802 case ERROR : flag = 0; nextToken(); break; 2803 default: break loop; 2804 } 2805 if ((flags & flag) != 0) error(token.pos, "repeated.modifier"); 2806 lastPos = token.pos; 2807 nextToken(); 2808 if (flag == Flags.ANNOTATION) { 2809 checkAnnotations(); 2810 if (token.kind != INTERFACE) { 2811 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION); 2812 // if first modifier is an annotation, set pos to annotation's. 2813 if (flags == 0 && annotations.isEmpty()) 2814 pos = ann.pos; 2815 annotations.append(ann); 2816 flag = 0; 2817 } 2818 } 2819 flags |= flag; 2820 } 2821 switch (token.kind) { 2822 case ENUM: flags |= Flags.ENUM; break; 2823 case INTERFACE: flags |= Flags.INTERFACE; break; 2824 default: break; 2825 } 2826 2827 /* A modifiers tree with no modifier tokens or annotations 2828 * has no text position. */ 2829 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty()) 2830 pos = Position.NOPOS; 2831 2832 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); 2833 if (pos != Position.NOPOS) 2834 storeEnd(mods, S.prevToken().endPos); 2835 return mods; 2836 } 2837 2838 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] 2839 * 2840 * @param pos position of "@" token 2841 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION 2842 */ 2843 JCAnnotation annotation(int pos, Tag kind) { 2844 // accept(AT); // AT consumed by caller 2845 checkAnnotations(); 2846 if (kind == Tag.TYPE_ANNOTATION) { 2847 checkTypeAnnotations(); 2848 } 2849 JCTree ident = qualident(false); 2850 List<JCExpression> fieldValues = annotationFieldValuesOpt(); 2851 JCAnnotation ann; 2852 if (kind == Tag.ANNOTATION) { 2853 ann = F.at(pos).Annotation(ident, fieldValues); 2854 } else if (kind == Tag.TYPE_ANNOTATION) { 2855 ann = F.at(pos).TypeAnnotation(ident, fieldValues); 2856 } else { 2857 throw new AssertionError("Unhandled annotation kind: " + kind); 2858 } 2859 2860 storeEnd(ann, S.prevToken().endPos); 2861 return ann; 2862 } 2863 2864 List<JCExpression> annotationFieldValuesOpt() { 2865 return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil(); 2866 } 2867 2868 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ 2869 List<JCExpression> annotationFieldValues() { 2870 accept(LPAREN); 2871 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 2872 if (token.kind != RPAREN) { 2873 buf.append(annotationFieldValue()); 2874 while (token.kind == COMMA) { 2875 nextToken(); 2876 buf.append(annotationFieldValue()); 2877 } 2878 } 2879 accept(RPAREN); 2880 return buf.toList(); 2881 } 2882 2883 /** AnnotationFieldValue = AnnotationValue 2884 * | Identifier "=" AnnotationValue 2885 */ 2886 JCExpression annotationFieldValue() { 2887 if (LAX_IDENTIFIER.accepts(token.kind)) { 2888 mode = EXPR; 2889 JCExpression t1 = term1(); 2890 if (t1.hasTag(IDENT) && token.kind == EQ) { 2891 int pos = token.pos; 2892 accept(EQ); 2893 JCExpression v = annotationValue(); 2894 return toP(F.at(pos).Assign(t1, v)); 2895 } else { 2896 return t1; 2897 } 2898 } 2899 return annotationValue(); 2900 } 2901 2902 /* AnnotationValue = ConditionalExpression 2903 * | Annotation 2904 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}" 2905 */ 2906 JCExpression annotationValue() { 2907 int pos; 2908 switch (token.kind) { 2909 case MONKEYS_AT: 2910 pos = token.pos; 2911 nextToken(); 2912 return annotation(pos, Tag.ANNOTATION); 2913 case LBRACE: 2914 pos = token.pos; 2915 accept(LBRACE); 2916 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 2917 if (token.kind != RBRACE) { 2918 buf.append(annotationValue()); 2919 while (token.kind == COMMA) { 2920 nextToken(); 2921 if (token.kind == RBRACE) break; 2922 buf.append(annotationValue()); 2923 } 2924 } 2925 accept(RBRACE); 2926 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList())); 2927 default: 2928 mode = EXPR; 2929 return term1(); 2930 } 2931 } 2932 2933 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator } 2934 */ 2935 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods, 2936 JCExpression type, 2937 T vdefs) 2938 { 2939 return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs); 2940 } 2941 2942 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } 2943 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } 2944 * 2945 * @param reqInit Is an initializer always required? 2946 * @param dc The documentation comment for the variable declarations, or null. 2947 */ 2948 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos, 2949 JCModifiers mods, 2950 JCExpression type, 2951 Name name, 2952 boolean reqInit, 2953 Comment dc, 2954 T vdefs) 2955 { 2956 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); 2957 while (token.kind == COMMA) { 2958 // All but last of multiple declarators subsume a comma 2959 storeEnd((JCTree)vdefs.last(), token.endPos); 2960 nextToken(); 2961 vdefs.append(variableDeclarator(mods, type, reqInit, dc)); 2962 } 2963 return vdefs; 2964 } 2965 2966 /** VariableDeclarator = Ident VariableDeclaratorRest 2967 * ConstantDeclarator = Ident ConstantDeclaratorRest 2968 */ 2969 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) { 2970 return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc); 2971 } 2972 2973 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] 2974 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer 2975 * 2976 * @param reqInit Is an initializer always required? 2977 * @param dc The documentation comment for the variable declarations, or null. 2978 */ 2979 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, 2980 boolean reqInit, Comment dc) { 2981 type = bracketsOpt(type); 2982 JCExpression init = null; 2983 if (token.kind == EQ) { 2984 nextToken(); 2985 init = variableInitializer(); 2986 } 2987 else if (reqInit) syntaxError(token.pos, "expected", EQ); 2988 JCVariableDecl result = 2989 toP(F.at(pos).VarDef(mods, name, type, init)); 2990 attach(result, dc); 2991 return result; 2992 } 2993 2994 /** VariableDeclaratorId = Ident BracketsOpt 2995 */ 2996 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { 2997 return variableDeclaratorId(mods, type, false); 2998 } 2999 //where 3000 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) { 3001 int pos = token.pos; 3002 Name name; 3003 if (lambdaParameter && token.kind == UNDERSCORE) { 3004 syntaxError(pos, "expected", IDENTIFIER); 3005 name = token.name(); 3006 } else { 3007 if (allowThisIdent) { 3008 JCExpression pn = qualident(false); 3009 if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) { 3010 name = ((JCIdent)pn).name; 3011 } else { 3012 if ((mods.flags & Flags.VARARGS) != 0) { 3013 log.error(token.pos, "varargs.and.receiver"); 3014 } 3015 if (token.kind == LBRACKET) { 3016 log.error(token.pos, "array.and.receiver"); 3017 } 3018 return toP(F.at(pos).ReceiverVarDef(mods, pn, type)); 3019 } 3020 } else { 3021 name = ident(); 3022 } 3023 } 3024 if ((mods.flags & Flags.VARARGS) != 0 && 3025 token.kind == LBRACKET) { 3026 log.error(token.pos, "varargs.and.old.array.syntax"); 3027 } 3028 type = bracketsOpt(type); 3029 return toP(F.at(pos).VarDef(mods, name, type, null)); 3030 } 3031 3032 /** Resources = Resource { ";" Resources } 3033 */ 3034 List<JCTree> resources() { 3035 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 3036 defs.append(resource()); 3037 while (token.kind == SEMI) { 3038 // All but last of multiple declarators must subsume a semicolon 3039 storeEnd(defs.last(), token.endPos); 3040 int semiColonPos = token.pos; 3041 nextToken(); 3042 if (token.kind == RPAREN) { // Optional trailing semicolon 3043 // after last resource 3044 break; 3045 } 3046 defs.append(resource()); 3047 } 3048 return defs.toList(); 3049 } 3050 3051 /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression 3052 */ 3053 protected JCTree resource() { 3054 JCModifiers optFinal = optFinal(Flags.FINAL); 3055 JCExpression type = parseType(); 3056 int pos = token.pos; 3057 Name ident = ident(); 3058 return variableDeclaratorRest(pos, optFinal, type, ident, true, null); 3059 } 3060 3061 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} 3062 */ 3063 public JCTree.JCCompilationUnit parseCompilationUnit() { 3064 Token firstToken = token; 3065 JCExpression pid = null; 3066 JCModifiers mods = null; 3067 boolean consumedToplevelDoc = false; 3068 boolean seenImport = false; 3069 boolean seenPackage = false; 3070 List<JCAnnotation> packageAnnotations = List.nil(); 3071 if (token.kind == MONKEYS_AT) 3072 mods = modifiersOpt(); 3073 3074 if (token.kind == PACKAGE) { 3075 seenPackage = true; 3076 if (mods != null) { 3077 checkNoMods(mods.flags); 3078 packageAnnotations = mods.annotations; 3079 mods = null; 3080 } 3081 nextToken(); 3082 pid = qualident(false); 3083 accept(SEMI); 3084 } 3085 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 3086 boolean checkForImports = true; 3087 boolean firstTypeDecl = true; 3088 while (token.kind != EOF) { 3089 if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) { 3090 // error recovery 3091 skip(checkForImports, false, false, false); 3092 if (token.kind == EOF) 3093 break; 3094 } 3095 if (checkForImports && mods == null && token.kind == IMPORT) { 3096 seenImport = true; 3097 defs.append(importDeclaration()); 3098 } else { 3099 Comment docComment = token.comment(CommentStyle.JAVADOC); 3100 if (firstTypeDecl && !seenImport && !seenPackage) { 3101 docComment = firstToken.comment(CommentStyle.JAVADOC); 3102 consumedToplevelDoc = true; 3103 } 3104 JCTree def = typeDeclaration(mods, docComment); 3105 if (def instanceof JCExpressionStatement) 3106 def = ((JCExpressionStatement)def).expr; 3107 defs.append(def); 3108 if (def instanceof JCClassDecl) 3109 checkForImports = false; 3110 mods = null; 3111 firstTypeDecl = false; 3112 } 3113 } 3114 JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList()); 3115 if (!consumedToplevelDoc) 3116 attach(toplevel, firstToken.comment(CommentStyle.JAVADOC)); 3117 if (defs.isEmpty()) 3118 storeEnd(toplevel, S.prevToken().endPos); 3119 if (keepDocComments) 3120 toplevel.docComments = docComments; 3121 if (keepLineMap) 3122 toplevel.lineMap = S.getLineMap(); 3123 this.endPosTable.setParser(null); // remove reference to parser 3124 toplevel.endPositions = this.endPosTable; 3125 return toplevel; 3126 } 3127 3128 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" 3129 */ 3130 JCTree importDeclaration() { 3131 int pos = token.pos; 3132 nextToken(); 3133 boolean importStatic = false; 3134 if (token.kind == STATIC) { 3135 checkStaticImports(); 3136 importStatic = true; 3137 nextToken(); 3138 } 3139 JCExpression pid = toP(F.at(token.pos).Ident(ident())); 3140 do { 3141 int pos1 = token.pos; 3142 accept(DOT); 3143 if (token.kind == STAR) { 3144 pid = to(F.at(pos1).Select(pid, names.asterisk)); 3145 nextToken(); 3146 break; 3147 } else { 3148 pid = toP(F.at(pos1).Select(pid, ident())); 3149 } 3150 } while (token.kind == DOT); 3151 accept(SEMI); 3152 return toP(F.at(pos).Import(pid, importStatic)); 3153 } 3154 3155 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration 3156 * | ";" 3157 */ 3158 JCTree typeDeclaration(JCModifiers mods, Comment docComment) { 3159 int pos = token.pos; 3160 if (mods == null && token.kind == SEMI) { 3161 nextToken(); 3162 return toP(F.at(pos).Skip()); 3163 } else { 3164 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment); 3165 } 3166 } 3167 3168 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt 3169 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) 3170 * @param mods Any modifiers starting the class or interface declaration 3171 * @param dc The documentation comment for the class, or null. 3172 */ 3173 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) { 3174 if (token.kind == CLASS) { 3175 return classDeclaration(mods, dc); 3176 } else if (token.kind == INTERFACE) { 3177 return interfaceDeclaration(mods, dc); 3178 } else if (allowEnums) { 3179 if (token.kind == ENUM) { 3180 return enumDeclaration(mods, dc); 3181 } else { 3182 int pos = token.pos; 3183 List<JCTree> errs; 3184 if (LAX_IDENTIFIER.accepts(token.kind)) { 3185 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 3186 setErrorEndPos(token.pos); 3187 } else { 3188 errs = List.<JCTree>of(mods); 3189 } 3190 return toP(F.Exec(syntaxError(pos, errs, "expected3", 3191 CLASS, INTERFACE, ENUM))); 3192 } 3193 } else { 3194 if (token.kind == ENUM) { 3195 error(token.pos, "enums.not.supported.in.source", source.name); 3196 allowEnums = true; 3197 return enumDeclaration(mods, dc); 3198 } 3199 int pos = token.pos; 3200 List<JCTree> errs; 3201 if (LAX_IDENTIFIER.accepts(token.kind)) { 3202 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 3203 setErrorEndPos(token.pos); 3204 } else { 3205 errs = List.<JCTree>of(mods); 3206 } 3207 return toP(F.Exec(syntaxError(pos, errs, "expected2", 3208 CLASS, INTERFACE))); 3209 } 3210 } 3211 3212 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] 3213 * [IMPLEMENTS TypeList] ClassBody 3214 * @param mods The modifiers starting the class declaration 3215 * @param dc The documentation comment for the class, or null. 3216 */ 3217 protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) { 3218 int pos = token.pos; 3219 accept(CLASS); 3220 Name name = ident(); 3221 3222 List<JCTypeParameter> typarams = typeParametersOpt(); 3223 3224 JCExpression extending = null; 3225 if (token.kind == EXTENDS) { 3226 nextToken(); 3227 extending = parseType(); 3228 } 3229 List<JCExpression> implementing = List.nil(); 3230 if (token.kind == IMPLEMENTS) { 3231 nextToken(); 3232 implementing = typeList(); 3233 } 3234 List<JCTree> defs = classOrInterfaceBody(name, false); 3235 JCClassDecl result = toP(F.at(pos).ClassDef( 3236 mods, name, typarams, extending, implementing, defs)); 3237 attach(result, dc); 3238 return result; 3239 } 3240 3241 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt 3242 * [EXTENDS TypeList] InterfaceBody 3243 * @param mods The modifiers starting the interface declaration 3244 * @param dc The documentation comment for the interface, or null. 3245 */ 3246 protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) { 3247 int pos = token.pos; 3248 accept(INTERFACE); 3249 Name name = ident(); 3250 3251 List<JCTypeParameter> typarams = typeParametersOpt(); 3252 3253 List<JCExpression> extending = List.nil(); 3254 if (token.kind == EXTENDS) { 3255 nextToken(); 3256 extending = typeList(); 3257 } 3258 List<JCTree> defs = classOrInterfaceBody(name, true); 3259 JCClassDecl result = toP(F.at(pos).ClassDef( 3260 mods, name, typarams, null, extending, defs)); 3261 attach(result, dc); 3262 return result; 3263 } 3264 3265 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody 3266 * @param mods The modifiers starting the enum declaration 3267 * @param dc The documentation comment for the enum, or null. 3268 */ 3269 protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) { 3270 int pos = token.pos; 3271 accept(ENUM); 3272 Name name = ident(); 3273 3274 List<JCExpression> implementing = List.nil(); 3275 if (token.kind == IMPLEMENTS) { 3276 nextToken(); 3277 implementing = typeList(); 3278 } 3279 3280 List<JCTree> defs = enumBody(name); 3281 mods.flags |= Flags.ENUM; 3282 JCClassDecl result = toP(F.at(pos). 3283 ClassDef(mods, name, List.<JCTypeParameter>nil(), 3284 null, implementing, defs)); 3285 attach(result, dc); 3286 return result; 3287 } 3288 3289 /** EnumBody = "{" { EnumeratorDeclarationList } [","] 3290 * [ ";" {ClassBodyDeclaration} ] "}" 3291 */ 3292 List<JCTree> enumBody(Name enumName) { 3293 accept(LBRACE); 3294 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 3295 if (token.kind == COMMA) { 3296 nextToken(); 3297 } else if (token.kind != RBRACE && token.kind != SEMI) { 3298 defs.append(enumeratorDeclaration(enumName)); 3299 while (token.kind == COMMA) { 3300 nextToken(); 3301 if (token.kind == RBRACE || token.kind == SEMI) break; 3302 defs.append(enumeratorDeclaration(enumName)); 3303 } 3304 if (token.kind != SEMI && token.kind != RBRACE) { 3305 defs.append(syntaxError(token.pos, "expected3", 3306 COMMA, RBRACE, SEMI)); 3307 nextToken(); 3308 } 3309 } 3310 if (token.kind == SEMI) { 3311 nextToken(); 3312 while (token.kind != RBRACE && token.kind != EOF) { 3313 defs.appendList(classOrInterfaceBodyDeclaration(enumName, 3314 false)); 3315 if (token.pos <= endPosTable.errorEndPos) { 3316 // error recovery 3317 skip(false, true, true, false); 3318 } 3319 } 3320 } 3321 accept(RBRACE); 3322 return defs.toList(); 3323 } 3324 3325 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] 3326 */ 3327 JCTree enumeratorDeclaration(Name enumName) { 3328 Comment dc = token.comment(CommentStyle.JAVADOC); 3329 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; 3330 if (token.deprecatedFlag()) { 3331 flags |= Flags.DEPRECATED; 3332 } 3333 int pos = token.pos; 3334 List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION); 3335 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 3336 List<JCExpression> typeArgs = typeArgumentsOpt(); 3337 int identPos = token.pos; 3338 Name name = ident(); 3339 int createPos = token.pos; 3340 List<JCExpression> args = (token.kind == LPAREN) 3341 ? arguments() : List.<JCExpression>nil(); 3342 JCClassDecl body = null; 3343 if (token.kind == LBRACE) { 3344 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); 3345 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 3346 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); 3347 } 3348 if (args.isEmpty() && body == null) 3349 createPos = identPos; 3350 JCIdent ident = F.at(identPos).Ident(enumName); 3351 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); 3352 if (createPos != identPos) 3353 storeEnd(create, S.prevToken().endPos); 3354 ident = F.at(identPos).Ident(enumName); 3355 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); 3356 attach(result, dc); 3357 return result; 3358 } 3359 3360 /** TypeList = Type {"," Type} 3361 */ 3362 List<JCExpression> typeList() { 3363 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 3364 ts.append(parseType()); 3365 while (token.kind == COMMA) { 3366 nextToken(); 3367 ts.append(parseType()); 3368 } 3369 return ts.toList(); 3370 } 3371 3372 /** ClassBody = "{" {ClassBodyDeclaration} "}" 3373 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" 3374 */ 3375 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 3376 accept(LBRACE); 3377 if (token.pos <= endPosTable.errorEndPos) { 3378 // error recovery 3379 skip(false, true, false, false); 3380 if (token.kind == LBRACE) 3381 nextToken(); 3382 } 3383 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 3384 while (token.kind != RBRACE && token.kind != EOF) { 3385 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 3386 if (token.pos <= endPosTable.errorEndPos) { 3387 // error recovery 3388 skip(false, true, true, false); 3389 } 3390 } 3391 accept(RBRACE); 3392 return defs.toList(); 3393 } 3394 3395 /** ClassBodyDeclaration = 3396 * ";" 3397 * | [STATIC] Block 3398 * | ModifiersOpt 3399 * ( Type Ident 3400 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) 3401 * | VOID Ident MethodDeclaratorRest 3402 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest 3403 * | Ident ConstructorDeclaratorRest 3404 * | TypeParameters Ident ConstructorDeclaratorRest 3405 * | ClassOrInterfaceOrEnumDeclaration 3406 * ) 3407 * InterfaceBodyDeclaration = 3408 * ";" 3409 * | ModifiersOpt Type Ident 3410 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) 3411 */ 3412 protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { 3413 if (token.kind == SEMI) { 3414 nextToken(); 3415 return List.<JCTree>nil(); 3416 } else { 3417 Comment dc = token.comment(CommentStyle.JAVADOC); 3418 int pos = token.pos; 3419 JCModifiers mods = modifiersOpt(); 3420 if (token.kind == CLASS || 3421 token.kind == INTERFACE || 3422 allowEnums && token.kind == ENUM) { 3423 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 3424 } else if (token.kind == LBRACE && !isInterface && 3425 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && 3426 mods.annotations.isEmpty()) { 3427 return List.<JCTree>of(block(pos, mods.flags)); 3428 } else { 3429 pos = token.pos; 3430 List<JCTypeParameter> typarams = typeParametersOpt(); 3431 // if there are type parameters but no modifiers, save the start 3432 // position of the method in the modifiers. 3433 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { 3434 mods.pos = pos; 3435 storeEnd(mods, pos); 3436 } 3437 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION); 3438 3439 Token tk = token; 3440 pos = token.pos; 3441 JCExpression type; 3442 boolean isVoid = token.kind == VOID; 3443 if (isVoid) { 3444 if (annosAfterParams.nonEmpty()) 3445 illegal(annosAfterParams.head.pos); 3446 type = to(F.at(pos).TypeIdent(TypeTag.VOID)); 3447 nextToken(); 3448 } else { 3449 if (annosAfterParams.nonEmpty()) { 3450 mods.annotations = mods.annotations.appendList(annosAfterParams); 3451 if (mods.pos == Position.NOPOS) 3452 mods.pos = mods.annotations.head.pos; 3453 } 3454 // method returns types are un-annotated types 3455 type = unannotatedType(); 3456 } 3457 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) { 3458 if (isInterface || tk.name() != className) 3459 error(pos, "invalid.meth.decl.ret.type.req"); 3460 return List.of(methodDeclaratorRest( 3461 pos, mods, null, names.init, typarams, 3462 isInterface, true, dc)); 3463 } else { 3464 pos = token.pos; 3465 Name name = ident(); 3466 if (token.kind == LPAREN) { 3467 return List.of(methodDeclaratorRest( 3468 pos, mods, type, name, typarams, 3469 isInterface, isVoid, dc)); 3470 } else if (!isVoid && typarams.isEmpty()) { 3471 List<JCTree> defs = 3472 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, 3473 new ListBuffer<JCTree>()).toList(); 3474 storeEnd(defs.last(), token.endPos); 3475 accept(SEMI); 3476 return defs; 3477 } else { 3478 pos = token.pos; 3479 List<JCTree> err = isVoid 3480 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, 3481 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 3482 : null; 3483 return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN)); 3484 } 3485 } 3486 } 3487 } 3488 } 3489 3490 /** MethodDeclaratorRest = 3491 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 3492 * VoidMethodDeclaratorRest = 3493 * FormalParameters [Throws TypeList] ( MethodBody | ";") 3494 * InterfaceMethodDeclaratorRest = 3495 * FormalParameters BracketsOpt [THROWS TypeList] ";" 3496 * VoidInterfaceMethodDeclaratorRest = 3497 * FormalParameters [THROWS TypeList] ";" 3498 * ConstructorDeclaratorRest = 3499 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody 3500 */ 3501 protected JCTree methodDeclaratorRest(int pos, 3502 JCModifiers mods, 3503 JCExpression type, 3504 Name name, 3505 List<JCTypeParameter> typarams, 3506 boolean isInterface, boolean isVoid, 3507 Comment dc) { 3508 if (isInterface && (mods.flags & Flags.STATIC) != 0) { 3509 checkStaticInterfaceMethods(); 3510 } 3511 JCVariableDecl prevReceiverParam = this.receiverParam; 3512 try { 3513 this.receiverParam = null; 3514 // Parsing formalParameters sets the receiverParam, if present 3515 List<JCVariableDecl> params = formalParameters(); 3516 if (!isVoid) type = bracketsOpt(type); 3517 List<JCExpression> thrown = List.nil(); 3518 if (token.kind == THROWS) { 3519 nextToken(); 3520 thrown = qualidentList(); 3521 } 3522 JCBlock body = null; 3523 JCExpression defaultValue; 3524 if (token.kind == LBRACE) { 3525 body = block(); 3526 defaultValue = null; 3527 } else { 3528 if (token.kind == DEFAULT) { 3529 accept(DEFAULT); 3530 defaultValue = annotationValue(); 3531 } else { 3532 defaultValue = null; 3533 } 3534 accept(SEMI); 3535 if (token.pos <= endPosTable.errorEndPos) { 3536 // error recovery 3537 skip(false, true, false, false); 3538 if (token.kind == LBRACE) { 3539 body = block(); 3540 } 3541 } 3542 } 3543 3544 JCMethodDecl result = 3545 toP(F.at(pos).MethodDef(mods, name, type, typarams, 3546 receiverParam, params, thrown, 3547 body, defaultValue)); 3548 attach(result, dc); 3549 return result; 3550 } finally { 3551 this.receiverParam = prevReceiverParam; 3552 } 3553 } 3554 3555 /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident} 3556 */ 3557 List<JCExpression> qualidentList() { 3558 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 3559 3560 List<JCAnnotation> typeAnnos = typeAnnotationsOpt(); 3561 JCExpression qi = qualident(true); 3562 if (!typeAnnos.isEmpty()) { 3563 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false); 3564 ts.append(at); 3565 } else { 3566 ts.append(qi); 3567 } 3568 while (token.kind == COMMA) { 3569 nextToken(); 3570 3571 typeAnnos = typeAnnotationsOpt(); 3572 qi = qualident(true); 3573 if (!typeAnnos.isEmpty()) { 3574 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false); 3575 ts.append(at); 3576 } else { 3577 ts.append(qi); 3578 } 3579 } 3580 return ts.toList(); 3581 } 3582 3583 /** 3584 * {@literal 3585 * TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] 3586 * } 3587 */ 3588 List<JCTypeParameter> typeParametersOpt() { 3589 if (token.kind == LT) { 3590 checkGenerics(); 3591 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>(); 3592 nextToken(); 3593 typarams.append(typeParameter()); 3594 while (token.kind == COMMA) { 3595 nextToken(); 3596 typarams.append(typeParameter()); 3597 } 3598 accept(GT); 3599 return typarams.toList(); 3600 } else { 3601 return List.nil(); 3602 } 3603 } 3604 3605 /** 3606 * {@literal 3607 * TypeParameter = [Annotations] TypeVariable [TypeParameterBound] 3608 * TypeParameterBound = EXTENDS Type {"&" Type} 3609 * TypeVariable = Ident 3610 * } 3611 */ 3612 JCTypeParameter typeParameter() { 3613 int pos = token.pos; 3614 List<JCAnnotation> annos = typeAnnotationsOpt(); 3615 Name name = ident(); 3616 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); 3617 if (token.kind == EXTENDS) { 3618 nextToken(); 3619 bounds.append(parseType()); 3620 while (token.kind == AMP) { 3621 nextToken(); 3622 bounds.append(parseType()); 3623 } 3624 } 3625 return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos)); 3626 } 3627 3628 /** FormalParameters = "(" [ FormalParameterList ] ")" 3629 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter 3630 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter 3631 */ 3632 List<JCVariableDecl> formalParameters() { 3633 return formalParameters(false); 3634 } 3635 List<JCVariableDecl> formalParameters(boolean lambdaParameters) { 3636 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); 3637 JCVariableDecl lastParam; 3638 accept(LPAREN); 3639 if (token.kind != RPAREN) { 3640 this.allowThisIdent = true; 3641 lastParam = formalParameter(lambdaParameters); 3642 if (lastParam.nameexpr != null) { 3643 this.receiverParam = lastParam; 3644 } else { 3645 params.append(lastParam); 3646 } 3647 this.allowThisIdent = false; 3648 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { 3649 nextToken(); 3650 params.append(lastParam = formalParameter(lambdaParameters)); 3651 } 3652 } 3653 accept(RPAREN); 3654 return params.toList(); 3655 } 3656 3657 List<JCVariableDecl> implicitParameters(boolean hasParens) { 3658 if (hasParens) { 3659 accept(LPAREN); 3660 } 3661 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); 3662 if (token.kind != RPAREN && token.kind != ARROW) { 3663 params.append(implicitParameter()); 3664 while (token.kind == COMMA) { 3665 nextToken(); 3666 params.append(implicitParameter()); 3667 } 3668 } 3669 if (hasParens) { 3670 accept(RPAREN); 3671 } 3672 return params.toList(); 3673 } 3674 3675 JCModifiers optFinal(long flags) { 3676 JCModifiers mods = modifiersOpt(); 3677 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); 3678 mods.flags |= flags; 3679 return mods; 3680 } 3681 3682 /** 3683 * Inserts the annotations (and possibly a new array level) 3684 * to the left-most type in an array or nested type. 3685 * 3686 * When parsing a type like {@code @B Outer.Inner @A []}, the 3687 * {@code @A} annotation should target the array itself, while 3688 * {@code @B} targets the nested type {@code Outer}. 3689 * 3690 * Currently the parser parses the annotation first, then 3691 * the array, and then inserts the annotation to the left-most 3692 * nested type. 3693 * 3694 * When {@code createNewLevel} is true, then a new array 3695 * level is inserted as the most inner type, and have the 3696 * annotations target it. This is useful in the case of 3697 * varargs, e.g. {@code String @A [] @B ...}, as the parser 3698 * first parses the type {@code String @A []} then inserts 3699 * a new array level with {@code @B} annotation. 3700 */ 3701 private JCExpression insertAnnotationsToMostInner( 3702 JCExpression type, List<JCAnnotation> annos, 3703 boolean createNewLevel) { 3704 int origEndPos = getEndPos(type); 3705 JCExpression mostInnerType = type; 3706 JCArrayTypeTree mostInnerArrayType = null; 3707 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) { 3708 mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType); 3709 mostInnerType = mostInnerArrayType.elemtype; 3710 } 3711 3712 if (createNewLevel) { 3713 mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType)); 3714 } 3715 3716 JCExpression mostInnerTypeToReturn = mostInnerType; 3717 if (annos.nonEmpty()) { 3718 JCExpression lastToModify = mostInnerType; 3719 3720 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) || 3721 TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) { 3722 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) { 3723 lastToModify = mostInnerType; 3724 mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression(); 3725 } 3726 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) { 3727 lastToModify = mostInnerType; 3728 mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz; 3729 } 3730 } 3731 3732 mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType); 3733 3734 if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) { 3735 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType; 3736 } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) { 3737 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType; 3738 } else { 3739 // We never saw a SELECT or TYPEAPPLY, return the annotated type. 3740 mostInnerTypeToReturn = mostInnerType; 3741 } 3742 } 3743 3744 if (mostInnerArrayType == null) { 3745 return mostInnerTypeToReturn; 3746 } else { 3747 mostInnerArrayType.elemtype = mostInnerTypeToReturn; 3748 storeEnd(type, origEndPos); 3749 return type; 3750 } 3751 } 3752 3753 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId 3754 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter 3755 */ 3756 protected JCVariableDecl formalParameter() { 3757 return formalParameter(false); 3758 } 3759 protected JCVariableDecl formalParameter(boolean lambdaParameter) { 3760 JCModifiers mods = optFinal(Flags.PARAMETER); 3761 // need to distinguish between vararg annos and array annos 3762 // look at typeAnnotationsPushedBack comment 3763 this.permitTypeAnnotationsPushBack = true; 3764 JCExpression type = parseType(); 3765 this.permitTypeAnnotationsPushBack = false; 3766 3767 if (token.kind == ELLIPSIS) { 3768 List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack; 3769 typeAnnotationsPushedBack = List.nil(); 3770 checkVarargs(); 3771 mods.flags |= Flags.VARARGS; 3772 // insert var arg type annotations 3773 type = insertAnnotationsToMostInner(type, varargsAnnos, true); 3774 nextToken(); 3775 } else { 3776 // if not a var arg, then typeAnnotationsPushedBack should be null 3777 if (typeAnnotationsPushedBack.nonEmpty()) { 3778 reportSyntaxError(typeAnnotationsPushedBack.head.pos, 3779 "illegal.start.of.type"); 3780 } 3781 typeAnnotationsPushedBack = List.nil(); 3782 } 3783 return variableDeclaratorId(mods, type, lambdaParameter); 3784 } 3785 3786 protected JCVariableDecl implicitParameter() { 3787 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); 3788 return variableDeclaratorId(mods, null, true); 3789 } 3790 3791 /* ---------- auxiliary methods -------------- */ 3792 3793 void error(int pos, String key, Object ... args) { 3794 log.error(DiagnosticFlag.SYNTAX, pos, key, args); 3795 } 3796 3797 void error(DiagnosticPosition pos, String key, Object ... args) { 3798 log.error(DiagnosticFlag.SYNTAX, pos, key, args); 3799 } 3800 3801 void warning(int pos, String key, Object ... args) { 3802 log.warning(pos, key, args); 3803 } 3804 3805 /** Check that given tree is a legal expression statement. 3806 */ 3807 protected JCExpression checkExprStat(JCExpression t) { 3808 if (!TreeInfo.isExpressionStatement(t)) { 3809 JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t)); 3810 error(ret, "not.stmt"); 3811 return ret; 3812 } else { 3813 return t; 3814 } 3815 } 3816 3817 /** Return precedence of operator represented by token, 3818 * -1 if token is not a binary operator. @see TreeInfo.opPrec 3819 */ 3820 static int prec(TokenKind token) { 3821 JCTree.Tag oc = optag(token); 3822 return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1; 3823 } 3824 3825 /** 3826 * Return the lesser of two positions, making allowance for either one 3827 * being unset. 3828 */ 3829 static int earlier(int pos1, int pos2) { 3830 if (pos1 == Position.NOPOS) 3831 return pos2; 3832 if (pos2 == Position.NOPOS) 3833 return pos1; 3834 return (pos1 < pos2 ? pos1 : pos2); 3835 } 3836 3837 /** Return operation tag of binary operator represented by token, 3838 * No_TAG if token is not a binary operator. 3839 */ 3840 static JCTree.Tag optag(TokenKind token) { 3841 switch (token) { 3842 case BARBAR: 3843 return OR; 3844 case AMPAMP: 3845 return AND; 3846 case BAR: 3847 return BITOR; 3848 case BAREQ: 3849 return BITOR_ASG; 3850 case CARET: 3851 return BITXOR; 3852 case CARETEQ: 3853 return BITXOR_ASG; 3854 case AMP: 3855 return BITAND; 3856 case AMPEQ: 3857 return BITAND_ASG; 3858 case EQEQ: 3859 return JCTree.Tag.EQ; 3860 case BANGEQ: 3861 return NE; 3862 case LT: 3863 return JCTree.Tag.LT; 3864 case GT: 3865 return JCTree.Tag.GT; 3866 case LTEQ: 3867 return LE; 3868 case GTEQ: 3869 return GE; 3870 case LTLT: 3871 return SL; 3872 case LTLTEQ: 3873 return SL_ASG; 3874 case GTGT: 3875 return SR; 3876 case GTGTEQ: 3877 return SR_ASG; 3878 case GTGTGT: 3879 return USR; 3880 case GTGTGTEQ: 3881 return USR_ASG; 3882 case PLUS: 3883 return JCTree.Tag.PLUS; 3884 case PLUSEQ: 3885 return PLUS_ASG; 3886 case SUB: 3887 return MINUS; 3888 case SUBEQ: 3889 return MINUS_ASG; 3890 case STAR: 3891 return MUL; 3892 case STAREQ: 3893 return MUL_ASG; 3894 case SLASH: 3895 return DIV; 3896 case SLASHEQ: 3897 return DIV_ASG; 3898 case PERCENT: 3899 return MOD; 3900 case PERCENTEQ: 3901 return MOD_ASG; 3902 case INSTANCEOF: 3903 return TYPETEST; 3904 default: 3905 return NO_TAG; 3906 } 3907 } 3908 3909 /** Return operation tag of unary operator represented by token, 3910 * No_TAG if token is not a binary operator. 3911 */ 3912 static JCTree.Tag unoptag(TokenKind token) { 3913 switch (token) { 3914 case PLUS: 3915 return POS; 3916 case SUB: 3917 return NEG; 3918 case BANG: 3919 return NOT; 3920 case TILDE: 3921 return COMPL; 3922 case PLUSPLUS: 3923 return PREINC; 3924 case SUBSUB: 3925 return PREDEC; 3926 default: 3927 return NO_TAG; 3928 } 3929 } 3930 3931 /** Return type tag of basic type represented by token, 3932 * NONE if token is not a basic type identifier. 3933 */ 3934 static TypeTag typetag(TokenKind token) { 3935 switch (token) { 3936 case BYTE: 3937 return TypeTag.BYTE; 3938 case CHAR: 3939 return TypeTag.CHAR; 3940 case SHORT: 3941 return TypeTag.SHORT; 3942 case INT: 3943 return TypeTag.INT; 3944 case LONG: 3945 return TypeTag.LONG; 3946 case FLOAT: 3947 return TypeTag.FLOAT; 3948 case DOUBLE: 3949 return TypeTag.DOUBLE; 3950 case BOOLEAN: 3951 return TypeTag.BOOLEAN; 3952 default: 3953 return TypeTag.NONE; 3954 } 3955 } 3956 3957 void checkGenerics() { 3958 if (!allowGenerics) { 3959 error(token.pos, "generics.not.supported.in.source", source.name); 3960 allowGenerics = true; 3961 } 3962 } 3963 void checkVarargs() { 3964 if (!allowVarargs) { 3965 error(token.pos, "varargs.not.supported.in.source", source.name); 3966 allowVarargs = true; 3967 } 3968 } 3969 void checkForeach() { 3970 if (!allowForeach) { 3971 error(token.pos, "foreach.not.supported.in.source", source.name); 3972 allowForeach = true; 3973 } 3974 } 3975 void checkStaticImports() { 3976 if (!allowStaticImport) { 3977 error(token.pos, "static.import.not.supported.in.source", source.name); 3978 allowStaticImport = true; 3979 } 3980 } 3981 void checkAnnotations() { 3982 if (!allowAnnotations) { 3983 error(token.pos, "annotations.not.supported.in.source", source.name); 3984 allowAnnotations = true; 3985 } 3986 } 3987 void checkDiamond() { 3988 if (!allowDiamond) { 3989 error(token.pos, "diamond.not.supported.in.source", source.name); 3990 allowDiamond = true; 3991 } 3992 } 3993 void checkMulticatch() { 3994 if (!allowMulticatch) { 3995 error(token.pos, "multicatch.not.supported.in.source", source.name); 3996 allowMulticatch = true; 3997 } 3998 } 3999 void checkTryWithResources() { 4000 if (!allowTWR) { 4001 error(token.pos, "try.with.resources.not.supported.in.source", source.name); 4002 allowTWR = true; 4003 } 4004 } 4005 void checkLambda() { 4006 if (!allowLambda) { 4007 log.error(token.pos, "lambda.not.supported.in.source", source.name); 4008 allowLambda = true; 4009 } 4010 } 4011 void checkMethodReferences() { 4012 if (!allowMethodReferences) { 4013 log.error(token.pos, "method.references.not.supported.in.source", source.name); 4014 allowMethodReferences = true; 4015 } 4016 } 4017 void checkDefaultMethods() { 4018 if (!allowDefaultMethods) { 4019 log.error(token.pos, "default.methods.not.supported.in.source", source.name); 4020 allowDefaultMethods = true; 4021 } 4022 } 4023 void checkIntersectionTypesInCast() { 4024 if (!allowIntersectionTypesInCast) { 4025 log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name); 4026 allowIntersectionTypesInCast = true; 4027 } 4028 } 4029 void checkStaticInterfaceMethods() { 4030 if (!allowStaticInterfaceMethods) { 4031 log.error(token.pos, "static.intf.methods.not.supported.in.source", source.name); 4032 allowStaticInterfaceMethods = true; 4033 } 4034 } 4035 void checkTypeAnnotations() { 4036 if (!allowTypeAnnotations) { 4037 log.error(token.pos, "type.annotations.not.supported.in.source", source.name); 4038 allowTypeAnnotations = true; 4039 } 4040 } 4041 4042 /* 4043 * a functional source tree and end position mappings 4044 */ 4045 protected static class SimpleEndPosTable extends AbstractEndPosTable { 4046 4047 private final Map<JCTree, Integer> endPosMap; 4048 4049 SimpleEndPosTable(JavacParser parser) { 4050 super(parser); 4051 endPosMap = new HashMap<JCTree, Integer>(); 4052 } 4053 4054 protected void storeEnd(JCTree tree, int endpos) { 4055 endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos); 4056 } 4057 4058 protected <T extends JCTree> T to(T t) { 4059 storeEnd(t, parser.token.endPos); 4060 return t; 4061 } 4062 4063 protected <T extends JCTree> T toP(T t) { 4064 storeEnd(t, parser.S.prevToken().endPos); 4065 return t; 4066 } 4067 4068 public int getEndPos(JCTree tree) { 4069 Integer value = endPosMap.get(tree); 4070 return (value == null) ? Position.NOPOS : value; 4071 } 4072 4073 public int replaceTree(JCTree oldTree, JCTree newTree) { 4074 Integer pos = endPosMap.remove(oldTree); 4075 if (pos != null) { 4076 endPosMap.put(newTree, pos); 4077 return pos; 4078 } 4079 return Position.NOPOS; 4080 } 4081 } 4082 4083 /* 4084 * a default skeletal implementation without any mapping overhead. 4085 */ 4086 protected static class EmptyEndPosTable extends AbstractEndPosTable { 4087 4088 EmptyEndPosTable(JavacParser parser) { 4089 super(parser); 4090 } 4091 4092 protected void storeEnd(JCTree tree, int endpos) { /* empty */ } 4093 4094 protected <T extends JCTree> T to(T t) { 4095 return t; 4096 } 4097 4098 protected <T extends JCTree> T toP(T t) { 4099 return t; 4100 } 4101 4102 public int getEndPos(JCTree tree) { 4103 return Position.NOPOS; 4104 } 4105 4106 public int replaceTree(JCTree oldTree, JCTree newTree) { 4107 return Position.NOPOS; 4108 } 4109 4110 } 4111 4112 protected static abstract class AbstractEndPosTable implements EndPosTable { 4113 /** 4114 * The current parser. 4115 */ 4116 protected JavacParser parser; 4117 4118 /** 4119 * Store the last error position. 4120 */ 4121 protected int errorEndPos; 4122 4123 public AbstractEndPosTable(JavacParser parser) { 4124 this.parser = parser; 4125 } 4126 4127 /** 4128 * Store ending position for a tree, the value of which is the greater 4129 * of last error position and the given ending position. 4130 * @param tree The tree. 4131 * @param endpos The ending position to associate with the tree. 4132 */ 4133 protected abstract void storeEnd(JCTree tree, int endpos); 4134 4135 /** 4136 * Store current token's ending position for a tree, the value of which 4137 * will be the greater of last error position and the ending position of 4138 * the current token. 4139 * @param t The tree. 4140 */ 4141 protected abstract <T extends JCTree> T to(T t); 4142 4143 /** 4144 * Store current token's ending position for a tree, the value of which 4145 * will be the greater of last error position and the ending position of 4146 * the previous token. 4147 * @param t The tree. 4148 */ 4149 protected abstract <T extends JCTree> T toP(T t); 4150 4151 /** 4152 * Set the error position during the parsing phases, the value of which 4153 * will be set only if it is greater than the last stored error position. 4154 * @param errPos The error position 4155 */ 4156 protected void setErrorEndPos(int errPos) { 4157 if (errPos > errorEndPos) { 4158 errorEndPos = errPos; 4159 } 4160 } 4161 4162 protected void setParser(JavacParser parser) { 4163 this.parser = parser; 4164 } 4165 } 4166 }