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