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