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