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