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