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