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