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