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