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