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