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