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