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