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