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