JavacParser.java revision 2789:014b653eafa9
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 t = bracketsSuffix(t); 1213 } else { 1214 if ((mode & EXPR) != 0) { 1215 mode = EXPR; 1216 JCExpression t1 = term(); 1217 if (!annos.isEmpty()) t = illegal(annos.head.pos); 1218 t = to(F.at(pos).Indexed(t, t1)); 1219 } 1220 accept(RBRACKET); 1221 } 1222 break loop; 1223 case LPAREN: 1224 if ((mode & EXPR) != 0) { 1225 mode = EXPR; 1226 t = arguments(typeArgs, t); 1227 if (!annos.isEmpty()) t = illegal(annos.head.pos); 1228 typeArgs = null; 1229 } 1230 break loop; 1231 case DOT: 1232 nextToken(); 1233 int oldmode = mode; 1234 mode &= ~NOPARAMS; 1235 typeArgs = typeArgumentsOpt(EXPR); 1236 mode = oldmode; 1237 if ((mode & EXPR) != 0) { 1238 switch (token.kind) { 1239 case CLASS: 1240 if (typeArgs != null) return illegal(); 1241 mode = EXPR; 1242 t = to(F.at(pos).Select(t, names._class)); 1243 nextToken(); 1244 break loop; 1245 case THIS: 1246 if (typeArgs != null) return illegal(); 1247 mode = EXPR; 1248 t = to(F.at(pos).Select(t, names._this)); 1249 nextToken(); 1250 break loop; 1251 case SUPER: 1252 mode = EXPR; 1253 t = to(F.at(pos).Select(t, names._super)); 1254 t = superSuffix(typeArgs, t); 1255 typeArgs = null; 1256 break loop; 1257 case NEW: 1258 if (typeArgs != null) return illegal(); 1259 mode = EXPR; 1260 int pos1 = token.pos; 1261 nextToken(); 1262 if (token.kind == LT) typeArgs = typeArguments(false); 1263 t = innerCreator(pos1, typeArgs, t); 1264 typeArgs = null; 1265 break loop; 1266 } 1267 } 1268 1269 List<JCAnnotation> tyannos = null; 1270 if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) { 1271 tyannos = typeAnnotationsOpt(); 1272 } 1273 // typeArgs saved for next loop iteration. 1274 t = toP(F.at(pos).Select(t, ident())); 1275 if (tyannos != null && tyannos.nonEmpty()) { 1276 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); 1277 } 1278 break; 1279 case ELLIPSIS: 1280 if (this.permitTypeAnnotationsPushBack) { 1281 this.typeAnnotationsPushedBack = annos; 1282 } else if (annos.nonEmpty()) { 1283 // Don't return here -- error recovery attempt 1284 illegal(annos.head.pos); 1285 } 1286 break loop; 1287 case LT: 1288 if ((mode & TYPE) == 0 && isUnboundMemberRef()) { 1289 //this is an unbound method reference whose qualifier 1290 //is a generic type i.e. A<S>::m 1291 int pos1 = token.pos; 1292 accept(LT); 1293 ListBuffer<JCExpression> args = new ListBuffer<>(); 1294 args.append(typeArgument()); 1295 while (token.kind == COMMA) { 1296 nextToken(); 1297 args.append(typeArgument()); 1298 } 1299 accept(GT); 1300 t = toP(F.at(pos1).TypeApply(t, args.toList())); 1301 while (token.kind == DOT) { 1302 nextToken(); 1303 mode = TYPE; 1304 t = toP(F.at(token.pos).Select(t, ident())); 1305 t = typeArgumentsOpt(t); 1306 } 1307 t = bracketsOpt(t); 1308 if (token.kind != COLCOL) { 1309 //method reference expected here 1310 t = illegal(); 1311 } 1312 mode = EXPR; 1313 return term3Rest(t, typeArgs); 1314 } 1315 break loop; 1316 default: 1317 break loop; 1318 } 1319 } 1320 } 1321 if (typeArgs != null) illegal(); 1322 t = typeArgumentsOpt(t); 1323 break; 1324 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 1325 case DOUBLE: case BOOLEAN: 1326 if (typeArgs != null) illegal(); 1327 t = bracketsSuffix(bracketsOpt(basicType())); 1328 break; 1329 case VOID: 1330 if (typeArgs != null) illegal(); 1331 if ((mode & EXPR) != 0) { 1332 nextToken(); 1333 if (token.kind == DOT) { 1334 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID)); 1335 t = bracketsSuffix(ti); 1336 } else { 1337 return illegal(pos); 1338 } 1339 } else { 1340 // Support the corner case of myMethodHandle.<void>invoke() by passing 1341 // a void type (like other primitive types) to the next phase. 1342 // The error will be reported in Attr.attribTypes or Attr.visitApply. 1343 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID)); 1344 nextToken(); 1345 return ti; 1346 //return illegal(); 1347 } 1348 break; 1349 default: 1350 return illegal(); 1351 } 1352 return term3Rest(t, typeArgs); 1353 } 1354 1355 JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) { 1356 if (typeArgs != null) illegal(); 1357 while (true) { 1358 int pos1 = token.pos; 1359 final List<JCAnnotation> annos = typeAnnotationsOpt(); 1360 1361 if (token.kind == LBRACKET) { 1362 nextToken(); 1363 if ((mode & TYPE) != 0) { 1364 int oldmode = mode; 1365 mode = TYPE; 1366 if (token.kind == RBRACKET) { 1367 nextToken(); 1368 t = bracketsOpt(t); 1369 t = toP(F.at(pos1).TypeArray(t)); 1370 if (token.kind == COLCOL) { 1371 mode = EXPR; 1372 continue; 1373 } 1374 if (annos.nonEmpty()) { 1375 t = toP(F.at(pos1).AnnotatedType(annos, t)); 1376 } 1377 return t; 1378 } 1379 mode = oldmode; 1380 } 1381 if ((mode & EXPR) != 0) { 1382 mode = EXPR; 1383 JCExpression t1 = term(); 1384 t = to(F.at(pos1).Indexed(t, t1)); 1385 } 1386 accept(RBRACKET); 1387 } else if (token.kind == DOT) { 1388 nextToken(); 1389 typeArgs = typeArgumentsOpt(EXPR); 1390 if (token.kind == SUPER && (mode & EXPR) != 0) { 1391 mode = EXPR; 1392 t = to(F.at(pos1).Select(t, names._super)); 1393 nextToken(); 1394 t = arguments(typeArgs, t); 1395 typeArgs = null; 1396 } else if (token.kind == NEW && (mode & EXPR) != 0) { 1397 if (typeArgs != null) return illegal(); 1398 mode = EXPR; 1399 int pos2 = token.pos; 1400 nextToken(); 1401 if (token.kind == LT) typeArgs = typeArguments(false); 1402 t = innerCreator(pos2, typeArgs, t); 1403 typeArgs = null; 1404 } else { 1405 List<JCAnnotation> tyannos = null; 1406 if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) { 1407 // is the mode check needed? 1408 tyannos = typeAnnotationsOpt(); 1409 } 1410 t = toP(F.at(pos1).Select(t, ident())); 1411 if (tyannos != null && tyannos.nonEmpty()) { 1412 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); 1413 } 1414 t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); 1415 typeArgs = null; 1416 } 1417 } else if ((mode & EXPR) != 0 && token.kind == COLCOL) { 1418 mode = EXPR; 1419 if (typeArgs != null) return illegal(); 1420 accept(COLCOL); 1421 t = memberReferenceSuffix(pos1, t); 1422 } else { 1423 if (!annos.isEmpty()) { 1424 if (permitTypeAnnotationsPushBack) 1425 typeAnnotationsPushedBack = annos; 1426 else 1427 return illegal(annos.head.pos); 1428 } 1429 break; 1430 } 1431 } 1432 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) { 1433 mode = EXPR; 1434 t = to(F.at(token.pos).Unary( 1435 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t)); 1436 nextToken(); 1437 } 1438 return toP(t); 1439 } 1440 1441 /** 1442 * If we see an identifier followed by a '<' it could be an unbound 1443 * method reference or a binary expression. To disambiguate, look for a 1444 * matching '>' and see if the subsequent terminal is either '.' or '::'. 1445 */ 1446 @SuppressWarnings("fallthrough") 1447 boolean isUnboundMemberRef() { 1448 int pos = 0, depth = 0; 1449 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) { 1450 switch (t.kind) { 1451 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER: 1452 case DOT: case RBRACKET: case LBRACKET: case COMMA: 1453 case BYTE: case SHORT: case INT: case LONG: case FLOAT: 1454 case DOUBLE: case BOOLEAN: case CHAR: 1455 case MONKEYS_AT: 1456 break; 1457 1458 case LPAREN: 1459 // skip annotation values 1460 int nesting = 0; 1461 for (; ; pos++) { 1462 TokenKind tk2 = S.token(pos).kind; 1463 switch (tk2) { 1464 case EOF: 1465 return false; 1466 case LPAREN: 1467 nesting++; 1468 break; 1469 case RPAREN: 1470 nesting--; 1471 if (nesting == 0) { 1472 continue outer; 1473 } 1474 break; 1475 } 1476 } 1477 1478 case LT: 1479 depth++; break; 1480 case GTGTGT: 1481 depth--; 1482 case GTGT: 1483 depth--; 1484 case GT: 1485 depth--; 1486 if (depth == 0) { 1487 TokenKind nextKind = S.token(pos + 1).kind; 1488 return 1489 nextKind == TokenKind.DOT || 1490 nextKind == TokenKind.LBRACKET || 1491 nextKind == TokenKind.COLCOL; 1492 } 1493 break; 1494 default: 1495 return false; 1496 } 1497 } 1498 } 1499 1500 /** 1501 * If we see an identifier followed by a '<' it could be an unbound 1502 * method reference or a binary expression. To disambiguate, look for a 1503 * matching '>' and see if the subsequent terminal is either '.' or '::'. 1504 */ 1505 @SuppressWarnings("fallthrough") 1506 ParensResult analyzeParens() { 1507 int depth = 0; 1508 boolean type = false; 1509 outer: for (int lookahead = 0 ; ; lookahead++) { 1510 TokenKind tk = S.token(lookahead).kind; 1511 switch (tk) { 1512 case COMMA: 1513 type = true; 1514 case EXTENDS: case SUPER: case DOT: case AMP: 1515 //skip 1516 break; 1517 case QUES: 1518 if (peekToken(lookahead, EXTENDS) || 1519 peekToken(lookahead, SUPER)) { 1520 //wildcards 1521 type = true; 1522 } 1523 break; 1524 case BYTE: case SHORT: case INT: case LONG: case FLOAT: 1525 case DOUBLE: case BOOLEAN: case CHAR: case VOID: 1526 if (peekToken(lookahead, RPAREN)) { 1527 //Type, ')' -> cast 1528 return ParensResult.CAST; 1529 } else if (peekToken(lookahead, LAX_IDENTIFIER)) { 1530 //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda 1531 return ParensResult.EXPLICIT_LAMBDA; 1532 } 1533 break; 1534 case LPAREN: 1535 if (lookahead != 0) { 1536 // '(' in a non-starting position -> parens 1537 return ParensResult.PARENS; 1538 } else if (peekToken(lookahead, RPAREN)) { 1539 // '(', ')' -> explicit lambda 1540 return ParensResult.EXPLICIT_LAMBDA; 1541 } 1542 break; 1543 case RPAREN: 1544 // if we have seen something that looks like a type, 1545 // then it's a cast expression 1546 if (type) return ParensResult.CAST; 1547 // otherwise, disambiguate cast vs. parenthesized expression 1548 // based on subsequent token. 1549 switch (S.token(lookahead + 1).kind) { 1550 /*case PLUSPLUS: case SUBSUB: */ 1551 case BANG: case TILDE: 1552 case LPAREN: case THIS: case SUPER: 1553 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: 1554 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: 1555 case TRUE: case FALSE: case NULL: 1556 case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE: 1557 case BYTE: case SHORT: case CHAR: case INT: 1558 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: 1559 return ParensResult.CAST; 1560 default: 1561 return ParensResult.PARENS; 1562 } 1563 case UNDERSCORE: 1564 case ASSERT: 1565 case ENUM: 1566 case IDENTIFIER: 1567 if (peekToken(lookahead, LAX_IDENTIFIER)) { 1568 // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda 1569 return ParensResult.EXPLICIT_LAMBDA; 1570 } else if (peekToken(lookahead, RPAREN, ARROW)) { 1571 // Identifier, ')' '->' -> implicit lambda 1572 return ParensResult.IMPLICIT_LAMBDA; 1573 } 1574 type = false; 1575 break; 1576 case FINAL: 1577 case ELLIPSIS: 1578 //those can only appear in explicit lambdas 1579 return ParensResult.EXPLICIT_LAMBDA; 1580 case MONKEYS_AT: 1581 type = true; 1582 lookahead += 1; //skip '@' 1583 while (peekToken(lookahead, DOT)) { 1584 lookahead += 2; 1585 } 1586 if (peekToken(lookahead, LPAREN)) { 1587 lookahead++; 1588 //skip annotation values 1589 int nesting = 0; 1590 for (; ; lookahead++) { 1591 TokenKind tk2 = S.token(lookahead).kind; 1592 switch (tk2) { 1593 case EOF: 1594 return ParensResult.PARENS; 1595 case LPAREN: 1596 nesting++; 1597 break; 1598 case RPAREN: 1599 nesting--; 1600 if (nesting == 0) { 1601 continue outer; 1602 } 1603 break; 1604 } 1605 } 1606 } 1607 break; 1608 case LBRACKET: 1609 if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) { 1610 // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda 1611 return ParensResult.EXPLICIT_LAMBDA; 1612 } else if (peekToken(lookahead, RBRACKET, RPAREN) || 1613 peekToken(lookahead, RBRACKET, AMP)) { 1614 // '[', ']', ')' -> cast 1615 // '[', ']', '&' -> cast (intersection type) 1616 return ParensResult.CAST; 1617 } else if (peekToken(lookahead, RBRACKET)) { 1618 //consume the ']' and skip 1619 type = true; 1620 lookahead++; 1621 break; 1622 } else { 1623 return ParensResult.PARENS; 1624 } 1625 case LT: 1626 depth++; break; 1627 case GTGTGT: 1628 depth--; 1629 case GTGT: 1630 depth--; 1631 case GT: 1632 depth--; 1633 if (depth == 0) { 1634 if (peekToken(lookahead, RPAREN) || 1635 peekToken(lookahead, AMP)) { 1636 // '>', ')' -> cast 1637 // '>', '&' -> cast 1638 return ParensResult.CAST; 1639 } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) || 1640 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) || 1641 peekToken(lookahead, ELLIPSIS)) { 1642 // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda 1643 // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda 1644 // '>', '...' -> explicit lambda 1645 return ParensResult.EXPLICIT_LAMBDA; 1646 } 1647 //it looks a type, but could still be (i) a cast to generic type, 1648 //(ii) an unbound method reference or (iii) an explicit lambda 1649 type = true; 1650 break; 1651 } else if (depth < 0) { 1652 //unbalanced '<', '>' - not a generic type 1653 return ParensResult.PARENS; 1654 } 1655 break; 1656 default: 1657 //this includes EOF 1658 return ParensResult.PARENS; 1659 } 1660 } 1661 } 1662 1663 /** Accepts all identifier-like tokens */ 1664 protected Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() { 1665 public boolean accepts(TokenKind t) { 1666 return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM; 1667 } 1668 }; 1669 1670 enum ParensResult { 1671 CAST, 1672 EXPLICIT_LAMBDA, 1673 IMPLICIT_LAMBDA, 1674 PARENS 1675 } 1676 1677 JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) { 1678 List<JCVariableDecl> params = explicitParams ? 1679 formalParameters(true) : 1680 implicitParameters(hasParens); 1681 1682 return lambdaExpressionOrStatementRest(params, pos); 1683 } 1684 1685 JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) { 1686 checkLambda(); 1687 accept(ARROW); 1688 1689 return token.kind == LBRACE ? 1690 lambdaStatement(args, pos, pos) : 1691 lambdaExpression(args, pos); 1692 } 1693 1694 JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) { 1695 JCBlock block = block(pos2, 0); 1696 return toP(F.at(pos).Lambda(args, block)); 1697 } 1698 1699 JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) { 1700 JCTree expr = parseExpression(); 1701 return toP(F.at(pos).Lambda(args, expr)); 1702 } 1703 1704 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments] 1705 */ 1706 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { 1707 nextToken(); 1708 if (token.kind == LPAREN || typeArgs != null) { 1709 t = arguments(typeArgs, t); 1710 } else if (token.kind == COLCOL) { 1711 if (typeArgs != null) return illegal(); 1712 t = memberReferenceSuffix(t); 1713 } else { 1714 int pos = token.pos; 1715 accept(DOT); 1716 typeArgs = (token.kind == LT) ? typeArguments(false) : null; 1717 t = toP(F.at(pos).Select(t, ident())); 1718 t = argumentsOpt(typeArgs, t); 1719 } 1720 return t; 1721 } 1722 1723 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN 1724 */ 1725 JCPrimitiveTypeTree basicType() { 1726 JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind))); 1727 nextToken(); 1728 return t; 1729 } 1730 1731 /** ArgumentsOpt = [ Arguments ] 1732 */ 1733 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) { 1734 if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) { 1735 mode = EXPR; 1736 return arguments(typeArgs, t); 1737 } else { 1738 return t; 1739 } 1740 } 1741 1742 /** Arguments = "(" [Expression { COMMA Expression }] ")" 1743 */ 1744 List<JCExpression> arguments() { 1745 ListBuffer<JCExpression> args = new ListBuffer<>(); 1746 if (token.kind == LPAREN) { 1747 nextToken(); 1748 if (token.kind != RPAREN) { 1749 args.append(parseExpression()); 1750 while (token.kind == COMMA) { 1751 nextToken(); 1752 args.append(parseExpression()); 1753 } 1754 } 1755 accept(RPAREN); 1756 } else { 1757 syntaxError(token.pos, "expected", LPAREN); 1758 } 1759 return args.toList(); 1760 } 1761 1762 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) { 1763 int pos = token.pos; 1764 List<JCExpression> args = arguments(); 1765 return toP(F.at(pos).Apply(typeArgs, t, args)); 1766 } 1767 1768 /** TypeArgumentsOpt = [ TypeArguments ] 1769 */ 1770 JCExpression typeArgumentsOpt(JCExpression t) { 1771 if (token.kind == LT && 1772 (mode & TYPE) != 0 && 1773 (mode & NOPARAMS) == 0) { 1774 mode = TYPE; 1775 return typeArguments(t, false); 1776 } else { 1777 return t; 1778 } 1779 } 1780 List<JCExpression> typeArgumentsOpt() { 1781 return typeArgumentsOpt(TYPE); 1782 } 1783 1784 List<JCExpression> typeArgumentsOpt(int useMode) { 1785 if (token.kind == LT) { 1786 if ((mode & useMode) == 0 || 1787 (mode & NOPARAMS) != 0) { 1788 illegal(); 1789 } 1790 mode = useMode; 1791 return typeArguments(false); 1792 } 1793 return null; 1794 } 1795 1796 /** 1797 * {@literal 1798 * TypeArguments = "<" TypeArgument {"," TypeArgument} ">" 1799 * } 1800 */ 1801 List<JCExpression> typeArguments(boolean diamondAllowed) { 1802 if (token.kind == LT) { 1803 nextToken(); 1804 if (token.kind == GT && diamondAllowed) { 1805 checkDiamond(); 1806 mode |= DIAMOND; 1807 nextToken(); 1808 return List.nil(); 1809 } else { 1810 ListBuffer<JCExpression> args = new ListBuffer<>(); 1811 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 1812 while (token.kind == COMMA) { 1813 nextToken(); 1814 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 1815 } 1816 switch (token.kind) { 1817 1818 case GTGTGTEQ: case GTGTEQ: case GTEQ: 1819 case GTGTGT: case GTGT: 1820 token = S.split(); 1821 break; 1822 case GT: 1823 nextToken(); 1824 break; 1825 default: 1826 args.append(syntaxError(token.pos, "expected", GT)); 1827 break; 1828 } 1829 return args.toList(); 1830 } 1831 } else { 1832 return List.<JCExpression>of(syntaxError(token.pos, "expected", LT)); 1833 } 1834 } 1835 1836 /** 1837 * {@literal 1838 * TypeArgument = Type 1839 * | [Annotations] "?" 1840 * | [Annotations] "?" EXTENDS Type {"&" Type} 1841 * | [Annotations] "?" SUPER Type 1842 * } 1843 */ 1844 JCExpression typeArgument() { 1845 List<JCAnnotation> annotations = typeAnnotationsOpt(); 1846 if (token.kind != QUES) return parseType(annotations); 1847 int pos = token.pos; 1848 nextToken(); 1849 JCExpression result; 1850 if (token.kind == EXTENDS) { 1851 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); 1852 nextToken(); 1853 JCExpression bound = parseType(); 1854 result = F.at(pos).Wildcard(t, bound); 1855 } else if (token.kind == SUPER) { 1856 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); 1857 nextToken(); 1858 JCExpression bound = parseType(); 1859 result = F.at(pos).Wildcard(t, bound); 1860 } else if (LAX_IDENTIFIER.accepts(token.kind)) { 1861 //error recovery 1862 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 1863 JCExpression wc = toP(F.at(pos).Wildcard(t, null)); 1864 JCIdent id = toP(F.at(token.pos).Ident(ident())); 1865 JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id)); 1866 reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER); 1867 result = err; 1868 } else { 1869 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); 1870 result = toP(F.at(pos).Wildcard(t, null)); 1871 } 1872 if (!annotations.isEmpty()) { 1873 result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result)); 1874 } 1875 return result; 1876 } 1877 1878 JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) { 1879 int pos = token.pos; 1880 List<JCExpression> args = typeArguments(diamondAllowed); 1881 return toP(F.at(pos).TypeApply(t, args)); 1882 } 1883 1884 /** 1885 * BracketsOpt = { [Annotations] "[" "]" }* 1886 * 1887 * <p> 1888 * 1889 * <code>annotations</code> is the list of annotations targeting 1890 * the expression <code>t</code>. 1891 */ 1892 private JCExpression bracketsOpt(JCExpression t, 1893 List<JCAnnotation> annotations) { 1894 List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt(); 1895 1896 if (token.kind == LBRACKET) { 1897 int pos = token.pos; 1898 nextToken(); 1899 t = bracketsOptCont(t, pos, nextLevelAnnotations); 1900 } else if (!nextLevelAnnotations.isEmpty()) { 1901 if (permitTypeAnnotationsPushBack) { 1902 this.typeAnnotationsPushedBack = nextLevelAnnotations; 1903 } else { 1904 return illegal(nextLevelAnnotations.head.pos); 1905 } 1906 } 1907 1908 if (!annotations.isEmpty()) { 1909 t = toP(F.at(token.pos).AnnotatedType(annotations, t)); 1910 } 1911 return t; 1912 } 1913 1914 /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ] 1915 */ 1916 private JCExpression bracketsOpt(JCExpression t) { 1917 return bracketsOpt(t, List.<JCAnnotation>nil()); 1918 } 1919 1920 private JCExpression bracketsOptCont(JCExpression t, int pos, 1921 List<JCAnnotation> annotations) { 1922 accept(RBRACKET); 1923 t = bracketsOpt(t); 1924 t = toP(F.at(pos).TypeArray(t)); 1925 if (annotations.nonEmpty()) { 1926 t = toP(F.at(pos).AnnotatedType(annotations, t)); 1927 } 1928 return t; 1929 } 1930 1931 /** BracketsSuffixExpr = "." CLASS 1932 * BracketsSuffixType = 1933 */ 1934 JCExpression bracketsSuffix(JCExpression t) { 1935 if ((mode & EXPR) != 0 && token.kind == DOT) { 1936 mode = EXPR; 1937 int pos = token.pos; 1938 nextToken(); 1939 accept(CLASS); 1940 if (token.pos == endPosTable.errorEndPos) { 1941 // error recovery 1942 Name name; 1943 if (LAX_IDENTIFIER.accepts(token.kind)) { 1944 name = token.name(); 1945 nextToken(); 1946 } else { 1947 name = names.error; 1948 } 1949 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name)))); 1950 } else { 1951 Tag tag = t.getTag(); 1952 // Type annotations are illegal on class literals. Annotated non array class literals 1953 // are complained about directly in term3(), Here check for type annotations on dimensions 1954 // taking care to handle some interior dimension(s) being annotated. 1955 if ((tag == TYPEARRAY && TreeInfo.containsTypeAnnotation(t)) || tag == ANNOTATED_TYPE) 1956 syntaxError("no.annotations.on.dot.class"); 1957 t = toP(F.at(pos).Select(t, names._class)); 1958 } 1959 } else if ((mode & TYPE) != 0) { 1960 if (token.kind != COLCOL) { 1961 mode = TYPE; 1962 } 1963 } else if (token.kind != COLCOL) { 1964 syntaxError(token.pos, "dot.class.expected"); 1965 } 1966 return t; 1967 } 1968 1969 /** 1970 * MemberReferenceSuffix = "::" [TypeArguments] Ident 1971 * | "::" [TypeArguments] "new" 1972 */ 1973 JCExpression memberReferenceSuffix(JCExpression t) { 1974 int pos1 = token.pos; 1975 accept(COLCOL); 1976 return memberReferenceSuffix(pos1, t); 1977 } 1978 1979 JCExpression memberReferenceSuffix(int pos1, JCExpression t) { 1980 checkMethodReferences(); 1981 mode = EXPR; 1982 List<JCExpression> typeArgs = null; 1983 if (token.kind == LT) { 1984 typeArgs = typeArguments(false); 1985 } 1986 Name refName; 1987 ReferenceMode refMode; 1988 if (token.kind == NEW) { 1989 refMode = ReferenceMode.NEW; 1990 refName = names.init; 1991 nextToken(); 1992 } else { 1993 refMode = ReferenceMode.INVOKE; 1994 refName = ident(); 1995 } 1996 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs)); 1997 } 1998 1999 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) 2000 */ 2001 JCExpression creator(int newpos, List<JCExpression> typeArgs) { 2002 List<JCAnnotation> newAnnotations = typeAnnotationsOpt(); 2003 2004 switch (token.kind) { 2005 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 2006 case DOUBLE: case BOOLEAN: 2007 if (typeArgs == null) { 2008 if (newAnnotations.isEmpty()) { 2009 return arrayCreatorRest(newpos, basicType()); 2010 } else { 2011 return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType()))); 2012 } 2013 } 2014 break; 2015 default: 2016 } 2017 JCExpression t = qualident(true); 2018 2019 int oldmode = mode; 2020 mode = TYPE; 2021 boolean diamondFound = false; 2022 int lastTypeargsPos = -1; 2023 if (token.kind == LT) { 2024 lastTypeargsPos = token.pos; 2025 t = typeArguments(t, true); 2026 diamondFound = (mode & DIAMOND) != 0; 2027 } 2028 while (token.kind == DOT) { 2029 if (diamondFound) { 2030 //cannot select after a diamond 2031 illegal(); 2032 } 2033 int pos = token.pos; 2034 nextToken(); 2035 List<JCAnnotation> tyannos = typeAnnotationsOpt(); 2036 t = toP(F.at(pos).Select(t, ident())); 2037 2038 if (tyannos != null && tyannos.nonEmpty()) { 2039 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); 2040 } 2041 2042 if (token.kind == LT) { 2043 lastTypeargsPos = token.pos; 2044 t = typeArguments(t, true); 2045 diamondFound = (mode & DIAMOND) != 0; 2046 } 2047 } 2048 mode = oldmode; 2049 if (token.kind == LBRACKET || token.kind == MONKEYS_AT) { 2050 // handle type annotations for non primitive arrays 2051 if (newAnnotations.nonEmpty()) { 2052 t = insertAnnotationsToMostInner(t, newAnnotations, false); 2053 } 2054 2055 JCExpression e = arrayCreatorRest(newpos, t); 2056 if (diamondFound) { 2057 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond"); 2058 return toP(F.at(newpos).Erroneous(List.of(e))); 2059 } 2060 else if (typeArgs != null) { 2061 int pos = newpos; 2062 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) { 2063 // note: this should always happen but we should 2064 // not rely on this as the parser is continuously 2065 // modified to improve error recovery. 2066 pos = typeArgs.head.pos; 2067 } 2068 setErrorEndPos(S.prevToken().endPos); 2069 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e)); 2070 reportSyntaxError(err, "cannot.create.array.with.type.arguments"); 2071 return toP(err); 2072 } 2073 return e; 2074 } else if (token.kind == LPAREN) { 2075 JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t); 2076 if (newClass.def != null) { 2077 assert newClass.def.mods.annotations.isEmpty(); 2078 if (newAnnotations.nonEmpty()) { 2079 // Add type and declaration annotations to the new class; 2080 // com.sun.tools.javac.code.TypeAnnotations.TypeAnnotationPositions.visitNewClass(JCNewClass) 2081 // will later remove all type annotations and only leave the 2082 // declaration annotations. 2083 newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos); 2084 newClass.def.mods.annotations = newAnnotations; 2085 } 2086 } else { 2087 // handle type annotations for instantiations 2088 if (newAnnotations.nonEmpty()) { 2089 t = insertAnnotationsToMostInner(t, newAnnotations, false); 2090 newClass.clazz = t; 2091 } 2092 } 2093 return newClass; 2094 } else { 2095 setErrorEndPos(token.pos); 2096 reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET); 2097 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null)); 2098 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t))); 2099 } 2100 } 2101 2102 /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest 2103 */ 2104 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) { 2105 List<JCAnnotation> newAnnotations = typeAnnotationsOpt(); 2106 2107 JCExpression t = toP(F.at(token.pos).Ident(ident())); 2108 2109 if (newAnnotations.nonEmpty()) { 2110 t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t)); 2111 } 2112 2113 if (token.kind == LT) { 2114 int oldmode = mode; 2115 t = typeArguments(t, true); 2116 mode = oldmode; 2117 } 2118 return classCreatorRest(newpos, encl, typeArgs, t); 2119 } 2120 2121 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer 2122 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt ) 2123 */ 2124 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { 2125 List<JCAnnotation> annos = typeAnnotationsOpt(); 2126 2127 accept(LBRACKET); 2128 if (token.kind == RBRACKET) { 2129 accept(RBRACKET); 2130 elemtype = bracketsOpt(elemtype, annos); 2131 if (token.kind == LBRACE) { 2132 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype); 2133 if (annos.nonEmpty()) { 2134 // when an array initializer is present then 2135 // the parsed annotations should target the 2136 // new array tree 2137 // bracketsOpt inserts the annotation in 2138 // elemtype, and it needs to be corrected 2139 // 2140 JCAnnotatedType annotated = (JCAnnotatedType)elemtype; 2141 assert annotated.annotations == annos; 2142 na.annotations = annotated.annotations; 2143 na.elemtype = annotated.underlyingType; 2144 } 2145 return na; 2146 } else { 2147 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null)); 2148 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing"); 2149 } 2150 } else { 2151 ListBuffer<JCExpression> dims = new ListBuffer<>(); 2152 2153 // maintain array dimension type annotations 2154 ListBuffer<List<JCAnnotation>> dimAnnotations = new ListBuffer<>(); 2155 dimAnnotations.append(annos); 2156 2157 dims.append(parseExpression()); 2158 accept(RBRACKET); 2159 while (token.kind == LBRACKET 2160 || token.kind == MONKEYS_AT) { 2161 List<JCAnnotation> maybeDimAnnos = typeAnnotationsOpt(); 2162 int pos = token.pos; 2163 nextToken(); 2164 if (token.kind == RBRACKET) { 2165 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); 2166 } else { 2167 if (token.kind == RBRACKET) { // no dimension 2168 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); 2169 } else { 2170 dimAnnotations.append(maybeDimAnnos); 2171 dims.append(parseExpression()); 2172 accept(RBRACKET); 2173 } 2174 } 2175 } 2176 2177 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); 2178 na.dimAnnotations = dimAnnotations.toList(); 2179 return na; 2180 } 2181 } 2182 2183 /** ClassCreatorRest = Arguments [ClassBody] 2184 */ 2185 JCNewClass classCreatorRest(int newpos, 2186 JCExpression encl, 2187 List<JCExpression> typeArgs, 2188 JCExpression t) 2189 { 2190 List<JCExpression> args = arguments(); 2191 JCClassDecl body = null; 2192 if (token.kind == LBRACE) { 2193 int pos = token.pos; 2194 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 2195 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 2196 body = toP(F.at(pos).AnonymousClassDef(mods, defs)); 2197 } 2198 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); 2199 } 2200 2201 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" 2202 */ 2203 JCExpression arrayInitializer(int newpos, JCExpression t) { 2204 accept(LBRACE); 2205 ListBuffer<JCExpression> elems = new ListBuffer<>(); 2206 if (token.kind == COMMA) { 2207 nextToken(); 2208 } else if (token.kind != RBRACE) { 2209 elems.append(variableInitializer()); 2210 while (token.kind == COMMA) { 2211 nextToken(); 2212 if (token.kind == RBRACE) break; 2213 elems.append(variableInitializer()); 2214 } 2215 } 2216 accept(RBRACE); 2217 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList())); 2218 } 2219 2220 /** VariableInitializer = ArrayInitializer | Expression 2221 */ 2222 public JCExpression variableInitializer() { 2223 return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression(); 2224 } 2225 2226 /** ParExpression = "(" Expression ")" 2227 */ 2228 JCExpression parExpression() { 2229 int pos = token.pos; 2230 accept(LPAREN); 2231 JCExpression t = parseExpression(); 2232 accept(RPAREN); 2233 return toP(F.at(pos).Parens(t)); 2234 } 2235 2236 /** Block = "{" BlockStatements "}" 2237 */ 2238 JCBlock block(int pos, long flags) { 2239 accept(LBRACE); 2240 List<JCStatement> stats = blockStatements(); 2241 JCBlock t = F.at(pos).Block(flags, stats); 2242 while (token.kind == CASE || token.kind == DEFAULT) { 2243 syntaxError("orphaned", token.kind); 2244 switchBlockStatementGroups(); 2245 } 2246 // the Block node has a field "endpos" for first char of last token, which is 2247 // usually but not necessarily the last char of the last token. 2248 t.endpos = token.pos; 2249 accept(RBRACE); 2250 return toP(t); 2251 } 2252 2253 public JCBlock block() { 2254 return block(token.pos, 0); 2255 } 2256 2257 /** BlockStatements = { BlockStatement } 2258 * BlockStatement = LocalVariableDeclarationStatement 2259 * | ClassOrInterfaceOrEnumDeclaration 2260 * | [Ident ":"] Statement 2261 * LocalVariableDeclarationStatement 2262 * = { FINAL | '@' Annotation } Type VariableDeclarators ";" 2263 */ 2264 @SuppressWarnings("fallthrough") 2265 List<JCStatement> blockStatements() { 2266 //todo: skip to anchor on error(?) 2267 int lastErrPos = -1; 2268 ListBuffer<JCStatement> stats = new ListBuffer<>(); 2269 while (true) { 2270 List<JCStatement> stat = blockStatement(); 2271 if (stat.isEmpty()) { 2272 return stats.toList(); 2273 } else { 2274 // error recovery 2275 if (token.pos == lastErrPos) 2276 return stats.toList(); 2277 if (token.pos <= endPosTable.errorEndPos) { 2278 skip(false, true, true, true); 2279 lastErrPos = token.pos; 2280 } 2281 stats.addAll(stat); 2282 } 2283 } 2284 } 2285 2286 /* 2287 * Parse a Statement (JLS 14.5). As an enhancement to improve error recovery, 2288 * this method will also recognize variable and class declarations (which are 2289 * not legal for a Statement) by delegating the parsing to BlockStatement (JLS 14.2). 2290 * If any illegal declarations are found, they will be wrapped in an erroneous tree, 2291 * and an error will be produced by this method. 2292 */ 2293 JCStatement parseStatementAsBlock() { 2294 int pos = token.pos; 2295 List<JCStatement> stats = blockStatement(); 2296 if (stats.isEmpty()) { 2297 JCErroneous e = F.at(pos).Erroneous(); 2298 error(e, "illegal.start.of.stmt"); 2299 return F.at(pos).Exec(e); 2300 } else { 2301 JCStatement first = stats.head; 2302 String error = null; 2303 switch (first.getTag()) { 2304 case CLASSDEF: 2305 error = "class.not.allowed"; 2306 break; 2307 case VARDEF: 2308 error = "variable.not.allowed"; 2309 break; 2310 } 2311 if (error != null) { 2312 error(first, error); 2313 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats)); 2314 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist))); 2315 } 2316 return first; 2317 } 2318 } 2319 2320 /**This method parses a statement appearing inside a block. 2321 */ 2322 List<JCStatement> blockStatement() { 2323 //todo: skip to anchor on error(?) 2324 int pos = token.pos; 2325 switch (token.kind) { 2326 case RBRACE: case CASE: case DEFAULT: case EOF: 2327 return List.nil(); 2328 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: 2329 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: 2330 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: 2331 case ASSERT: 2332 return List.of(parseSimpleStatement()); 2333 case MONKEYS_AT: 2334 case FINAL: { 2335 Comment dc = token.comment(CommentStyle.JAVADOC); 2336 JCModifiers mods = modifiersOpt(); 2337 if (token.kind == INTERFACE || 2338 token.kind == CLASS || 2339 token.kind == ENUM) { 2340 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); 2341 } else { 2342 JCExpression t = parseType(); 2343 ListBuffer<JCStatement> stats = 2344 variableDeclarators(mods, t, new ListBuffer<JCStatement>()); 2345 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 2346 accept(SEMI); 2347 storeEnd(stats.last(), S.prevToken().endPos); 2348 return stats.toList(); 2349 } 2350 } 2351 case ABSTRACT: case STRICTFP: { 2352 Comment dc = token.comment(CommentStyle.JAVADOC); 2353 JCModifiers mods = modifiersOpt(); 2354 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); 2355 } 2356 case INTERFACE: 2357 case CLASS: 2358 Comment dc = token.comment(CommentStyle.JAVADOC); 2359 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); 2360 case ENUM: 2361 error(token.pos, "local.enum"); 2362 dc = token.comment(CommentStyle.JAVADOC); 2363 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); 2364 default: 2365 Token prevToken = token; 2366 JCExpression t = term(EXPR | TYPE); 2367 if (token.kind == COLON && t.hasTag(IDENT)) { 2368 nextToken(); 2369 JCStatement stat = parseStatementAsBlock(); 2370 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat)); 2371 } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { 2372 pos = token.pos; 2373 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 2374 F.at(pos); 2375 ListBuffer<JCStatement> stats = 2376 variableDeclarators(mods, t, new ListBuffer<JCStatement>()); 2377 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 2378 accept(SEMI); 2379 storeEnd(stats.last(), S.prevToken().endPos); 2380 return stats.toList(); 2381 } else { 2382 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 2383 t = checkExprStat(t); 2384 accept(SEMI); 2385 JCExpressionStatement expr = toP(F.at(pos).Exec(t)); 2386 return List.<JCStatement>of(expr); 2387 } 2388 } 2389 } 2390 2391 /** Statement = 2392 * Block 2393 * | IF ParExpression Statement [ELSE Statement] 2394 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement 2395 * | FOR "(" FormalParameter : Expression ")" Statement 2396 * | WHILE ParExpression Statement 2397 * | DO Statement WHILE ParExpression ";" 2398 * | TRY Block ( Catches | [Catches] FinallyPart ) 2399 * | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart] 2400 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" 2401 * | SYNCHRONIZED ParExpression Block 2402 * | RETURN [Expression] ";" 2403 * | THROW Expression ";" 2404 * | BREAK [Ident] ";" 2405 * | CONTINUE [Ident] ";" 2406 * | ASSERT Expression [ ":" Expression ] ";" 2407 * | ";" 2408 */ 2409 public JCStatement parseSimpleStatement() { 2410 int pos = token.pos; 2411 switch (token.kind) { 2412 case LBRACE: 2413 return block(); 2414 case IF: { 2415 nextToken(); 2416 JCExpression cond = parExpression(); 2417 JCStatement thenpart = parseStatementAsBlock(); 2418 JCStatement elsepart = null; 2419 if (token.kind == ELSE) { 2420 nextToken(); 2421 elsepart = parseStatementAsBlock(); 2422 } 2423 return F.at(pos).If(cond, thenpart, elsepart); 2424 } 2425 case FOR: { 2426 nextToken(); 2427 accept(LPAREN); 2428 List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit(); 2429 if (inits.length() == 1 && 2430 inits.head.hasTag(VARDEF) && 2431 ((JCVariableDecl) inits.head).init == null && 2432 token.kind == COLON) { 2433 JCVariableDecl var = (JCVariableDecl)inits.head; 2434 accept(COLON); 2435 JCExpression expr = parseExpression(); 2436 accept(RPAREN); 2437 JCStatement body = parseStatementAsBlock(); 2438 return F.at(pos).ForeachLoop(var, expr, body); 2439 } else { 2440 accept(SEMI); 2441 JCExpression cond = token.kind == SEMI ? null : parseExpression(); 2442 accept(SEMI); 2443 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); 2444 accept(RPAREN); 2445 JCStatement body = parseStatementAsBlock(); 2446 return F.at(pos).ForLoop(inits, cond, steps, body); 2447 } 2448 } 2449 case WHILE: { 2450 nextToken(); 2451 JCExpression cond = parExpression(); 2452 JCStatement body = parseStatementAsBlock(); 2453 return F.at(pos).WhileLoop(cond, body); 2454 } 2455 case DO: { 2456 nextToken(); 2457 JCStatement body = parseStatementAsBlock(); 2458 accept(WHILE); 2459 JCExpression cond = parExpression(); 2460 accept(SEMI); 2461 JCDoWhileLoop t = toP(F.at(pos).DoLoop(body, cond)); 2462 return t; 2463 } 2464 case TRY: { 2465 nextToken(); 2466 List<JCTree> resources = List.<JCTree>nil(); 2467 if (token.kind == LPAREN) { 2468 checkTryWithResources(); 2469 nextToken(); 2470 resources = resources(); 2471 accept(RPAREN); 2472 } 2473 JCBlock body = block(); 2474 ListBuffer<JCCatch> catchers = new ListBuffer<>(); 2475 JCBlock finalizer = null; 2476 if (token.kind == CATCH || token.kind == FINALLY) { 2477 while (token.kind == CATCH) catchers.append(catchClause()); 2478 if (token.kind == FINALLY) { 2479 nextToken(); 2480 finalizer = block(); 2481 } 2482 } else { 2483 if (allowTWR) { 2484 if (resources.isEmpty()) 2485 error(pos, "try.without.catch.finally.or.resource.decls"); 2486 } else 2487 error(pos, "try.without.catch.or.finally"); 2488 } 2489 return F.at(pos).Try(resources, body, catchers.toList(), finalizer); 2490 } 2491 case SWITCH: { 2492 nextToken(); 2493 JCExpression selector = parExpression(); 2494 accept(LBRACE); 2495 List<JCCase> cases = switchBlockStatementGroups(); 2496 JCSwitch t = to(F.at(pos).Switch(selector, cases)); 2497 accept(RBRACE); 2498 return t; 2499 } 2500 case SYNCHRONIZED: { 2501 nextToken(); 2502 JCExpression lock = parExpression(); 2503 JCBlock body = block(); 2504 return F.at(pos).Synchronized(lock, body); 2505 } 2506 case RETURN: { 2507 nextToken(); 2508 JCExpression result = token.kind == SEMI ? null : parseExpression(); 2509 accept(SEMI); 2510 JCReturn t = toP(F.at(pos).Return(result)); 2511 return t; 2512 } 2513 case THROW: { 2514 nextToken(); 2515 JCExpression exc = parseExpression(); 2516 accept(SEMI); 2517 JCThrow t = toP(F.at(pos).Throw(exc)); 2518 return t; 2519 } 2520 case BREAK: { 2521 nextToken(); 2522 Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null; 2523 accept(SEMI); 2524 JCBreak t = toP(F.at(pos).Break(label)); 2525 return t; 2526 } 2527 case CONTINUE: { 2528 nextToken(); 2529 Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null; 2530 accept(SEMI); 2531 JCContinue t = toP(F.at(pos).Continue(label)); 2532 return t; 2533 } 2534 case SEMI: 2535 nextToken(); 2536 return toP(F.at(pos).Skip()); 2537 case ELSE: 2538 int elsePos = token.pos; 2539 nextToken(); 2540 return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if"); 2541 case FINALLY: 2542 int finallyPos = token.pos; 2543 nextToken(); 2544 return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try"); 2545 case CATCH: 2546 return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try"); 2547 case ASSERT: { 2548 nextToken(); 2549 JCExpression assertion = parseExpression(); 2550 JCExpression message = null; 2551 if (token.kind == COLON) { 2552 nextToken(); 2553 message = parseExpression(); 2554 } 2555 accept(SEMI); 2556 JCAssert t = toP(F.at(pos).Assert(assertion, message)); 2557 return t; 2558 } 2559 default: 2560 Assert.error(); 2561 return null; 2562 } 2563 } 2564 2565 @Override 2566 public JCStatement parseStatement() { 2567 return parseStatementAsBlock(); 2568 } 2569 2570 private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) { 2571 int errPos = S.errPos(); 2572 JCTree stm = action.doRecover(this); 2573 S.errPos(errPos); 2574 return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key))); 2575 } 2576 2577 /** CatchClause = CATCH "(" FormalParameter ")" Block 2578 * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below. 2579 */ 2580 protected JCCatch catchClause() { 2581 int pos = token.pos; 2582 accept(CATCH); 2583 accept(LPAREN); 2584 JCModifiers mods = optFinal(Flags.PARAMETER); 2585 List<JCExpression> catchTypes = catchTypes(); 2586 JCExpression paramType = catchTypes.size() > 1 ? 2587 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) : 2588 catchTypes.head; 2589 JCVariableDecl formal = variableDeclaratorId(mods, paramType); 2590 accept(RPAREN); 2591 JCBlock body = block(); 2592 return F.at(pos).Catch(formal, body); 2593 } 2594 2595 List<JCExpression> catchTypes() { 2596 ListBuffer<JCExpression> catchTypes = new ListBuffer<>(); 2597 catchTypes.add(parseType()); 2598 while (token.kind == BAR) { 2599 checkMulticatch(); 2600 nextToken(); 2601 // Instead of qualident this is now parseType. 2602 // But would that allow too much, e.g. arrays or generics? 2603 catchTypes.add(parseType()); 2604 } 2605 return catchTypes.toList(); 2606 } 2607 2608 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup } 2609 * SwitchBlockStatementGroup = SwitchLabel BlockStatements 2610 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" 2611 */ 2612 List<JCCase> switchBlockStatementGroups() { 2613 ListBuffer<JCCase> cases = new ListBuffer<>(); 2614 while (true) { 2615 int pos = token.pos; 2616 switch (token.kind) { 2617 case CASE: 2618 case DEFAULT: 2619 cases.append(switchBlockStatementGroup()); 2620 break; 2621 case RBRACE: case EOF: 2622 return cases.toList(); 2623 default: 2624 nextToken(); // to ensure progress 2625 syntaxError(pos, "expected3", 2626 CASE, DEFAULT, RBRACE); 2627 } 2628 } 2629 } 2630 2631 protected JCCase switchBlockStatementGroup() { 2632 int pos = token.pos; 2633 List<JCStatement> stats; 2634 JCCase c; 2635 switch (token.kind) { 2636 case CASE: 2637 nextToken(); 2638 JCExpression pat = parseExpression(); 2639 accept(COLON); 2640 stats = blockStatements(); 2641 c = F.at(pos).Case(pat, stats); 2642 if (stats.isEmpty()) 2643 storeEnd(c, S.prevToken().endPos); 2644 return c; 2645 case DEFAULT: 2646 nextToken(); 2647 accept(COLON); 2648 stats = blockStatements(); 2649 c = F.at(pos).Case(null, stats); 2650 if (stats.isEmpty()) 2651 storeEnd(c, S.prevToken().endPos); 2652 return c; 2653 } 2654 throw new AssertionError("should not reach here"); 2655 } 2656 2657 /** MoreStatementExpressions = { COMMA StatementExpression } 2658 */ 2659 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos, 2660 JCExpression first, 2661 T stats) { 2662 // This Exec is a "StatementExpression"; it subsumes no terminating token 2663 stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); 2664 while (token.kind == COMMA) { 2665 nextToken(); 2666 pos = token.pos; 2667 JCExpression t = parseExpression(); 2668 // This Exec is a "StatementExpression"; it subsumes no terminating token 2669 stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); 2670 } 2671 return stats; 2672 } 2673 2674 /** ForInit = StatementExpression MoreStatementExpressions 2675 * | { FINAL | '@' Annotation } Type VariableDeclarators 2676 */ 2677 List<JCStatement> forInit() { 2678 ListBuffer<JCStatement> stats = new ListBuffer<>(); 2679 int pos = token.pos; 2680 if (token.kind == FINAL || token.kind == MONKEYS_AT) { 2681 return variableDeclarators(optFinal(0), parseType(), stats).toList(); 2682 } else { 2683 JCExpression t = term(EXPR | TYPE); 2684 if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { 2685 return variableDeclarators(modifiersOpt(), t, stats).toList(); 2686 } else if ((lastmode & TYPE) != 0 && token.kind == COLON) { 2687 error(pos, "bad.initializer", "for-loop"); 2688 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null)); 2689 } else { 2690 return moreStatementExpressions(pos, t, stats).toList(); 2691 } 2692 } 2693 } 2694 2695 /** ForUpdate = StatementExpression MoreStatementExpressions 2696 */ 2697 List<JCExpressionStatement> forUpdate() { 2698 return moreStatementExpressions(token.pos, 2699 parseExpression(), 2700 new ListBuffer<JCExpressionStatement>()).toList(); 2701 } 2702 2703 /** AnnotationsOpt = { '@' Annotation } 2704 * 2705 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION 2706 */ 2707 protected List<JCAnnotation> annotationsOpt(Tag kind) { 2708 if (token.kind != MONKEYS_AT) return List.nil(); // optimization 2709 ListBuffer<JCAnnotation> buf = new ListBuffer<>(); 2710 int prevmode = mode; 2711 while (token.kind == MONKEYS_AT) { 2712 int pos = token.pos; 2713 nextToken(); 2714 buf.append(annotation(pos, kind)); 2715 } 2716 lastmode = mode; 2717 mode = prevmode; 2718 List<JCAnnotation> annotations = buf.toList(); 2719 2720 return annotations; 2721 } 2722 2723 List<JCAnnotation> typeAnnotationsOpt() { 2724 List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION); 2725 return annotations; 2726 } 2727 2728 /** ModifiersOpt = { Modifier } 2729 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL 2730 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" 2731 * | "@" Annotation 2732 */ 2733 protected JCModifiers modifiersOpt() { 2734 return modifiersOpt(null); 2735 } 2736 protected JCModifiers modifiersOpt(JCModifiers partial) { 2737 long flags; 2738 ListBuffer<JCAnnotation> annotations = new ListBuffer<>(); 2739 int pos; 2740 if (partial == null) { 2741 flags = 0; 2742 pos = token.pos; 2743 } else { 2744 flags = partial.flags; 2745 annotations.appendList(partial.annotations); 2746 pos = partial.pos; 2747 } 2748 if (token.deprecatedFlag()) { 2749 flags |= Flags.DEPRECATED; 2750 } 2751 int lastPos; 2752 loop: 2753 while (true) { 2754 long flag; 2755 switch (token.kind) { 2756 case PRIVATE : flag = Flags.PRIVATE; break; 2757 case PROTECTED : flag = Flags.PROTECTED; break; 2758 case PUBLIC : flag = Flags.PUBLIC; break; 2759 case STATIC : flag = Flags.STATIC; break; 2760 case TRANSIENT : flag = Flags.TRANSIENT; break; 2761 case FINAL : flag = Flags.FINAL; break; 2762 case ABSTRACT : flag = Flags.ABSTRACT; break; 2763 case NATIVE : flag = Flags.NATIVE; break; 2764 case VOLATILE : flag = Flags.VOLATILE; break; 2765 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; 2766 case STRICTFP : flag = Flags.STRICTFP; break; 2767 case MONKEYS_AT : flag = Flags.ANNOTATION; break; 2768 case DEFAULT : checkDefaultMethods(); flag = Flags.DEFAULT; break; 2769 case ERROR : flag = 0; nextToken(); break; 2770 default: break loop; 2771 } 2772 if ((flags & flag) != 0) error(token.pos, "repeated.modifier"); 2773 lastPos = token.pos; 2774 nextToken(); 2775 if (flag == Flags.ANNOTATION) { 2776 if (token.kind != INTERFACE) { 2777 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION); 2778 // if first modifier is an annotation, set pos to annotation's. 2779 if (flags == 0 && annotations.isEmpty()) 2780 pos = ann.pos; 2781 annotations.append(ann); 2782 flag = 0; 2783 } 2784 } 2785 flags |= flag; 2786 } 2787 switch (token.kind) { 2788 case ENUM: flags |= Flags.ENUM; break; 2789 case INTERFACE: flags |= Flags.INTERFACE; break; 2790 default: break; 2791 } 2792 2793 /* A modifiers tree with no modifier tokens or annotations 2794 * has no text position. */ 2795 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty()) 2796 pos = Position.NOPOS; 2797 2798 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); 2799 if (pos != Position.NOPOS) 2800 storeEnd(mods, S.prevToken().endPos); 2801 return mods; 2802 } 2803 2804 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] 2805 * 2806 * @param pos position of "@" token 2807 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION 2808 */ 2809 JCAnnotation annotation(int pos, Tag kind) { 2810 // accept(AT); // AT consumed by caller 2811 if (kind == Tag.TYPE_ANNOTATION) { 2812 checkTypeAnnotations(); 2813 } 2814 JCTree ident = qualident(false); 2815 List<JCExpression> fieldValues = annotationFieldValuesOpt(); 2816 JCAnnotation ann; 2817 if (kind == Tag.ANNOTATION) { 2818 ann = F.at(pos).Annotation(ident, fieldValues); 2819 } else if (kind == Tag.TYPE_ANNOTATION) { 2820 ann = F.at(pos).TypeAnnotation(ident, fieldValues); 2821 } else { 2822 throw new AssertionError("Unhandled annotation kind: " + kind); 2823 } 2824 2825 storeEnd(ann, S.prevToken().endPos); 2826 return ann; 2827 } 2828 2829 List<JCExpression> annotationFieldValuesOpt() { 2830 return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil(); 2831 } 2832 2833 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ 2834 List<JCExpression> annotationFieldValues() { 2835 accept(LPAREN); 2836 ListBuffer<JCExpression> buf = new ListBuffer<>(); 2837 if (token.kind != RPAREN) { 2838 buf.append(annotationFieldValue()); 2839 while (token.kind == COMMA) { 2840 nextToken(); 2841 buf.append(annotationFieldValue()); 2842 } 2843 } 2844 accept(RPAREN); 2845 return buf.toList(); 2846 } 2847 2848 /** AnnotationFieldValue = AnnotationValue 2849 * | Identifier "=" AnnotationValue 2850 */ 2851 JCExpression annotationFieldValue() { 2852 if (LAX_IDENTIFIER.accepts(token.kind)) { 2853 mode = EXPR; 2854 JCExpression t1 = term1(); 2855 if (t1.hasTag(IDENT) && token.kind == EQ) { 2856 int pos = token.pos; 2857 accept(EQ); 2858 JCExpression v = annotationValue(); 2859 return toP(F.at(pos).Assign(t1, v)); 2860 } else { 2861 return t1; 2862 } 2863 } 2864 return annotationValue(); 2865 } 2866 2867 /* AnnotationValue = ConditionalExpression 2868 * | Annotation 2869 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}" 2870 */ 2871 JCExpression annotationValue() { 2872 int pos; 2873 switch (token.kind) { 2874 case MONKEYS_AT: 2875 pos = token.pos; 2876 nextToken(); 2877 return annotation(pos, Tag.ANNOTATION); 2878 case LBRACE: 2879 pos = token.pos; 2880 accept(LBRACE); 2881 ListBuffer<JCExpression> buf = new ListBuffer<>(); 2882 if (token.kind == COMMA) { 2883 nextToken(); 2884 } else if (token.kind != RBRACE) { 2885 buf.append(annotationValue()); 2886 while (token.kind == COMMA) { 2887 nextToken(); 2888 if (token.kind == RBRACE) break; 2889 buf.append(annotationValue()); 2890 } 2891 } 2892 accept(RBRACE); 2893 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList())); 2894 default: 2895 mode = EXPR; 2896 return term1(); 2897 } 2898 } 2899 2900 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator } 2901 */ 2902 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods, 2903 JCExpression type, 2904 T vdefs) 2905 { 2906 return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs); 2907 } 2908 2909 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } 2910 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } 2911 * 2912 * @param reqInit Is an initializer always required? 2913 * @param dc The documentation comment for the variable declarations, or null. 2914 */ 2915 protected <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos, 2916 JCModifiers mods, 2917 JCExpression type, 2918 Name name, 2919 boolean reqInit, 2920 Comment dc, 2921 T vdefs) 2922 { 2923 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); 2924 while (token.kind == COMMA) { 2925 // All but last of multiple declarators subsume a comma 2926 storeEnd((JCTree)vdefs.last(), token.endPos); 2927 nextToken(); 2928 vdefs.append(variableDeclarator(mods, type, reqInit, dc)); 2929 } 2930 return vdefs; 2931 } 2932 2933 /** VariableDeclarator = Ident VariableDeclaratorRest 2934 * ConstantDeclarator = Ident ConstantDeclaratorRest 2935 */ 2936 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) { 2937 return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc); 2938 } 2939 2940 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] 2941 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer 2942 * 2943 * @param reqInit Is an initializer always required? 2944 * @param dc The documentation comment for the variable declarations, or null. 2945 */ 2946 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, 2947 boolean reqInit, Comment dc) { 2948 type = bracketsOpt(type); 2949 JCExpression init = null; 2950 if (token.kind == EQ) { 2951 nextToken(); 2952 init = variableInitializer(); 2953 } 2954 else if (reqInit) syntaxError(token.pos, "expected", EQ); 2955 JCVariableDecl result = 2956 toP(F.at(pos).VarDef(mods, name, type, init)); 2957 attach(result, dc); 2958 return result; 2959 } 2960 2961 /** VariableDeclaratorId = Ident BracketsOpt 2962 */ 2963 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { 2964 return variableDeclaratorId(mods, type, false); 2965 } 2966 //where 2967 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) { 2968 int pos = token.pos; 2969 Name name; 2970 if (lambdaParameter && token.kind == UNDERSCORE) { 2971 log.error(pos, "underscore.as.identifier.in.lambda"); 2972 name = token.name(); 2973 nextToken(); 2974 } else { 2975 if (allowThisIdent) { 2976 JCExpression pn = qualident(false); 2977 if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) { 2978 name = ((JCIdent)pn).name; 2979 } else { 2980 if ((mods.flags & Flags.VARARGS) != 0) { 2981 log.error(token.pos, "varargs.and.receiver"); 2982 } 2983 if (token.kind == LBRACKET) { 2984 log.error(token.pos, "array.and.receiver"); 2985 } 2986 return toP(F.at(pos).ReceiverVarDef(mods, pn, type)); 2987 } 2988 } else { 2989 name = ident(); 2990 } 2991 } 2992 if ((mods.flags & Flags.VARARGS) != 0 && 2993 token.kind == LBRACKET) { 2994 log.error(token.pos, "varargs.and.old.array.syntax"); 2995 } 2996 type = bracketsOpt(type); 2997 return toP(F.at(pos).VarDef(mods, name, type, null)); 2998 } 2999 3000 /** Resources = Resource { ";" Resources } 3001 */ 3002 List<JCTree> resources() { 3003 ListBuffer<JCTree> defs = new ListBuffer<>(); 3004 defs.append(resource()); 3005 while (token.kind == SEMI) { 3006 // All but last of multiple declarators must subsume a semicolon 3007 storeEnd(defs.last(), token.endPos); 3008 int semiColonPos = token.pos; 3009 nextToken(); 3010 if (token.kind == RPAREN) { // Optional trailing semicolon 3011 // after last resource 3012 break; 3013 } 3014 defs.append(resource()); 3015 } 3016 return defs.toList(); 3017 } 3018 3019 /** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression 3020 * | Expression 3021 */ 3022 protected JCTree resource() { 3023 int startPos = token.pos; 3024 if (token.kind == FINAL || token.kind == MONKEYS_AT) { 3025 JCModifiers mods = optFinal(Flags.FINAL); 3026 JCExpression t = parseType(); 3027 return variableDeclaratorRest(token.pos, mods, t, ident(), true, null); 3028 } 3029 JCExpression t = term(EXPR | TYPE); 3030 if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { 3031 JCModifiers mods = toP(F.at(startPos).Modifiers(Flags.FINAL)); 3032 return variableDeclaratorRest(token.pos, mods, t, ident(), true, null); 3033 } else { 3034 checkVariableInTryWithResources(startPos); 3035 if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) { 3036 log.error(t.pos(), "try.with.resources.expr.needs.var"); 3037 } 3038 3039 return t; 3040 } 3041 } 3042 3043 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} 3044 */ 3045 public JCTree.JCCompilationUnit parseCompilationUnit() { 3046 Token firstToken = token; 3047 JCModifiers mods = null; 3048 boolean consumedToplevelDoc = false; 3049 boolean seenImport = false; 3050 boolean seenPackage = false; 3051 ListBuffer<JCTree> defs = new ListBuffer<>(); 3052 if (token.kind == MONKEYS_AT) 3053 mods = modifiersOpt(); 3054 3055 if (token.kind == PACKAGE) { 3056 int packagePos = token.pos; 3057 List<JCAnnotation> annotations = List.nil(); 3058 seenPackage = true; 3059 if (mods != null) { 3060 checkNoMods(mods.flags); 3061 annotations = mods.annotations; 3062 mods = null; 3063 } 3064 nextToken(); 3065 JCExpression pid = qualident(false); 3066 accept(SEMI); 3067 JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid); 3068 attach(pd, firstToken.comment(CommentStyle.JAVADOC)); 3069 consumedToplevelDoc = true; 3070 storeEnd(pd, token.pos); 3071 defs.append(pd); 3072 } 3073 3074 boolean checkForImports = true; 3075 boolean firstTypeDecl = true; 3076 while (token.kind != EOF) { 3077 if (token.pos <= endPosTable.errorEndPos) { 3078 // error recovery 3079 skip(checkForImports, false, false, false); 3080 if (token.kind == EOF) 3081 break; 3082 } 3083 if (checkForImports && mods == null && token.kind == IMPORT) { 3084 seenImport = true; 3085 defs.append(importDeclaration()); 3086 } else { 3087 Comment docComment = token.comment(CommentStyle.JAVADOC); 3088 if (firstTypeDecl && !seenImport && !seenPackage) { 3089 docComment = firstToken.comment(CommentStyle.JAVADOC); 3090 consumedToplevelDoc = true; 3091 } 3092 JCTree def = typeDeclaration(mods, docComment); 3093 if (def instanceof JCExpressionStatement) 3094 def = ((JCExpressionStatement)def).expr; 3095 defs.append(def); 3096 if (def instanceof JCClassDecl) 3097 checkForImports = false; 3098 mods = null; 3099 firstTypeDecl = false; 3100 } 3101 } 3102 JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList()); 3103 if (!consumedToplevelDoc) 3104 attach(toplevel, firstToken.comment(CommentStyle.JAVADOC)); 3105 if (defs.isEmpty()) 3106 storeEnd(toplevel, S.prevToken().endPos); 3107 if (keepDocComments) 3108 toplevel.docComments = docComments; 3109 if (keepLineMap) 3110 toplevel.lineMap = S.getLineMap(); 3111 this.endPosTable.setParser(null); // remove reference to parser 3112 toplevel.endPositions = this.endPosTable; 3113 return toplevel; 3114 } 3115 3116 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" 3117 */ 3118 protected JCTree importDeclaration() { 3119 int pos = token.pos; 3120 nextToken(); 3121 boolean importStatic = false; 3122 if (token.kind == STATIC) { 3123 importStatic = true; 3124 nextToken(); 3125 } 3126 JCExpression pid = toP(F.at(token.pos).Ident(ident())); 3127 do { 3128 int pos1 = token.pos; 3129 accept(DOT); 3130 if (token.kind == STAR) { 3131 pid = to(F.at(pos1).Select(pid, names.asterisk)); 3132 nextToken(); 3133 break; 3134 } else { 3135 pid = toP(F.at(pos1).Select(pid, ident())); 3136 } 3137 } while (token.kind == DOT); 3138 accept(SEMI); 3139 return toP(F.at(pos).Import(pid, importStatic)); 3140 } 3141 3142 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration 3143 * | ";" 3144 */ 3145 JCTree typeDeclaration(JCModifiers mods, Comment docComment) { 3146 int pos = token.pos; 3147 if (mods == null && token.kind == SEMI) { 3148 nextToken(); 3149 return toP(F.at(pos).Skip()); 3150 } else { 3151 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment); 3152 } 3153 } 3154 3155 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt 3156 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) 3157 * @param mods Any modifiers starting the class or interface declaration 3158 * @param dc The documentation comment for the class, or null. 3159 */ 3160 protected JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) { 3161 if (token.kind == CLASS) { 3162 return classDeclaration(mods, dc); 3163 } else if (token.kind == INTERFACE) { 3164 return interfaceDeclaration(mods, dc); 3165 } else if (token.kind == ENUM) { 3166 return enumDeclaration(mods, dc); 3167 } else { 3168 int pos = token.pos; 3169 List<JCTree> errs; 3170 if (LAX_IDENTIFIER.accepts(token.kind)) { 3171 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 3172 setErrorEndPos(token.pos); 3173 } else { 3174 errs = List.<JCTree>of(mods); 3175 } 3176 return toP(F.Exec(syntaxError(pos, errs, "expected3", 3177 CLASS, INTERFACE, ENUM))); 3178 } 3179 } 3180 3181 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] 3182 * [IMPLEMENTS TypeList] ClassBody 3183 * @param mods The modifiers starting the class declaration 3184 * @param dc The documentation comment for the class, or null. 3185 */ 3186 protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) { 3187 int pos = token.pos; 3188 accept(CLASS); 3189 Name name = ident(); 3190 3191 List<JCTypeParameter> typarams = typeParametersOpt(); 3192 3193 JCExpression extending = null; 3194 if (token.kind == EXTENDS) { 3195 nextToken(); 3196 extending = parseType(); 3197 } 3198 List<JCExpression> implementing = List.nil(); 3199 if (token.kind == IMPLEMENTS) { 3200 nextToken(); 3201 implementing = typeList(); 3202 } 3203 List<JCTree> defs = classOrInterfaceBody(name, false); 3204 JCClassDecl result = toP(F.at(pos).ClassDef( 3205 mods, name, typarams, extending, implementing, defs)); 3206 attach(result, dc); 3207 return result; 3208 } 3209 3210 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt 3211 * [EXTENDS TypeList] InterfaceBody 3212 * @param mods The modifiers starting the interface declaration 3213 * @param dc The documentation comment for the interface, or null. 3214 */ 3215 protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) { 3216 int pos = token.pos; 3217 accept(INTERFACE); 3218 Name name = ident(); 3219 3220 List<JCTypeParameter> typarams = typeParametersOpt(); 3221 3222 List<JCExpression> extending = List.nil(); 3223 if (token.kind == EXTENDS) { 3224 nextToken(); 3225 extending = typeList(); 3226 } 3227 List<JCTree> defs = classOrInterfaceBody(name, true); 3228 JCClassDecl result = toP(F.at(pos).ClassDef( 3229 mods, name, typarams, null, extending, defs)); 3230 attach(result, dc); 3231 return result; 3232 } 3233 3234 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody 3235 * @param mods The modifiers starting the enum declaration 3236 * @param dc The documentation comment for the enum, or null. 3237 */ 3238 protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) { 3239 int pos = token.pos; 3240 accept(ENUM); 3241 Name name = ident(); 3242 3243 List<JCExpression> implementing = List.nil(); 3244 if (token.kind == IMPLEMENTS) { 3245 nextToken(); 3246 implementing = typeList(); 3247 } 3248 3249 List<JCTree> defs = enumBody(name); 3250 mods.flags |= Flags.ENUM; 3251 JCClassDecl result = toP(F.at(pos). 3252 ClassDef(mods, name, List.<JCTypeParameter>nil(), 3253 null, implementing, defs)); 3254 attach(result, dc); 3255 return result; 3256 } 3257 3258 /** EnumBody = "{" { EnumeratorDeclarationList } [","] 3259 * [ ";" {ClassBodyDeclaration} ] "}" 3260 */ 3261 List<JCTree> enumBody(Name enumName) { 3262 accept(LBRACE); 3263 ListBuffer<JCTree> defs = new ListBuffer<>(); 3264 if (token.kind == COMMA) { 3265 nextToken(); 3266 } else if (token.kind != RBRACE && token.kind != SEMI) { 3267 defs.append(enumeratorDeclaration(enumName)); 3268 while (token.kind == COMMA) { 3269 nextToken(); 3270 if (token.kind == RBRACE || token.kind == SEMI) break; 3271 defs.append(enumeratorDeclaration(enumName)); 3272 } 3273 if (token.kind != SEMI && token.kind != RBRACE) { 3274 defs.append(syntaxError(token.pos, "expected3", 3275 COMMA, RBRACE, SEMI)); 3276 nextToken(); 3277 } 3278 } 3279 if (token.kind == SEMI) { 3280 nextToken(); 3281 while (token.kind != RBRACE && token.kind != EOF) { 3282 defs.appendList(classOrInterfaceBodyDeclaration(enumName, 3283 false)); 3284 if (token.pos <= endPosTable.errorEndPos) { 3285 // error recovery 3286 skip(false, true, true, false); 3287 } 3288 } 3289 } 3290 accept(RBRACE); 3291 return defs.toList(); 3292 } 3293 3294 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] 3295 */ 3296 JCTree enumeratorDeclaration(Name enumName) { 3297 Comment dc = token.comment(CommentStyle.JAVADOC); 3298 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; 3299 if (token.deprecatedFlag()) { 3300 flags |= Flags.DEPRECATED; 3301 } 3302 int pos = token.pos; 3303 List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION); 3304 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 3305 List<JCExpression> typeArgs = typeArgumentsOpt(); 3306 int identPos = token.pos; 3307 Name name = ident(); 3308 int createPos = token.pos; 3309 List<JCExpression> args = (token.kind == LPAREN) 3310 ? arguments() : List.<JCExpression>nil(); 3311 JCClassDecl body = null; 3312 if (token.kind == LBRACE) { 3313 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM); 3314 List<JCTree> defs = classOrInterfaceBody(names.empty, false); 3315 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); 3316 } 3317 if (args.isEmpty() && body == null) 3318 createPos = identPos; 3319 JCIdent ident = F.at(identPos).Ident(enumName); 3320 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); 3321 if (createPos != identPos) 3322 storeEnd(create, S.prevToken().endPos); 3323 ident = F.at(identPos).Ident(enumName); 3324 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); 3325 attach(result, dc); 3326 return result; 3327 } 3328 3329 /** TypeList = Type {"," Type} 3330 */ 3331 List<JCExpression> typeList() { 3332 ListBuffer<JCExpression> ts = new ListBuffer<>(); 3333 ts.append(parseType()); 3334 while (token.kind == COMMA) { 3335 nextToken(); 3336 ts.append(parseType()); 3337 } 3338 return ts.toList(); 3339 } 3340 3341 /** ClassBody = "{" {ClassBodyDeclaration} "}" 3342 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" 3343 */ 3344 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 3345 accept(LBRACE); 3346 if (token.pos <= endPosTable.errorEndPos) { 3347 // error recovery 3348 skip(false, true, false, false); 3349 if (token.kind == LBRACE) 3350 nextToken(); 3351 } 3352 ListBuffer<JCTree> defs = new ListBuffer<>(); 3353 while (token.kind != RBRACE && token.kind != EOF) { 3354 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 3355 if (token.pos <= endPosTable.errorEndPos) { 3356 // error recovery 3357 skip(false, true, true, false); 3358 } 3359 } 3360 accept(RBRACE); 3361 return defs.toList(); 3362 } 3363 3364 /** ClassBodyDeclaration = 3365 * ";" 3366 * | [STATIC] Block 3367 * | ModifiersOpt 3368 * ( Type Ident 3369 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) 3370 * | VOID Ident VoidMethodDeclaratorRest 3371 * | TypeParameters [Annotations] 3372 * ( Type Ident MethodDeclaratorRest 3373 * | VOID Ident VoidMethodDeclaratorRest 3374 * ) 3375 * | Ident ConstructorDeclaratorRest 3376 * | TypeParameters Ident ConstructorDeclaratorRest 3377 * | ClassOrInterfaceOrEnumDeclaration 3378 * ) 3379 * InterfaceBodyDeclaration = 3380 * ";" 3381 * | ModifiersOpt 3382 * ( Type Ident 3383 * ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest ) 3384 * | VOID Ident MethodDeclaratorRest 3385 * | TypeParameters [Annotations] 3386 * ( Type Ident MethodDeclaratorRest 3387 * | VOID Ident VoidMethodDeclaratorRest 3388 * ) 3389 * | ClassOrInterfaceOrEnumDeclaration 3390 * ) 3391 * 3392 */ 3393 protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { 3394 if (token.kind == SEMI) { 3395 nextToken(); 3396 return List.<JCTree>nil(); 3397 } else { 3398 Comment dc = token.comment(CommentStyle.JAVADOC); 3399 int pos = token.pos; 3400 JCModifiers mods = modifiersOpt(); 3401 if (token.kind == CLASS || 3402 token.kind == INTERFACE || 3403 token.kind == ENUM) { 3404 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 3405 } else if (token.kind == LBRACE && 3406 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && 3407 mods.annotations.isEmpty()) { 3408 if (isInterface) { 3409 error(token.pos, "initializer.not.allowed"); 3410 } 3411 return List.<JCTree>of(block(pos, mods.flags)); 3412 } else { 3413 pos = token.pos; 3414 List<JCTypeParameter> typarams = typeParametersOpt(); 3415 // if there are type parameters but no modifiers, save the start 3416 // position of the method in the modifiers. 3417 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { 3418 mods.pos = pos; 3419 storeEnd(mods, pos); 3420 } 3421 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION); 3422 3423 if (annosAfterParams.nonEmpty()) { 3424 checkAnnotationsAfterTypeParams(annosAfterParams.head.pos); 3425 mods.annotations = mods.annotations.appendList(annosAfterParams); 3426 if (mods.pos == Position.NOPOS) 3427 mods.pos = mods.annotations.head.pos; 3428 } 3429 3430 Token tk = token; 3431 pos = token.pos; 3432 JCExpression type; 3433 boolean isVoid = token.kind == VOID; 3434 if (isVoid) { 3435 type = to(F.at(pos).TypeIdent(TypeTag.VOID)); 3436 nextToken(); 3437 } else { 3438 // method returns types are un-annotated types 3439 type = unannotatedType(); 3440 } 3441 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) { 3442 if (isInterface || tk.name() != className) 3443 error(pos, "invalid.meth.decl.ret.type.req"); 3444 else if (annosAfterParams.nonEmpty()) 3445 illegal(annosAfterParams.head.pos); 3446 return List.of(methodDeclaratorRest( 3447 pos, mods, null, names.init, typarams, 3448 isInterface, true, dc)); 3449 } else { 3450 pos = token.pos; 3451 Name name = ident(); 3452 if (token.kind == LPAREN) { 3453 return List.of(methodDeclaratorRest( 3454 pos, mods, type, name, typarams, 3455 isInterface, isVoid, dc)); 3456 } else if (!isVoid && typarams.isEmpty()) { 3457 List<JCTree> defs = 3458 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, 3459 new ListBuffer<JCTree>()).toList(); 3460 accept(SEMI); 3461 storeEnd(defs.last(), S.prevToken().endPos); 3462 return defs; 3463 } else { 3464 pos = token.pos; 3465 List<JCTree> err = isVoid 3466 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, 3467 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 3468 : null; 3469 return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN)); 3470 } 3471 } 3472 } 3473 } 3474 } 3475 3476 /** MethodDeclaratorRest = 3477 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 3478 * VoidMethodDeclaratorRest = 3479 * FormalParameters [THROWS TypeList] ( MethodBody | ";") 3480 * ConstructorDeclaratorRest = 3481 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody 3482 */ 3483 protected JCTree methodDeclaratorRest(int pos, 3484 JCModifiers mods, 3485 JCExpression type, 3486 Name name, 3487 List<JCTypeParameter> typarams, 3488 boolean isInterface, boolean isVoid, 3489 Comment dc) { 3490 if (isInterface && (mods.flags & Flags.STATIC) != 0) { 3491 checkStaticInterfaceMethods(); 3492 } 3493 JCVariableDecl prevReceiverParam = this.receiverParam; 3494 try { 3495 this.receiverParam = null; 3496 // Parsing formalParameters sets the receiverParam, if present 3497 List<JCVariableDecl> params = formalParameters(); 3498 if (!isVoid) type = bracketsOpt(type); 3499 List<JCExpression> thrown = List.nil(); 3500 if (token.kind == THROWS) { 3501 nextToken(); 3502 thrown = qualidentList(); 3503 } 3504 JCBlock body = null; 3505 JCExpression defaultValue; 3506 if (token.kind == LBRACE) { 3507 body = block(); 3508 defaultValue = null; 3509 } else { 3510 if (token.kind == DEFAULT) { 3511 accept(DEFAULT); 3512 defaultValue = annotationValue(); 3513 } else { 3514 defaultValue = null; 3515 } 3516 accept(SEMI); 3517 if (token.pos <= endPosTable.errorEndPos) { 3518 // error recovery 3519 skip(false, true, false, false); 3520 if (token.kind == LBRACE) { 3521 body = block(); 3522 } 3523 } 3524 } 3525 3526 JCMethodDecl result = 3527 toP(F.at(pos).MethodDef(mods, name, type, typarams, 3528 receiverParam, params, thrown, 3529 body, defaultValue)); 3530 attach(result, dc); 3531 return result; 3532 } finally { 3533 this.receiverParam = prevReceiverParam; 3534 } 3535 } 3536 3537 /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident} 3538 */ 3539 List<JCExpression> qualidentList() { 3540 ListBuffer<JCExpression> ts = new ListBuffer<>(); 3541 3542 List<JCAnnotation> typeAnnos = typeAnnotationsOpt(); 3543 JCExpression qi = qualident(true); 3544 if (!typeAnnos.isEmpty()) { 3545 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false); 3546 ts.append(at); 3547 } else { 3548 ts.append(qi); 3549 } 3550 while (token.kind == COMMA) { 3551 nextToken(); 3552 3553 typeAnnos = typeAnnotationsOpt(); 3554 qi = qualident(true); 3555 if (!typeAnnos.isEmpty()) { 3556 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false); 3557 ts.append(at); 3558 } else { 3559 ts.append(qi); 3560 } 3561 } 3562 return ts.toList(); 3563 } 3564 3565 /** 3566 * {@literal 3567 * TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] 3568 * } 3569 */ 3570 protected List<JCTypeParameter> typeParametersOpt() { 3571 if (token.kind == LT) { 3572 ListBuffer<JCTypeParameter> typarams = new ListBuffer<>(); 3573 nextToken(); 3574 typarams.append(typeParameter()); 3575 while (token.kind == COMMA) { 3576 nextToken(); 3577 typarams.append(typeParameter()); 3578 } 3579 accept(GT); 3580 return typarams.toList(); 3581 } else { 3582 return List.nil(); 3583 } 3584 } 3585 3586 /** 3587 * {@literal 3588 * TypeParameter = [Annotations] TypeVariable [TypeParameterBound] 3589 * TypeParameterBound = EXTENDS Type {"&" Type} 3590 * TypeVariable = Ident 3591 * } 3592 */ 3593 JCTypeParameter typeParameter() { 3594 int pos = token.pos; 3595 List<JCAnnotation> annos = typeAnnotationsOpt(); 3596 Name name = ident(); 3597 ListBuffer<JCExpression> bounds = new ListBuffer<>(); 3598 if (token.kind == EXTENDS) { 3599 nextToken(); 3600 bounds.append(parseType()); 3601 while (token.kind == AMP) { 3602 nextToken(); 3603 bounds.append(parseType()); 3604 } 3605 } 3606 return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos)); 3607 } 3608 3609 /** FormalParameters = "(" [ FormalParameterList ] ")" 3610 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter 3611 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter 3612 */ 3613 List<JCVariableDecl> formalParameters() { 3614 return formalParameters(false); 3615 } 3616 List<JCVariableDecl> formalParameters(boolean lambdaParameters) { 3617 ListBuffer<JCVariableDecl> params = new ListBuffer<>(); 3618 JCVariableDecl lastParam; 3619 accept(LPAREN); 3620 if (token.kind != RPAREN) { 3621 this.allowThisIdent = true; 3622 lastParam = formalParameter(lambdaParameters); 3623 if (lastParam.nameexpr != null) { 3624 this.receiverParam = lastParam; 3625 } else { 3626 params.append(lastParam); 3627 } 3628 this.allowThisIdent = false; 3629 while (token.kind == COMMA) { 3630 if ((lastParam.mods.flags & Flags.VARARGS) != 0) { 3631 error(lastParam, "varargs.must.be.last"); 3632 } 3633 nextToken(); 3634 params.append(lastParam = formalParameter(lambdaParameters)); 3635 } 3636 } 3637 if (token.kind == RPAREN) { 3638 nextToken(); 3639 } else { 3640 setErrorEndPos(token.pos); 3641 reportSyntaxError(S.prevToken().endPos, "expected3", COMMA, RPAREN, LBRACKET); 3642 } 3643 return params.toList(); 3644 } 3645 3646 List<JCVariableDecl> implicitParameters(boolean hasParens) { 3647 if (hasParens) { 3648 accept(LPAREN); 3649 } 3650 ListBuffer<JCVariableDecl> params = new ListBuffer<>(); 3651 if (token.kind != RPAREN && token.kind != ARROW) { 3652 params.append(implicitParameter()); 3653 while (token.kind == COMMA) { 3654 nextToken(); 3655 params.append(implicitParameter()); 3656 } 3657 } 3658 if (hasParens) { 3659 accept(RPAREN); 3660 } 3661 return params.toList(); 3662 } 3663 3664 JCModifiers optFinal(long flags) { 3665 JCModifiers mods = modifiersOpt(); 3666 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); 3667 mods.flags |= flags; 3668 return mods; 3669 } 3670 3671 /** 3672 * Inserts the annotations (and possibly a new array level) 3673 * to the left-most type in an array or nested type. 3674 * 3675 * When parsing a type like {@code @B Outer.Inner @A []}, the 3676 * {@code @A} annotation should target the array itself, while 3677 * {@code @B} targets the nested type {@code Outer}. 3678 * 3679 * Currently the parser parses the annotation first, then 3680 * the array, and then inserts the annotation to the left-most 3681 * nested type. 3682 * 3683 * When {@code createNewLevel} is true, then a new array 3684 * level is inserted as the most inner type, and have the 3685 * annotations target it. This is useful in the case of 3686 * varargs, e.g. {@code String @A [] @B ...}, as the parser 3687 * first parses the type {@code String @A []} then inserts 3688 * a new array level with {@code @B} annotation. 3689 */ 3690 private JCExpression insertAnnotationsToMostInner( 3691 JCExpression type, List<JCAnnotation> annos, 3692 boolean createNewLevel) { 3693 int origEndPos = getEndPos(type); 3694 JCExpression mostInnerType = type; 3695 JCArrayTypeTree mostInnerArrayType = null; 3696 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) { 3697 mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType); 3698 mostInnerType = mostInnerArrayType.elemtype; 3699 } 3700 3701 if (createNewLevel) { 3702 mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType)); 3703 } 3704 3705 JCExpression mostInnerTypeToReturn = mostInnerType; 3706 if (annos.nonEmpty()) { 3707 JCExpression lastToModify = mostInnerType; 3708 3709 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) || 3710 TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) { 3711 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) { 3712 lastToModify = mostInnerType; 3713 mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression(); 3714 } 3715 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) { 3716 lastToModify = mostInnerType; 3717 mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz; 3718 } 3719 } 3720 3721 mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType); 3722 3723 if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) { 3724 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType; 3725 } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) { 3726 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType; 3727 } else { 3728 // We never saw a SELECT or TYPEAPPLY, return the annotated type. 3729 mostInnerTypeToReturn = mostInnerType; 3730 } 3731 } 3732 3733 if (mostInnerArrayType == null) { 3734 return mostInnerTypeToReturn; 3735 } else { 3736 mostInnerArrayType.elemtype = mostInnerTypeToReturn; 3737 storeEnd(type, origEndPos); 3738 return type; 3739 } 3740 } 3741 3742 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId 3743 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter 3744 */ 3745 protected JCVariableDecl formalParameter() { 3746 return formalParameter(false); 3747 } 3748 protected JCVariableDecl formalParameter(boolean lambdaParameter) { 3749 JCModifiers mods = optFinal(Flags.PARAMETER); 3750 // need to distinguish between vararg annos and array annos 3751 // look at typeAnnotationsPushedBack comment 3752 this.permitTypeAnnotationsPushBack = true; 3753 JCExpression type = parseType(); 3754 this.permitTypeAnnotationsPushBack = false; 3755 3756 if (token.kind == ELLIPSIS) { 3757 List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack; 3758 typeAnnotationsPushedBack = List.nil(); 3759 mods.flags |= Flags.VARARGS; 3760 // insert var arg type annotations 3761 type = insertAnnotationsToMostInner(type, varargsAnnos, true); 3762 nextToken(); 3763 } else { 3764 // if not a var arg, then typeAnnotationsPushedBack should be null 3765 if (typeAnnotationsPushedBack.nonEmpty()) { 3766 reportSyntaxError(typeAnnotationsPushedBack.head.pos, 3767 "illegal.start.of.type"); 3768 } 3769 typeAnnotationsPushedBack = List.nil(); 3770 } 3771 return variableDeclaratorId(mods, type, lambdaParameter); 3772 } 3773 3774 protected JCVariableDecl implicitParameter() { 3775 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); 3776 return variableDeclaratorId(mods, null, true); 3777 } 3778 3779/* ---------- auxiliary methods -------------- */ 3780 3781 void error(int pos, String key, Object ... args) { 3782 log.error(DiagnosticFlag.SYNTAX, pos, key, args); 3783 } 3784 3785 void error(DiagnosticPosition pos, String key, Object ... args) { 3786 log.error(DiagnosticFlag.SYNTAX, pos, key, args); 3787 } 3788 3789 void warning(int pos, String key, Object ... args) { 3790 log.warning(pos, key, args); 3791 } 3792 3793 /** Check that given tree is a legal expression statement. 3794 */ 3795 protected JCExpression checkExprStat(JCExpression t) { 3796 if (!TreeInfo.isExpressionStatement(t)) { 3797 JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t)); 3798 error(ret, "not.stmt"); 3799 return ret; 3800 } else { 3801 return t; 3802 } 3803 } 3804 3805 /** Return precedence of operator represented by token, 3806 * -1 if token is not a binary operator. @see TreeInfo.opPrec 3807 */ 3808 static int prec(TokenKind token) { 3809 JCTree.Tag oc = optag(token); 3810 return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1; 3811 } 3812 3813 /** 3814 * Return the lesser of two positions, making allowance for either one 3815 * being unset. 3816 */ 3817 static int earlier(int pos1, int pos2) { 3818 if (pos1 == Position.NOPOS) 3819 return pos2; 3820 if (pos2 == Position.NOPOS) 3821 return pos1; 3822 return (pos1 < pos2 ? pos1 : pos2); 3823 } 3824 3825 /** Return operation tag of binary operator represented by token, 3826 * No_TAG if token is not a binary operator. 3827 */ 3828 static JCTree.Tag optag(TokenKind token) { 3829 switch (token) { 3830 case BARBAR: 3831 return OR; 3832 case AMPAMP: 3833 return AND; 3834 case BAR: 3835 return BITOR; 3836 case BAREQ: 3837 return BITOR_ASG; 3838 case CARET: 3839 return BITXOR; 3840 case CARETEQ: 3841 return BITXOR_ASG; 3842 case AMP: 3843 return BITAND; 3844 case AMPEQ: 3845 return BITAND_ASG; 3846 case EQEQ: 3847 return JCTree.Tag.EQ; 3848 case BANGEQ: 3849 return NE; 3850 case LT: 3851 return JCTree.Tag.LT; 3852 case GT: 3853 return JCTree.Tag.GT; 3854 case LTEQ: 3855 return LE; 3856 case GTEQ: 3857 return GE; 3858 case LTLT: 3859 return SL; 3860 case LTLTEQ: 3861 return SL_ASG; 3862 case GTGT: 3863 return SR; 3864 case GTGTEQ: 3865 return SR_ASG; 3866 case GTGTGT: 3867 return USR; 3868 case GTGTGTEQ: 3869 return USR_ASG; 3870 case PLUS: 3871 return JCTree.Tag.PLUS; 3872 case PLUSEQ: 3873 return PLUS_ASG; 3874 case SUB: 3875 return MINUS; 3876 case SUBEQ: 3877 return MINUS_ASG; 3878 case STAR: 3879 return MUL; 3880 case STAREQ: 3881 return MUL_ASG; 3882 case SLASH: 3883 return DIV; 3884 case SLASHEQ: 3885 return DIV_ASG; 3886 case PERCENT: 3887 return MOD; 3888 case PERCENTEQ: 3889 return MOD_ASG; 3890 case INSTANCEOF: 3891 return TYPETEST; 3892 default: 3893 return NO_TAG; 3894 } 3895 } 3896 3897 /** Return operation tag of unary operator represented by token, 3898 * No_TAG if token is not a binary operator. 3899 */ 3900 static JCTree.Tag unoptag(TokenKind token) { 3901 switch (token) { 3902 case PLUS: 3903 return POS; 3904 case SUB: 3905 return NEG; 3906 case BANG: 3907 return NOT; 3908 case TILDE: 3909 return COMPL; 3910 case PLUSPLUS: 3911 return PREINC; 3912 case SUBSUB: 3913 return PREDEC; 3914 default: 3915 return NO_TAG; 3916 } 3917 } 3918 3919 /** Return type tag of basic type represented by token, 3920 * NONE if token is not a basic type identifier. 3921 */ 3922 static TypeTag typetag(TokenKind token) { 3923 switch (token) { 3924 case BYTE: 3925 return TypeTag.BYTE; 3926 case CHAR: 3927 return TypeTag.CHAR; 3928 case SHORT: 3929 return TypeTag.SHORT; 3930 case INT: 3931 return TypeTag.INT; 3932 case LONG: 3933 return TypeTag.LONG; 3934 case FLOAT: 3935 return TypeTag.FLOAT; 3936 case DOUBLE: 3937 return TypeTag.DOUBLE; 3938 case BOOLEAN: 3939 return TypeTag.BOOLEAN; 3940 default: 3941 return TypeTag.NONE; 3942 } 3943 } 3944 3945 void checkDiamond() { 3946 if (!allowDiamond) { 3947 error(token.pos, "diamond.not.supported.in.source", source.name); 3948 allowDiamond = true; 3949 } 3950 } 3951 void checkMulticatch() { 3952 if (!allowMulticatch) { 3953 error(token.pos, "multicatch.not.supported.in.source", source.name); 3954 allowMulticatch = true; 3955 } 3956 } 3957 void checkTryWithResources() { 3958 if (!allowTWR) { 3959 error(token.pos, "try.with.resources.not.supported.in.source", source.name); 3960 allowTWR = true; 3961 } 3962 } 3963 void checkVariableInTryWithResources(int startPos) { 3964 if (!allowEffectivelyFinalVariablesInTWR) { 3965 error(startPos, "var.in.try.with.resources.not.supported.in.source", source.name); 3966 allowEffectivelyFinalVariablesInTWR = true; 3967 } 3968 } 3969 void checkLambda() { 3970 if (!allowLambda) { 3971 log.error(token.pos, "lambda.not.supported.in.source", source.name); 3972 allowLambda = true; 3973 } 3974 } 3975 void checkMethodReferences() { 3976 if (!allowMethodReferences) { 3977 log.error(token.pos, "method.references.not.supported.in.source", source.name); 3978 allowMethodReferences = true; 3979 } 3980 } 3981 void checkDefaultMethods() { 3982 if (!allowDefaultMethods) { 3983 log.error(token.pos, "default.methods.not.supported.in.source", source.name); 3984 allowDefaultMethods = true; 3985 } 3986 } 3987 void checkIntersectionTypesInCast() { 3988 if (!allowIntersectionTypesInCast) { 3989 log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name); 3990 allowIntersectionTypesInCast = true; 3991 } 3992 } 3993 void checkStaticInterfaceMethods() { 3994 if (!allowStaticInterfaceMethods) { 3995 log.error(token.pos, "static.intf.methods.not.supported.in.source", source.name); 3996 allowStaticInterfaceMethods = true; 3997 } 3998 } 3999 void checkTypeAnnotations() { 4000 if (!allowTypeAnnotations) { 4001 log.error(token.pos, "type.annotations.not.supported.in.source", source.name); 4002 allowTypeAnnotations = true; 4003 } 4004 } 4005 protected void checkAnnotationsAfterTypeParams(int pos) { 4006 if (!allowAnnotationsAfterTypeParams) { 4007 log.error(pos, "annotations.after.type.params.not.supported.in.source", source.name); 4008 allowAnnotationsAfterTypeParams = true; 4009 } 4010 } 4011 4012 /* 4013 * a functional source tree and end position mappings 4014 */ 4015 protected static class SimpleEndPosTable extends AbstractEndPosTable { 4016 4017 private final IntHashTable endPosMap; 4018 4019 SimpleEndPosTable(JavacParser parser) { 4020 super(parser); 4021 endPosMap = new IntHashTable(); 4022 } 4023 4024 public void storeEnd(JCTree tree, int endpos) { 4025 endPosMap.putAtIndex(tree, errorEndPos > endpos ? errorEndPos : endpos, 4026 endPosMap.lookup(tree)); 4027 } 4028 4029 protected <T extends JCTree> T to(T t) { 4030 storeEnd(t, parser.token.endPos); 4031 return t; 4032 } 4033 4034 protected <T extends JCTree> T toP(T t) { 4035 storeEnd(t, parser.S.prevToken().endPos); 4036 return t; 4037 } 4038 4039 public int getEndPos(JCTree tree) { 4040 int value = endPosMap.getFromIndex(endPosMap.lookup(tree)); 4041 // As long as Position.NOPOS==-1, this just returns value. 4042 return (value == -1) ? Position.NOPOS : value; 4043 } 4044 4045 public int replaceTree(JCTree oldTree, JCTree newTree) { 4046 int pos = endPosMap.remove(oldTree); 4047 if (pos != -1) { 4048 storeEnd(newTree, pos); 4049 return pos; 4050 } 4051 return Position.NOPOS; 4052 } 4053 } 4054 4055 /* 4056 * a default skeletal implementation without any mapping overhead. 4057 */ 4058 protected static class EmptyEndPosTable extends AbstractEndPosTable { 4059 4060 EmptyEndPosTable(JavacParser parser) { 4061 super(parser); 4062 } 4063 4064 public void storeEnd(JCTree tree, int endpos) { /* empty */ } 4065 4066 protected <T extends JCTree> T to(T t) { 4067 return t; 4068 } 4069 4070 protected <T extends JCTree> T toP(T t) { 4071 return t; 4072 } 4073 4074 public int getEndPos(JCTree tree) { 4075 return Position.NOPOS; 4076 } 4077 4078 public int replaceTree(JCTree oldTree, JCTree newTree) { 4079 return Position.NOPOS; 4080 } 4081 4082 } 4083 4084 protected static abstract class AbstractEndPosTable implements EndPosTable { 4085 /** 4086 * The current parser. 4087 */ 4088 protected JavacParser parser; 4089 4090 /** 4091 * Store the last error position. 4092 */ 4093 public int errorEndPos = Position.NOPOS; 4094 4095 public AbstractEndPosTable(JavacParser parser) { 4096 this.parser = parser; 4097 } 4098 4099 /** 4100 * Store current token's ending position for a tree, the value of which 4101 * will be the greater of last error position and the ending position of 4102 * the current token. 4103 * @param t The tree. 4104 */ 4105 protected abstract <T extends JCTree> T to(T t); 4106 4107 /** 4108 * Store current token's ending position for a tree, the value of which 4109 * will be the greater of last error position and the ending position of 4110 * the previous token. 4111 * @param t The tree. 4112 */ 4113 protected abstract <T extends JCTree> T toP(T t); 4114 4115 /** 4116 * Set the error position during the parsing phases, the value of which 4117 * will be set only if it is greater than the last stored error position. 4118 * @param errPos The error position 4119 */ 4120 public void setErrorEndPos(int errPos) { 4121 if (errPos > errorEndPos) { 4122 errorEndPos = errPos; 4123 } 4124 } 4125 4126 public void setParser(JavacParser parser) { 4127 this.parser = parser; 4128 } 4129 } 4130} 4131