src/share/classes/com/sun/tools/javac/parser/JavacParser.java

Thu, 24 May 2018 18:02:46 +0800

author
aoqi
date
Thu, 24 May 2018 18:02:46 +0800
changeset 3446
e468915bad3a
parent 3315
6f0746b6de9f
parent 3295
859dc787b52b
permissions
-rw-r--r--

Merge

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

mercurial