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