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