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