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