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