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