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