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