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