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