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