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