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