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

Tue, 04 Mar 2008 15:45:20 +0000

author
mcimadamore
date
Tue, 04 Mar 2008 15:45:20 +0000
changeset 8
38bd6375f37d
parent 1
9a66ca7c79fa
child 26
25338c55e458
permissions
-rw-r--r--

6663588: Compiler goes into infinite loop for Cyclic Inheritance test case
Summary: interplay between cyclic inheritance and tvar bounds hangs javac
Reviewed-by: jjg

duke@1 1 /*
duke@1 2 * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
duke@1 7 * published by the Free Software Foundation. Sun designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
duke@1 9 * by Sun in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
duke@1 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@1 22 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@1 23 * have any questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.javac.parser;
duke@1 27
duke@1 28 import java.util.*;
duke@1 29
duke@1 30 import com.sun.tools.javac.tree.*;
duke@1 31 import com.sun.tools.javac.code.*;
duke@1 32 import com.sun.tools.javac.util.*;
duke@1 33 import com.sun.tools.javac.util.List;
duke@1 34 import static com.sun.tools.javac.util.ListBuffer.lb;
duke@1 35
duke@1 36 import com.sun.tools.javac.tree.JCTree.*;
duke@1 37
duke@1 38 import static com.sun.tools.javac.parser.Token.*;
duke@1 39
duke@1 40 /** The parser maps a token sequence into an abstract syntax
duke@1 41 * tree. It operates by recursive descent, with code derived
duke@1 42 * systematically from an LL(1) grammar. For efficiency reasons, an
duke@1 43 * operator precedence scheme is used for parsing binary operation
duke@1 44 * expressions.
duke@1 45 *
duke@1 46 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
duke@1 47 * you write code that depends on this, you do so at your own risk.
duke@1 48 * This code and its internal interfaces are subject to change or
duke@1 49 * deletion without notice.</b>
duke@1 50 */
duke@1 51 public class Parser {
duke@1 52
duke@1 53 /** A factory for creating parsers. */
duke@1 54 public static class Factory {
duke@1 55 /** The context key for the parser factory. */
duke@1 56 protected static final Context.Key<Parser.Factory> parserFactoryKey =
duke@1 57 new Context.Key<Parser.Factory>();
duke@1 58
duke@1 59 /** Get the Factory instance for this context. */
duke@1 60 public static Factory instance(Context context) {
duke@1 61 Factory instance = context.get(parserFactoryKey);
duke@1 62 if (instance == null)
duke@1 63 instance = new Factory(context);
duke@1 64 return instance;
duke@1 65 }
duke@1 66
duke@1 67 final TreeMaker F;
duke@1 68 final Log log;
duke@1 69 final Keywords keywords;
duke@1 70 final Source source;
duke@1 71 final Name.Table names;
duke@1 72 final Options options;
duke@1 73
duke@1 74 /** Create a new parser factory. */
duke@1 75 protected Factory(Context context) {
duke@1 76 context.put(parserFactoryKey, this);
duke@1 77 this.F = TreeMaker.instance(context);
duke@1 78 this.log = Log.instance(context);
duke@1 79 this.names = Name.Table.instance(context);
duke@1 80 this.keywords = Keywords.instance(context);
duke@1 81 this.source = Source.instance(context);
duke@1 82 this.options = Options.instance(context);
duke@1 83 }
duke@1 84
duke@1 85 /**
duke@1 86 * Create a new Parser.
duke@1 87 * @param S Lexer for getting tokens while parsing
duke@1 88 * @param keepDocComments true if javadoc comments should be kept
duke@1 89 * @param genEndPos true if end positions should be generated
duke@1 90 */
duke@1 91 public Parser newParser(Lexer S, boolean keepDocComments, boolean genEndPos) {
duke@1 92 if (!genEndPos)
duke@1 93 return new Parser(this, S, keepDocComments);
duke@1 94 else
duke@1 95 return new EndPosParser(this, S, keepDocComments);
duke@1 96 }
duke@1 97 }
duke@1 98
duke@1 99 /** The number of precedence levels of infix operators.
duke@1 100 */
duke@1 101 private static final int infixPrecedenceLevels = 10;
duke@1 102
duke@1 103 /** The scanner used for lexical analysis.
duke@1 104 */
duke@1 105 private Lexer S;
duke@1 106
duke@1 107 /** The factory to be used for abstract syntax tree construction.
duke@1 108 */
duke@1 109 protected TreeMaker F;
duke@1 110
duke@1 111 /** The log to be used for error diagnostics.
duke@1 112 */
duke@1 113 private Log log;
duke@1 114
duke@1 115 /** The keyword table. */
duke@1 116 private Keywords keywords;
duke@1 117
duke@1 118 /** The Source language setting. */
duke@1 119 private Source source;
duke@1 120
duke@1 121 /** The name table. */
duke@1 122 private Name.Table names;
duke@1 123
duke@1 124 /** Construct a parser from a given scanner, tree factory and log.
duke@1 125 */
duke@1 126 protected Parser(Factory fac,
duke@1 127 Lexer S,
duke@1 128 boolean keepDocComments) {
duke@1 129 this.S = S;
duke@1 130 S.nextToken(); // prime the pump
duke@1 131 this.F = fac.F;
duke@1 132 this.log = fac.log;
duke@1 133 this.names = fac.names;
duke@1 134 this.keywords = fac.keywords;
duke@1 135 this.source = fac.source;
duke@1 136 Options options = fac.options;
duke@1 137 this.allowGenerics = source.allowGenerics();
duke@1 138 this.allowVarargs = source.allowVarargs();
duke@1 139 this.allowAsserts = source.allowAsserts();
duke@1 140 this.allowEnums = source.allowEnums();
duke@1 141 this.allowForeach = source.allowForeach();
duke@1 142 this.allowStaticImport = source.allowStaticImport();
duke@1 143 this.allowAnnotations = source.allowAnnotations();
duke@1 144 this.keepDocComments = keepDocComments;
duke@1 145 if (keepDocComments) docComments = new HashMap<JCTree,String>();
duke@1 146 this.errorTree = F.Erroneous();
duke@1 147 }
duke@1 148
duke@1 149 /** Switch: Should generics be recognized?
duke@1 150 */
duke@1 151 boolean allowGenerics;
duke@1 152
duke@1 153 /** Switch: Should varargs be recognized?
duke@1 154 */
duke@1 155 boolean allowVarargs;
duke@1 156
duke@1 157 /** Switch: should we recognize assert statements, or just give a warning?
duke@1 158 */
duke@1 159 boolean allowAsserts;
duke@1 160
duke@1 161 /** Switch: should we recognize enums, or just give a warning?
duke@1 162 */
duke@1 163 boolean allowEnums;
duke@1 164
duke@1 165 /** Switch: should we recognize foreach?
duke@1 166 */
duke@1 167 boolean allowForeach;
duke@1 168
duke@1 169 /** Switch: should we recognize foreach?
duke@1 170 */
duke@1 171 boolean allowStaticImport;
duke@1 172
duke@1 173 /** Switch: should we recognize annotations?
duke@1 174 */
duke@1 175 boolean allowAnnotations;
duke@1 176
duke@1 177 /** Switch: should we keep docComments?
duke@1 178 */
duke@1 179 boolean keepDocComments;
duke@1 180
duke@1 181 /** When terms are parsed, the mode determines which is expected:
duke@1 182 * mode = EXPR : an expression
duke@1 183 * mode = TYPE : a type
duke@1 184 * mode = NOPARAMS : no parameters allowed for type
duke@1 185 * mode = TYPEARG : type argument
duke@1 186 */
duke@1 187 static final int EXPR = 1;
duke@1 188 static final int TYPE = 2;
duke@1 189 static final int NOPARAMS = 4;
duke@1 190 static final int TYPEARG = 8;
duke@1 191
duke@1 192 /** The current mode.
duke@1 193 */
duke@1 194 private int mode = 0;
duke@1 195
duke@1 196 /** The mode of the term that was parsed last.
duke@1 197 */
duke@1 198 private int lastmode = 0;
duke@1 199
duke@1 200 /* ---------- error recovery -------------- */
duke@1 201
duke@1 202 private JCErroneous errorTree;
duke@1 203
duke@1 204 /** Skip forward until a suitable stop token is found.
duke@1 205 */
duke@1 206 private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
duke@1 207 while (true) {
duke@1 208 switch (S.token()) {
duke@1 209 case SEMI:
duke@1 210 S.nextToken();
duke@1 211 return;
duke@1 212 case PUBLIC:
duke@1 213 case FINAL:
duke@1 214 case ABSTRACT:
duke@1 215 case MONKEYS_AT:
duke@1 216 case EOF:
duke@1 217 case CLASS:
duke@1 218 case INTERFACE:
duke@1 219 case ENUM:
duke@1 220 return;
duke@1 221 case IMPORT:
duke@1 222 if (stopAtImport)
duke@1 223 return;
duke@1 224 break;
duke@1 225 case LBRACE:
duke@1 226 case RBRACE:
duke@1 227 case PRIVATE:
duke@1 228 case PROTECTED:
duke@1 229 case STATIC:
duke@1 230 case TRANSIENT:
duke@1 231 case NATIVE:
duke@1 232 case VOLATILE:
duke@1 233 case SYNCHRONIZED:
duke@1 234 case STRICTFP:
duke@1 235 case LT:
duke@1 236 case BYTE:
duke@1 237 case SHORT:
duke@1 238 case CHAR:
duke@1 239 case INT:
duke@1 240 case LONG:
duke@1 241 case FLOAT:
duke@1 242 case DOUBLE:
duke@1 243 case BOOLEAN:
duke@1 244 case VOID:
duke@1 245 if (stopAtMemberDecl)
duke@1 246 return;
duke@1 247 break;
duke@1 248 case IDENTIFIER:
duke@1 249 if (stopAtIdentifier)
duke@1 250 return;
duke@1 251 break;
duke@1 252 case CASE:
duke@1 253 case DEFAULT:
duke@1 254 case IF:
duke@1 255 case FOR:
duke@1 256 case WHILE:
duke@1 257 case DO:
duke@1 258 case TRY:
duke@1 259 case SWITCH:
duke@1 260 case RETURN:
duke@1 261 case THROW:
duke@1 262 case BREAK:
duke@1 263 case CONTINUE:
duke@1 264 case ELSE:
duke@1 265 case FINALLY:
duke@1 266 case CATCH:
duke@1 267 if (stopAtStatement)
duke@1 268 return;
duke@1 269 break;
duke@1 270 }
duke@1 271 S.nextToken();
duke@1 272 }
duke@1 273 }
duke@1 274
duke@1 275 private JCErroneous syntaxError(int pos, String key, Object... arg) {
duke@1 276 return syntaxError(pos, null, key, arg);
duke@1 277 }
duke@1 278
duke@1 279 private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Object... arg) {
duke@1 280 setErrorEndPos(pos);
duke@1 281 reportSyntaxError(pos, key, arg);
duke@1 282 return toP(F.at(pos).Erroneous(errs));
duke@1 283 }
duke@1 284
duke@1 285 private int errorPos = Position.NOPOS;
duke@1 286 /**
duke@1 287 * Report a syntax error at given position using the given
duke@1 288 * argument unless one was already reported at the same position.
duke@1 289 */
duke@1 290 private void reportSyntaxError(int pos, String key, Object... arg) {
duke@1 291 if (pos > S.errPos() || pos == Position.NOPOS) {
duke@1 292 if (S.token() == EOF)
duke@1 293 log.error(pos, "premature.eof");
duke@1 294 else
duke@1 295 log.error(pos, key, arg);
duke@1 296 }
duke@1 297 S.errPos(pos);
duke@1 298 if (S.pos() == errorPos)
duke@1 299 S.nextToken(); // guarantee progress
duke@1 300 errorPos = S.pos();
duke@1 301 }
duke@1 302
duke@1 303
duke@1 304 /** Generate a syntax error at current position unless one was already
duke@1 305 * reported at the same position.
duke@1 306 */
duke@1 307 private JCErroneous syntaxError(String key) {
duke@1 308 return syntaxError(S.pos(), key);
duke@1 309 }
duke@1 310
duke@1 311 /** Generate a syntax error at current position unless one was
duke@1 312 * already reported at the same position.
duke@1 313 */
duke@1 314 private JCErroneous syntaxError(String key, String arg) {
duke@1 315 return syntaxError(S.pos(), key, arg);
duke@1 316 }
duke@1 317
duke@1 318 /** If next input token matches given token, skip it, otherwise report
duke@1 319 * an error.
duke@1 320 */
duke@1 321 public void accept(Token token) {
duke@1 322 if (S.token() == token) {
duke@1 323 S.nextToken();
duke@1 324 } else {
duke@1 325 setErrorEndPos(S.pos());
duke@1 326 reportSyntaxError(S.prevEndPos(), "expected", keywords.token2string(token));
duke@1 327 }
duke@1 328 }
duke@1 329
duke@1 330 /** Report an illegal start of expression/type error at given position.
duke@1 331 */
duke@1 332 JCExpression illegal(int pos) {
duke@1 333 setErrorEndPos(S.pos());
duke@1 334 if ((mode & EXPR) != 0)
duke@1 335 return syntaxError(pos, "illegal.start.of.expr");
duke@1 336 else
duke@1 337 return syntaxError(pos, "illegal.start.of.type");
duke@1 338
duke@1 339 }
duke@1 340
duke@1 341 /** Report an illegal start of expression/type error at current position.
duke@1 342 */
duke@1 343 JCExpression illegal() {
duke@1 344 return illegal(S.pos());
duke@1 345 }
duke@1 346
duke@1 347 /** Diagnose a modifier flag from the set, if any. */
duke@1 348 void checkNoMods(long mods) {
duke@1 349 if (mods != 0) {
duke@1 350 long lowestMod = mods & -mods;
duke@1 351 log.error(S.pos(), "mod.not.allowed.here",
duke@1 352 Flags.toString(lowestMod).trim());
duke@1 353 }
duke@1 354 }
duke@1 355
duke@1 356 /* ---------- doc comments --------- */
duke@1 357
duke@1 358 /** A hashtable to store all documentation comments
duke@1 359 * indexed by the tree nodes they refer to.
duke@1 360 * defined only if option flag keepDocComment is set.
duke@1 361 */
duke@1 362 Map<JCTree, String> docComments;
duke@1 363
duke@1 364 /** Make an entry into docComments hashtable,
duke@1 365 * provided flag keepDocComments is set and given doc comment is non-null.
duke@1 366 * @param tree The tree to be used as index in the hashtable
duke@1 367 * @param dc The doc comment to associate with the tree, or null.
duke@1 368 */
duke@1 369 void attach(JCTree tree, String dc) {
duke@1 370 if (keepDocComments && dc != null) {
duke@1 371 // System.out.println("doc comment = ");System.out.println(dc);//DEBUG
duke@1 372 docComments.put(tree, dc);
duke@1 373 }
duke@1 374 }
duke@1 375
duke@1 376 /* -------- source positions ------- */
duke@1 377
duke@1 378 private int errorEndPos = -1;
duke@1 379
duke@1 380 private void setErrorEndPos(int errPos) {
duke@1 381 if (errPos > errorEndPos)
duke@1 382 errorEndPos = errPos;
duke@1 383 }
duke@1 384
duke@1 385 protected int getErrorEndPos() {
duke@1 386 return errorEndPos;
duke@1 387 }
duke@1 388
duke@1 389 /**
duke@1 390 * Store ending position for a tree.
duke@1 391 * @param tree The tree.
duke@1 392 * @param endpos The ending position to associate with the tree.
duke@1 393 */
duke@1 394 protected void storeEnd(JCTree tree, int endpos) {}
duke@1 395
duke@1 396 /**
duke@1 397 * Store ending position for a tree. The ending position should
duke@1 398 * be the ending position of the current token.
duke@1 399 * @param t The tree.
duke@1 400 */
duke@1 401 protected <T extends JCTree> T to(T t) { return t; }
duke@1 402
duke@1 403 /**
duke@1 404 * Store ending position for a tree. The ending position should
duke@1 405 * be greater of the ending position of the previous token and errorEndPos.
duke@1 406 * @param t The tree.
duke@1 407 */
duke@1 408 protected <T extends JCTree> T toP(T t) { return t; }
duke@1 409
duke@1 410 /** Get the start position for a tree node. The start position is
duke@1 411 * defined to be the position of the first character of the first
duke@1 412 * token of the node's source text.
duke@1 413 * @param tree The tree node
duke@1 414 */
duke@1 415 public int getStartPos(JCTree tree) {
duke@1 416 return TreeInfo.getStartPos(tree);
duke@1 417 }
duke@1 418
duke@1 419 /**
duke@1 420 * Get the end position for a tree node. The end position is
duke@1 421 * defined to be the position of the last character of the last
duke@1 422 * token of the node's source text. Returns Position.NOPOS if end
duke@1 423 * positions are not generated or the position is otherwise not
duke@1 424 * found.
duke@1 425 * @param tree The tree node
duke@1 426 */
duke@1 427 public int getEndPos(JCTree tree) {
duke@1 428 return Position.NOPOS;
duke@1 429 }
duke@1 430
duke@1 431
duke@1 432
duke@1 433 /* ---------- parsing -------------- */
duke@1 434
duke@1 435 /**
duke@1 436 * Ident = IDENTIFIER
duke@1 437 */
duke@1 438 Name ident() {
duke@1 439 if (S.token() == IDENTIFIER) {
duke@1 440 Name name = S.name();
duke@1 441 S.nextToken();
duke@1 442 return name;
duke@1 443 } else if (S.token() == ASSERT) {
duke@1 444 if (allowAsserts) {
duke@1 445 log.error(S.pos(), "assert.as.identifier");
duke@1 446 S.nextToken();
duke@1 447 return names.error;
duke@1 448 } else {
duke@1 449 log.warning(S.pos(), "assert.as.identifier");
duke@1 450 Name name = S.name();
duke@1 451 S.nextToken();
duke@1 452 return name;
duke@1 453 }
duke@1 454 } else if (S.token() == ENUM) {
duke@1 455 if (allowEnums) {
duke@1 456 log.error(S.pos(), "enum.as.identifier");
duke@1 457 S.nextToken();
duke@1 458 return names.error;
duke@1 459 } else {
duke@1 460 log.warning(S.pos(), "enum.as.identifier");
duke@1 461 Name name = S.name();
duke@1 462 S.nextToken();
duke@1 463 return name;
duke@1 464 }
duke@1 465 } else {
duke@1 466 accept(IDENTIFIER);
duke@1 467 return names.error;
duke@1 468 }
duke@1 469 }
duke@1 470
duke@1 471 /**
duke@1 472 * Qualident = Ident { DOT Ident }
duke@1 473 */
duke@1 474 public JCExpression qualident() {
duke@1 475 JCExpression t = toP(F.at(S.pos()).Ident(ident()));
duke@1 476 while (S.token() == DOT) {
duke@1 477 int pos = S.pos();
duke@1 478 S.nextToken();
duke@1 479 t = toP(F.at(pos).Select(t, ident()));
duke@1 480 }
duke@1 481 return t;
duke@1 482 }
duke@1 483
duke@1 484 /**
duke@1 485 * Literal =
duke@1 486 * INTLITERAL
duke@1 487 * | LONGLITERAL
duke@1 488 * | FLOATLITERAL
duke@1 489 * | DOUBLELITERAL
duke@1 490 * | CHARLITERAL
duke@1 491 * | STRINGLITERAL
duke@1 492 * | TRUE
duke@1 493 * | FALSE
duke@1 494 * | NULL
duke@1 495 */
duke@1 496 JCExpression literal(Name prefix) {
duke@1 497 int pos = S.pos();
duke@1 498 JCExpression t = errorTree;
duke@1 499 switch (S.token()) {
duke@1 500 case INTLITERAL:
duke@1 501 try {
duke@1 502 t = F.at(pos).Literal(
duke@1 503 TypeTags.INT,
duke@1 504 Convert.string2int(strval(prefix), S.radix()));
duke@1 505 } catch (NumberFormatException ex) {
duke@1 506 log.error(S.pos(), "int.number.too.large", strval(prefix));
duke@1 507 }
duke@1 508 break;
duke@1 509 case LONGLITERAL:
duke@1 510 try {
duke@1 511 t = F.at(pos).Literal(
duke@1 512 TypeTags.LONG,
duke@1 513 new Long(Convert.string2long(strval(prefix), S.radix())));
duke@1 514 } catch (NumberFormatException ex) {
duke@1 515 log.error(S.pos(), "int.number.too.large", strval(prefix));
duke@1 516 }
duke@1 517 break;
duke@1 518 case FLOATLITERAL: {
duke@1 519 String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
duke@1 520 Float n;
duke@1 521 try {
duke@1 522 n = Float.valueOf(proper);
duke@1 523 } catch (NumberFormatException ex) {
duke@1 524 // error already repoted in scanner
duke@1 525 n = Float.NaN;
duke@1 526 }
duke@1 527 if (n.floatValue() == 0.0f && !isZero(proper))
duke@1 528 log.error(S.pos(), "fp.number.too.small");
duke@1 529 else if (n.floatValue() == Float.POSITIVE_INFINITY)
duke@1 530 log.error(S.pos(), "fp.number.too.large");
duke@1 531 else
duke@1 532 t = F.at(pos).Literal(TypeTags.FLOAT, n);
duke@1 533 break;
duke@1 534 }
duke@1 535 case DOUBLELITERAL: {
duke@1 536 String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
duke@1 537 Double n;
duke@1 538 try {
duke@1 539 n = Double.valueOf(proper);
duke@1 540 } catch (NumberFormatException ex) {
duke@1 541 // error already reported in scanner
duke@1 542 n = Double.NaN;
duke@1 543 }
duke@1 544 if (n.doubleValue() == 0.0d && !isZero(proper))
duke@1 545 log.error(S.pos(), "fp.number.too.small");
duke@1 546 else if (n.doubleValue() == Double.POSITIVE_INFINITY)
duke@1 547 log.error(S.pos(), "fp.number.too.large");
duke@1 548 else
duke@1 549 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
duke@1 550 break;
duke@1 551 }
duke@1 552 case CHARLITERAL:
duke@1 553 t = F.at(pos).Literal(
duke@1 554 TypeTags.CHAR,
duke@1 555 S.stringVal().charAt(0) + 0);
duke@1 556 break;
duke@1 557 case STRINGLITERAL:
duke@1 558 t = F.at(pos).Literal(
duke@1 559 TypeTags.CLASS,
duke@1 560 S.stringVal());
duke@1 561 break;
duke@1 562 case TRUE: case FALSE:
duke@1 563 t = F.at(pos).Literal(
duke@1 564 TypeTags.BOOLEAN,
duke@1 565 (S.token() == TRUE ? 1 : 0));
duke@1 566 break;
duke@1 567 case NULL:
duke@1 568 t = F.at(pos).Literal(
duke@1 569 TypeTags.BOT,
duke@1 570 null);
duke@1 571 break;
duke@1 572 default:
duke@1 573 assert false;
duke@1 574 }
duke@1 575 if (t == errorTree)
duke@1 576 t = F.at(pos).Erroneous();
duke@1 577 storeEnd(t, S.endPos());
duke@1 578 S.nextToken();
duke@1 579 return t;
duke@1 580 }
duke@1 581 //where
duke@1 582 boolean isZero(String s) {
duke@1 583 char[] cs = s.toCharArray();
duke@1 584 int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10);
duke@1 585 int i = ((base==16) ? 2 : 0);
duke@1 586 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
duke@1 587 return !(i < cs.length && (Character.digit(cs[i], base) > 0));
duke@1 588 }
duke@1 589
duke@1 590 String strval(Name prefix) {
duke@1 591 String s = S.stringVal();
duke@1 592 return (prefix.len == 0) ? s : prefix + s;
duke@1 593 }
duke@1 594
duke@1 595 /** terms can be either expressions or types.
duke@1 596 */
duke@1 597 public JCExpression expression() {
duke@1 598 return term(EXPR);
duke@1 599 }
duke@1 600
duke@1 601 public JCExpression type() {
duke@1 602 return term(TYPE);
duke@1 603 }
duke@1 604
duke@1 605 JCExpression term(int newmode) {
duke@1 606 int prevmode = mode;
duke@1 607 mode = newmode;
duke@1 608 JCExpression t = term();
duke@1 609 lastmode = mode;
duke@1 610 mode = prevmode;
duke@1 611 return t;
duke@1 612 }
duke@1 613
duke@1 614 /**
duke@1 615 * Expression = Expression1 [ExpressionRest]
duke@1 616 * ExpressionRest = [AssignmentOperator Expression1]
duke@1 617 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
duke@1 618 * "&=" | "|=" | "^=" |
duke@1 619 * "%=" | "<<=" | ">>=" | ">>>="
duke@1 620 * Type = Type1
duke@1 621 * TypeNoParams = TypeNoParams1
duke@1 622 * StatementExpression = Expression
duke@1 623 * ConstantExpression = Expression
duke@1 624 */
duke@1 625 JCExpression term() {
duke@1 626 JCExpression t = term1();
duke@1 627 if ((mode & EXPR) != 0 &&
duke@1 628 S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
duke@1 629 return termRest(t);
duke@1 630 else
duke@1 631 return t;
duke@1 632 }
duke@1 633
duke@1 634 JCExpression termRest(JCExpression t) {
duke@1 635 switch (S.token()) {
duke@1 636 case EQ: {
duke@1 637 int pos = S.pos();
duke@1 638 S.nextToken();
duke@1 639 mode = EXPR;
duke@1 640 JCExpression t1 = term();
duke@1 641 return toP(F.at(pos).Assign(t, t1));
duke@1 642 }
duke@1 643 case PLUSEQ:
duke@1 644 case SUBEQ:
duke@1 645 case STAREQ:
duke@1 646 case SLASHEQ:
duke@1 647 case PERCENTEQ:
duke@1 648 case AMPEQ:
duke@1 649 case BAREQ:
duke@1 650 case CARETEQ:
duke@1 651 case LTLTEQ:
duke@1 652 case GTGTEQ:
duke@1 653 case GTGTGTEQ:
duke@1 654 int pos = S.pos();
duke@1 655 Token token = S.token();
duke@1 656 S.nextToken();
duke@1 657 mode = EXPR;
duke@1 658 JCExpression t1 = term();
duke@1 659 return F.at(pos).Assignop(optag(token), t, t1);
duke@1 660 default:
duke@1 661 return t;
duke@1 662 }
duke@1 663 }
duke@1 664
duke@1 665 /** Expression1 = Expression2 [Expression1Rest]
duke@1 666 * Type1 = Type2
duke@1 667 * TypeNoParams1 = TypeNoParams2
duke@1 668 */
duke@1 669 JCExpression term1() {
duke@1 670 JCExpression t = term2();
duke@1 671 if ((mode & EXPR) != 0 && S.token() == QUES) {
duke@1 672 mode = EXPR;
duke@1 673 return term1Rest(t);
duke@1 674 } else {
duke@1 675 return t;
duke@1 676 }
duke@1 677 }
duke@1 678
duke@1 679 /** Expression1Rest = ["?" Expression ":" Expression1]
duke@1 680 */
duke@1 681 JCExpression term1Rest(JCExpression t) {
duke@1 682 if (S.token() == QUES) {
duke@1 683 int pos = S.pos();
duke@1 684 S.nextToken();
duke@1 685 JCExpression t1 = term();
duke@1 686 accept(COLON);
duke@1 687 JCExpression t2 = term1();
duke@1 688 return F.at(pos).Conditional(t, t1, t2);
duke@1 689 } else {
duke@1 690 return t;
duke@1 691 }
duke@1 692 }
duke@1 693
duke@1 694 /** Expression2 = Expression3 [Expression2Rest]
duke@1 695 * Type2 = Type3
duke@1 696 * TypeNoParams2 = TypeNoParams3
duke@1 697 */
duke@1 698 JCExpression term2() {
duke@1 699 JCExpression t = term3();
duke@1 700 if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
duke@1 701 mode = EXPR;
duke@1 702 return term2Rest(t, TreeInfo.orPrec);
duke@1 703 } else {
duke@1 704 return t;
duke@1 705 }
duke@1 706 }
duke@1 707
duke@1 708 /* Expression2Rest = {infixop Expression3}
duke@1 709 * | Expression3 instanceof Type
duke@1 710 * infixop = "||"
duke@1 711 * | "&&"
duke@1 712 * | "|"
duke@1 713 * | "^"
duke@1 714 * | "&"
duke@1 715 * | "==" | "!="
duke@1 716 * | "<" | ">" | "<=" | ">="
duke@1 717 * | "<<" | ">>" | ">>>"
duke@1 718 * | "+" | "-"
duke@1 719 * | "*" | "/" | "%"
duke@1 720 */
duke@1 721 JCExpression term2Rest(JCExpression t, int minprec) {
duke@1 722 List<JCExpression[]> savedOd = odStackSupply.elems;
duke@1 723 JCExpression[] odStack = newOdStack();
duke@1 724 List<Token[]> savedOp = opStackSupply.elems;
duke@1 725 Token[] opStack = newOpStack();
duke@1 726 // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
duke@1 727 int top = 0;
duke@1 728 odStack[0] = t;
duke@1 729 int startPos = S.pos();
duke@1 730 Token topOp = ERROR;
duke@1 731 while (prec(S.token()) >= minprec) {
duke@1 732 opStack[top] = topOp;
duke@1 733 top++;
duke@1 734 topOp = S.token();
duke@1 735 int pos = S.pos();
duke@1 736 S.nextToken();
duke@1 737 odStack[top] = topOp == INSTANCEOF ? type() : term3();
duke@1 738 while (top > 0 && prec(topOp) >= prec(S.token())) {
duke@1 739 odStack[top-1] = makeOp(pos, topOp, odStack[top-1],
duke@1 740 odStack[top]);
duke@1 741 top--;
duke@1 742 topOp = opStack[top];
duke@1 743 }
duke@1 744 }
duke@1 745 assert top == 0;
duke@1 746 t = odStack[0];
duke@1 747
duke@1 748 if (t.getTag() == JCTree.PLUS) {
duke@1 749 StringBuffer buf = foldStrings(t);
duke@1 750 if (buf != null) {
duke@1 751 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
duke@1 752 }
duke@1 753 }
duke@1 754
duke@1 755 odStackSupply.elems = savedOd; // optimization
duke@1 756 opStackSupply.elems = savedOp; // optimization
duke@1 757 return t;
duke@1 758 }
duke@1 759 //where
duke@1 760 /** Construct a binary or type test node.
duke@1 761 */
duke@1 762 private JCExpression makeOp(int pos,
duke@1 763 Token topOp,
duke@1 764 JCExpression od1,
duke@1 765 JCExpression od2)
duke@1 766 {
duke@1 767 if (topOp == INSTANCEOF) {
duke@1 768 return F.at(pos).TypeTest(od1, od2);
duke@1 769 } else {
duke@1 770 return F.at(pos).Binary(optag(topOp), od1, od2);
duke@1 771 }
duke@1 772 }
duke@1 773 /** If tree is a concatenation of string literals, replace it
duke@1 774 * by a single literal representing the concatenated string.
duke@1 775 */
duke@1 776 protected StringBuffer foldStrings(JCTree tree) {
duke@1 777 List<String> buf = List.nil();
duke@1 778 while (true) {
duke@1 779 if (tree.getTag() == JCTree.LITERAL) {
duke@1 780 JCLiteral lit = (JCLiteral) tree;
duke@1 781 if (lit.typetag == TypeTags.CLASS) {
duke@1 782 StringBuffer sbuf =
duke@1 783 new StringBuffer((String)lit.value);
duke@1 784 while (buf.nonEmpty()) {
duke@1 785 sbuf.append(buf.head);
duke@1 786 buf = buf.tail;
duke@1 787 }
duke@1 788 return sbuf;
duke@1 789 }
duke@1 790 } else if (tree.getTag() == JCTree.PLUS) {
duke@1 791 JCBinary op = (JCBinary)tree;
duke@1 792 if (op.rhs.getTag() == JCTree.LITERAL) {
duke@1 793 JCLiteral lit = (JCLiteral) op.rhs;
duke@1 794 if (lit.typetag == TypeTags.CLASS) {
duke@1 795 buf = buf.prepend((String) lit.value);
duke@1 796 tree = op.lhs;
duke@1 797 continue;
duke@1 798 }
duke@1 799 }
duke@1 800 }
duke@1 801 return null;
duke@1 802 }
duke@1 803 }
duke@1 804
duke@1 805 /** optimization: To save allocating a new operand/operator stack
duke@1 806 * for every binary operation, we use supplys.
duke@1 807 */
duke@1 808 ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
duke@1 809 ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
duke@1 810
duke@1 811 private JCExpression[] newOdStack() {
duke@1 812 if (odStackSupply.elems == odStackSupply.last)
duke@1 813 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
duke@1 814 JCExpression[] odStack = odStackSupply.elems.head;
duke@1 815 odStackSupply.elems = odStackSupply.elems.tail;
duke@1 816 return odStack;
duke@1 817 }
duke@1 818
duke@1 819 private Token[] newOpStack() {
duke@1 820 if (opStackSupply.elems == opStackSupply.last)
duke@1 821 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
duke@1 822 Token[] opStack = opStackSupply.elems.head;
duke@1 823 opStackSupply.elems = opStackSupply.elems.tail;
duke@1 824 return opStack;
duke@1 825 }
duke@1 826
duke@1 827 /** Expression3 = PrefixOp Expression3
duke@1 828 * | "(" Expr | TypeNoParams ")" Expression3
duke@1 829 * | Primary {Selector} {PostfixOp}
duke@1 830 * Primary = "(" Expression ")"
duke@1 831 * | Literal
duke@1 832 * | [TypeArguments] THIS [Arguments]
duke@1 833 * | [TypeArguments] SUPER SuperSuffix
duke@1 834 * | NEW [TypeArguments] Creator
duke@1 835 * | Ident { "." Ident }
duke@1 836 * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
duke@1 837 * | Arguments
duke@1 838 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
duke@1 839 * ]
duke@1 840 * | BasicType BracketsOpt "." CLASS
duke@1 841 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
duke@1 842 * PostfixOp = "++" | "--"
duke@1 843 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
duke@1 844 * | BasicType
duke@1 845 * TypeNoParams3 = Ident { "." Ident } BracketsOpt
duke@1 846 * Selector = "." [TypeArguments] Ident [Arguments]
duke@1 847 * | "." THIS
duke@1 848 * | "." [TypeArguments] SUPER SuperSuffix
duke@1 849 * | "." NEW [TypeArguments] InnerCreator
duke@1 850 * | "[" Expression "]"
duke@1 851 * TypeSelector = "." Ident [TypeArguments]
duke@1 852 * SuperSuffix = Arguments | "." Ident [Arguments]
duke@1 853 */
duke@1 854 protected JCExpression term3() {
duke@1 855 int pos = S.pos();
duke@1 856 JCExpression t;
duke@1 857 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
duke@1 858 switch (S.token()) {
duke@1 859 case QUES:
duke@1 860 if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
duke@1 861 mode = TYPE;
duke@1 862 return typeArgument();
duke@1 863 } else
duke@1 864 return illegal();
duke@1 865 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
duke@1 866 if (typeArgs == null && (mode & EXPR) != 0) {
duke@1 867 Token token = S.token();
duke@1 868 S.nextToken();
duke@1 869 mode = EXPR;
duke@1 870 if (token == SUB &&
duke@1 871 (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
duke@1 872 S.radix() == 10) {
duke@1 873 mode = EXPR;
duke@1 874 t = literal(names.hyphen);
duke@1 875 } else {
duke@1 876 t = term3();
duke@1 877 return F.at(pos).Unary(unoptag(token), t);
duke@1 878 }
duke@1 879 } else return illegal();
duke@1 880 break;
duke@1 881 case LPAREN:
duke@1 882 if (typeArgs == null && (mode & EXPR) != 0) {
duke@1 883 S.nextToken();
duke@1 884 mode = EXPR | TYPE | NOPARAMS;
duke@1 885 t = term3();
duke@1 886 if ((mode & TYPE) != 0 && S.token() == LT) {
duke@1 887 // Could be a cast to a parameterized type
duke@1 888 int op = JCTree.LT;
duke@1 889 int pos1 = S.pos();
duke@1 890 S.nextToken();
duke@1 891 mode &= (EXPR | TYPE);
duke@1 892 mode |= TYPEARG;
duke@1 893 JCExpression t1 = term3();
duke@1 894 if ((mode & TYPE) != 0 &&
duke@1 895 (S.token() == COMMA || S.token() == GT)) {
duke@1 896 mode = TYPE;
duke@1 897 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
duke@1 898 args.append(t1);
duke@1 899 while (S.token() == COMMA) {
duke@1 900 S.nextToken();
duke@1 901 args.append(typeArgument());
duke@1 902 }
duke@1 903 accept(GT);
duke@1 904 t = F.at(pos1).TypeApply(t, args.toList());
duke@1 905 checkGenerics();
duke@1 906 t = bracketsOpt(toP(t));
duke@1 907 } else if ((mode & EXPR) != 0) {
duke@1 908 mode = EXPR;
duke@1 909 t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec));
duke@1 910 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
duke@1 911 } else {
duke@1 912 accept(GT);
duke@1 913 }
duke@1 914 } else {
duke@1 915 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
duke@1 916 }
duke@1 917 accept(RPAREN);
duke@1 918 lastmode = mode;
duke@1 919 mode = EXPR;
duke@1 920 if ((lastmode & EXPR) == 0) {
duke@1 921 JCExpression t1 = term3();
duke@1 922 return F.at(pos).TypeCast(t, t1);
duke@1 923 } else if ((lastmode & TYPE) != 0) {
duke@1 924 switch (S.token()) {
duke@1 925 /*case PLUSPLUS: case SUBSUB: */
duke@1 926 case BANG: case TILDE:
duke@1 927 case LPAREN: case THIS: case SUPER:
duke@1 928 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
duke@1 929 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
duke@1 930 case TRUE: case FALSE: case NULL:
duke@1 931 case NEW: case IDENTIFIER: case ASSERT: case ENUM:
duke@1 932 case BYTE: case SHORT: case CHAR: case INT:
duke@1 933 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
duke@1 934 JCExpression t1 = term3();
duke@1 935 return F.at(pos).TypeCast(t, t1);
duke@1 936 }
duke@1 937 }
duke@1 938 } else return illegal();
duke@1 939 t = toP(F.at(pos).Parens(t));
duke@1 940 break;
duke@1 941 case THIS:
duke@1 942 if ((mode & EXPR) != 0) {
duke@1 943 mode = EXPR;
duke@1 944 t = to(F.at(pos).Ident(names._this));
duke@1 945 S.nextToken();
duke@1 946 if (typeArgs == null)
duke@1 947 t = argumentsOpt(null, t);
duke@1 948 else
duke@1 949 t = arguments(typeArgs, t);
duke@1 950 typeArgs = null;
duke@1 951 } else return illegal();
duke@1 952 break;
duke@1 953 case SUPER:
duke@1 954 if ((mode & EXPR) != 0) {
duke@1 955 mode = EXPR;
duke@1 956 t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super)));
duke@1 957 typeArgs = null;
duke@1 958 } else return illegal();
duke@1 959 break;
duke@1 960 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
duke@1 961 case CHARLITERAL: case STRINGLITERAL:
duke@1 962 case TRUE: case FALSE: case NULL:
duke@1 963 if (typeArgs == null && (mode & EXPR) != 0) {
duke@1 964 mode = EXPR;
duke@1 965 t = literal(names.empty);
duke@1 966 } else return illegal();
duke@1 967 break;
duke@1 968 case NEW:
duke@1 969 if (typeArgs != null) return illegal();
duke@1 970 if ((mode & EXPR) != 0) {
duke@1 971 mode = EXPR;
duke@1 972 S.nextToken();
duke@1 973 if (S.token() == LT) typeArgs = typeArguments();
duke@1 974 t = creator(pos, typeArgs);
duke@1 975 typeArgs = null;
duke@1 976 } else return illegal();
duke@1 977 break;
duke@1 978 case IDENTIFIER: case ASSERT: case ENUM:
duke@1 979 if (typeArgs != null) return illegal();
duke@1 980 t = toP(F.at(S.pos()).Ident(ident()));
duke@1 981 loop: while (true) {
duke@1 982 pos = S.pos();
duke@1 983 switch (S.token()) {
duke@1 984 case LBRACKET:
duke@1 985 S.nextToken();
duke@1 986 if (S.token() == RBRACKET) {
duke@1 987 S.nextToken();
duke@1 988 t = bracketsOpt(t);
duke@1 989 t = toP(F.at(pos).TypeArray(t));
duke@1 990 t = bracketsSuffix(t);
duke@1 991 } else {
duke@1 992 if ((mode & EXPR) != 0) {
duke@1 993 mode = EXPR;
duke@1 994 JCExpression t1 = term();
duke@1 995 t = to(F.at(pos).Indexed(t, t1));
duke@1 996 }
duke@1 997 accept(RBRACKET);
duke@1 998 }
duke@1 999 break loop;
duke@1 1000 case LPAREN:
duke@1 1001 if ((mode & EXPR) != 0) {
duke@1 1002 mode = EXPR;
duke@1 1003 t = arguments(typeArgs, t);
duke@1 1004 typeArgs = null;
duke@1 1005 }
duke@1 1006 break loop;
duke@1 1007 case DOT:
duke@1 1008 S.nextToken();
duke@1 1009 typeArgs = typeArgumentsOpt(EXPR);
duke@1 1010 if ((mode & EXPR) != 0) {
duke@1 1011 switch (S.token()) {
duke@1 1012 case CLASS:
duke@1 1013 if (typeArgs != null) return illegal();
duke@1 1014 mode = EXPR;
duke@1 1015 t = to(F.at(pos).Select(t, names._class));
duke@1 1016 S.nextToken();
duke@1 1017 break loop;
duke@1 1018 case THIS:
duke@1 1019 if (typeArgs != null) return illegal();
duke@1 1020 mode = EXPR;
duke@1 1021 t = to(F.at(pos).Select(t, names._this));
duke@1 1022 S.nextToken();
duke@1 1023 break loop;
duke@1 1024 case SUPER:
duke@1 1025 mode = EXPR;
duke@1 1026 t = to(F.at(pos).Select(t, names._super));
duke@1 1027 t = superSuffix(typeArgs, t);
duke@1 1028 typeArgs = null;
duke@1 1029 break loop;
duke@1 1030 case NEW:
duke@1 1031 if (typeArgs != null) return illegal();
duke@1 1032 mode = EXPR;
duke@1 1033 int pos1 = S.pos();
duke@1 1034 S.nextToken();
duke@1 1035 if (S.token() == LT) typeArgs = typeArguments();
duke@1 1036 t = innerCreator(pos1, typeArgs, t);
duke@1 1037 typeArgs = null;
duke@1 1038 break loop;
duke@1 1039 }
duke@1 1040 }
duke@1 1041 // typeArgs saved for next loop iteration.
duke@1 1042 t = toP(F.at(pos).Select(t, ident()));
duke@1 1043 break;
duke@1 1044 default:
duke@1 1045 break loop;
duke@1 1046 }
duke@1 1047 }
duke@1 1048 if (typeArgs != null) illegal();
duke@1 1049 t = typeArgumentsOpt(t);
duke@1 1050 break;
duke@1 1051 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
duke@1 1052 case DOUBLE: case BOOLEAN:
duke@1 1053 if (typeArgs != null) illegal();
duke@1 1054 t = bracketsSuffix(bracketsOpt(basicType()));
duke@1 1055 break;
duke@1 1056 case VOID:
duke@1 1057 if (typeArgs != null) illegal();
duke@1 1058 if ((mode & EXPR) != 0) {
duke@1 1059 S.nextToken();
duke@1 1060 if (S.token() == DOT) {
duke@1 1061 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
duke@1 1062 t = bracketsSuffix(ti);
duke@1 1063 } else {
duke@1 1064 return illegal(pos);
duke@1 1065 }
duke@1 1066 } else {
duke@1 1067 return illegal();
duke@1 1068 }
duke@1 1069 break;
duke@1 1070 default:
duke@1 1071 return illegal();
duke@1 1072 }
duke@1 1073 if (typeArgs != null) illegal();
duke@1 1074 while (true) {
duke@1 1075 int pos1 = S.pos();
duke@1 1076 if (S.token() == LBRACKET) {
duke@1 1077 S.nextToken();
duke@1 1078 if ((mode & TYPE) != 0) {
duke@1 1079 int oldmode = mode;
duke@1 1080 mode = TYPE;
duke@1 1081 if (S.token() == RBRACKET) {
duke@1 1082 S.nextToken();
duke@1 1083 t = bracketsOpt(t);
duke@1 1084 t = toP(F.at(pos1).TypeArray(t));
duke@1 1085 return t;
duke@1 1086 }
duke@1 1087 mode = oldmode;
duke@1 1088 }
duke@1 1089 if ((mode & EXPR) != 0) {
duke@1 1090 mode = EXPR;
duke@1 1091 JCExpression t1 = term();
duke@1 1092 t = to(F.at(pos1).Indexed(t, t1));
duke@1 1093 }
duke@1 1094 accept(RBRACKET);
duke@1 1095 } else if (S.token() == DOT) {
duke@1 1096 S.nextToken();
duke@1 1097 typeArgs = typeArgumentsOpt(EXPR);
duke@1 1098 if (S.token() == SUPER && (mode & EXPR) != 0) {
duke@1 1099 mode = EXPR;
duke@1 1100 t = to(F.at(pos1).Select(t, names._super));
duke@1 1101 S.nextToken();
duke@1 1102 t = arguments(typeArgs, t);
duke@1 1103 typeArgs = null;
duke@1 1104 } else if (S.token() == NEW && (mode & EXPR) != 0) {
duke@1 1105 if (typeArgs != null) return illegal();
duke@1 1106 mode = EXPR;
duke@1 1107 int pos2 = S.pos();
duke@1 1108 S.nextToken();
duke@1 1109 if (S.token() == LT) typeArgs = typeArguments();
duke@1 1110 t = innerCreator(pos2, typeArgs, t);
duke@1 1111 typeArgs = null;
duke@1 1112 } else {
duke@1 1113 t = toP(F.at(pos1).Select(t, ident()));
duke@1 1114 t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
duke@1 1115 typeArgs = null;
duke@1 1116 }
duke@1 1117 } else {
duke@1 1118 break;
duke@1 1119 }
duke@1 1120 }
duke@1 1121 while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
duke@1 1122 mode = EXPR;
duke@1 1123 t = to(F.at(S.pos()).Unary(
duke@1 1124 S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
duke@1 1125 S.nextToken();
duke@1 1126 }
duke@1 1127 return toP(t);
duke@1 1128 }
duke@1 1129
duke@1 1130 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
duke@1 1131 */
duke@1 1132 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
duke@1 1133 S.nextToken();
duke@1 1134 if (S.token() == LPAREN || typeArgs != null) {
duke@1 1135 t = arguments(typeArgs, t);
duke@1 1136 } else {
duke@1 1137 int pos = S.pos();
duke@1 1138 accept(DOT);
duke@1 1139 typeArgs = (S.token() == LT) ? typeArguments() : null;
duke@1 1140 t = toP(F.at(pos).Select(t, ident()));
duke@1 1141 t = argumentsOpt(typeArgs, t);
duke@1 1142 }
duke@1 1143 return t;
duke@1 1144 }
duke@1 1145
duke@1 1146 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
duke@1 1147 */
duke@1 1148 JCPrimitiveTypeTree basicType() {
duke@1 1149 JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
duke@1 1150 S.nextToken();
duke@1 1151 return t;
duke@1 1152 }
duke@1 1153
duke@1 1154 /** ArgumentsOpt = [ Arguments ]
duke@1 1155 */
duke@1 1156 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
duke@1 1157 if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
duke@1 1158 mode = EXPR;
duke@1 1159 return arguments(typeArgs, t);
duke@1 1160 } else {
duke@1 1161 return t;
duke@1 1162 }
duke@1 1163 }
duke@1 1164
duke@1 1165 /** Arguments = "(" [Expression { COMMA Expression }] ")"
duke@1 1166 */
duke@1 1167 List<JCExpression> arguments() {
duke@1 1168 ListBuffer<JCExpression> args = lb();
duke@1 1169 if (S.token() == LPAREN) {
duke@1 1170 S.nextToken();
duke@1 1171 if (S.token() != RPAREN) {
duke@1 1172 args.append(expression());
duke@1 1173 while (S.token() == COMMA) {
duke@1 1174 S.nextToken();
duke@1 1175 args.append(expression());
duke@1 1176 }
duke@1 1177 }
duke@1 1178 accept(RPAREN);
duke@1 1179 } else {
duke@1 1180 syntaxError(S.pos(), "expected", keywords.token2string(LPAREN));
duke@1 1181 }
duke@1 1182 return args.toList();
duke@1 1183 }
duke@1 1184
duke@1 1185 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
duke@1 1186 int pos = S.pos();
duke@1 1187 List<JCExpression> args = arguments();
duke@1 1188 return toP(F.at(pos).Apply(typeArgs, t, args));
duke@1 1189 }
duke@1 1190
duke@1 1191 /** TypeArgumentsOpt = [ TypeArguments ]
duke@1 1192 */
duke@1 1193 JCExpression typeArgumentsOpt(JCExpression t) {
duke@1 1194 if (S.token() == LT &&
duke@1 1195 (mode & TYPE) != 0 &&
duke@1 1196 (mode & NOPARAMS) == 0) {
duke@1 1197 mode = TYPE;
duke@1 1198 checkGenerics();
duke@1 1199 return typeArguments(t);
duke@1 1200 } else {
duke@1 1201 return t;
duke@1 1202 }
duke@1 1203 }
duke@1 1204 List<JCExpression> typeArgumentsOpt() {
duke@1 1205 return typeArgumentsOpt(TYPE);
duke@1 1206 }
duke@1 1207
duke@1 1208 List<JCExpression> typeArgumentsOpt(int useMode) {
duke@1 1209 if (S.token() == LT) {
duke@1 1210 checkGenerics();
duke@1 1211 if ((mode & useMode) == 0 ||
duke@1 1212 (mode & NOPARAMS) != 0) {
duke@1 1213 illegal();
duke@1 1214 }
duke@1 1215 mode = useMode;
duke@1 1216 return typeArguments();
duke@1 1217 }
duke@1 1218 return null;
duke@1 1219 }
duke@1 1220
duke@1 1221 /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
duke@1 1222 */
duke@1 1223 List<JCExpression> typeArguments() {
duke@1 1224 ListBuffer<JCExpression> args = lb();
duke@1 1225 if (S.token() == LT) {
duke@1 1226 S.nextToken();
duke@1 1227 args.append(((mode & EXPR) == 0) ? typeArgument() : type());
duke@1 1228 while (S.token() == COMMA) {
duke@1 1229 S.nextToken();
duke@1 1230 args.append(((mode & EXPR) == 0) ? typeArgument() : type());
duke@1 1231 }
duke@1 1232 switch (S.token()) {
duke@1 1233 case GTGTGTEQ:
duke@1 1234 S.token(GTGTEQ);
duke@1 1235 break;
duke@1 1236 case GTGTEQ:
duke@1 1237 S.token(GTEQ);
duke@1 1238 break;
duke@1 1239 case GTEQ:
duke@1 1240 S.token(EQ);
duke@1 1241 break;
duke@1 1242 case GTGTGT:
duke@1 1243 S.token(GTGT);
duke@1 1244 break;
duke@1 1245 case GTGT:
duke@1 1246 S.token(GT);
duke@1 1247 break;
duke@1 1248 default:
duke@1 1249 accept(GT);
duke@1 1250 break;
duke@1 1251 }
duke@1 1252 } else {
duke@1 1253 syntaxError(S.pos(), "expected", keywords.token2string(LT));
duke@1 1254 }
duke@1 1255 return args.toList();
duke@1 1256 }
duke@1 1257
duke@1 1258 /** TypeArgument = Type
duke@1 1259 * | "?"
duke@1 1260 * | "?" EXTENDS Type {"&" Type}
duke@1 1261 * | "?" SUPER Type
duke@1 1262 */
duke@1 1263 JCExpression typeArgument() {
duke@1 1264 if (S.token() != QUES) return type();
duke@1 1265 int pos = S.pos();
duke@1 1266 S.nextToken();
duke@1 1267 if (S.token() == EXTENDS) {
duke@1 1268 TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
duke@1 1269 S.nextToken();
duke@1 1270 return F.at(pos).Wildcard(t, type());
duke@1 1271 } else if (S.token() == SUPER) {
duke@1 1272 TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
duke@1 1273 S.nextToken();
duke@1 1274 return F.at(pos).Wildcard(t, type());
duke@1 1275 } else if (S.token() == IDENTIFIER) {
duke@1 1276 //error recovery
duke@1 1277 reportSyntaxError(S.prevEndPos(), "expected3",
duke@1 1278 keywords.token2string(GT),
duke@1 1279 keywords.token2string(EXTENDS),
duke@1 1280 keywords.token2string(SUPER));
duke@1 1281 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
duke@1 1282 JCExpression wc = toP(F.at(pos).Wildcard(t, null));
duke@1 1283 JCIdent id = toP(F.at(S.pos()).Ident(ident()));
duke@1 1284 return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
duke@1 1285 } else {
duke@1 1286 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
duke@1 1287 return toP(F.at(pos).Wildcard(t, null));
duke@1 1288 }
duke@1 1289 }
duke@1 1290
duke@1 1291 JCTypeApply typeArguments(JCExpression t) {
duke@1 1292 int pos = S.pos();
duke@1 1293 List<JCExpression> args = typeArguments();
duke@1 1294 return toP(F.at(pos).TypeApply(t, args));
duke@1 1295 }
duke@1 1296
duke@1 1297 /** BracketsOpt = {"[" "]"}
duke@1 1298 */
duke@1 1299 private JCExpression bracketsOpt(JCExpression t) {
duke@1 1300 if (S.token() == LBRACKET) {
duke@1 1301 int pos = S.pos();
duke@1 1302 S.nextToken();
duke@1 1303 t = bracketsOptCont(t, pos);
duke@1 1304 F.at(pos);
duke@1 1305 }
duke@1 1306 return t;
duke@1 1307 }
duke@1 1308
duke@1 1309 private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
duke@1 1310 accept(RBRACKET);
duke@1 1311 t = bracketsOpt(t);
duke@1 1312 return toP(F.at(pos).TypeArray(t));
duke@1 1313 }
duke@1 1314
duke@1 1315 /** BracketsSuffixExpr = "." CLASS
duke@1 1316 * BracketsSuffixType =
duke@1 1317 */
duke@1 1318 JCExpression bracketsSuffix(JCExpression t) {
duke@1 1319 if ((mode & EXPR) != 0 && S.token() == DOT) {
duke@1 1320 mode = EXPR;
duke@1 1321 int pos = S.pos();
duke@1 1322 S.nextToken();
duke@1 1323 accept(CLASS);
duke@1 1324 if (S.pos() == errorEndPos) {
duke@1 1325 // error recovery
duke@1 1326 Name name = null;
duke@1 1327 if (S.token() == IDENTIFIER) {
duke@1 1328 name = S.name();
duke@1 1329 S.nextToken();
duke@1 1330 } else {
duke@1 1331 name = names.error;
duke@1 1332 }
duke@1 1333 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
duke@1 1334 } else {
duke@1 1335 t = toP(F.at(pos).Select(t, names._class));
duke@1 1336 }
duke@1 1337 } else if ((mode & TYPE) != 0) {
duke@1 1338 mode = TYPE;
duke@1 1339 } else {
duke@1 1340 syntaxError(S.pos(), "dot.class.expected");
duke@1 1341 }
duke@1 1342 return t;
duke@1 1343 }
duke@1 1344
duke@1 1345 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
duke@1 1346 */
duke@1 1347 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
duke@1 1348 switch (S.token()) {
duke@1 1349 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
duke@1 1350 case DOUBLE: case BOOLEAN:
duke@1 1351 if (typeArgs == null)
duke@1 1352 return arrayCreatorRest(newpos, basicType());
duke@1 1353 break;
duke@1 1354 default:
duke@1 1355 }
duke@1 1356 JCExpression t = qualident();
duke@1 1357 int oldmode = mode;
duke@1 1358 mode = TYPE;
duke@1 1359 if (S.token() == LT) {
duke@1 1360 checkGenerics();
duke@1 1361 t = typeArguments(t);
duke@1 1362 }
duke@1 1363 while (S.token() == DOT) {
duke@1 1364 int pos = S.pos();
duke@1 1365 S.nextToken();
duke@1 1366 t = toP(F.at(pos).Select(t, ident()));
duke@1 1367 if (S.token() == LT) {
duke@1 1368 checkGenerics();
duke@1 1369 t = typeArguments(t);
duke@1 1370 }
duke@1 1371 }
duke@1 1372 mode = oldmode;
duke@1 1373 if (S.token() == LBRACKET) {
duke@1 1374 JCExpression e = arrayCreatorRest(newpos, t);
duke@1 1375 if (typeArgs != null) {
duke@1 1376 int pos = newpos;
duke@1 1377 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
duke@1 1378 // note: this should always happen but we should
duke@1 1379 // not rely on this as the parser is continuously
duke@1 1380 // modified to improve error recovery.
duke@1 1381 pos = typeArgs.head.pos;
duke@1 1382 }
duke@1 1383 setErrorEndPos(S.prevEndPos());
duke@1 1384 reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
duke@1 1385 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
duke@1 1386 }
duke@1 1387 return e;
duke@1 1388 } else if (S.token() == LPAREN) {
duke@1 1389 return classCreatorRest(newpos, null, typeArgs, t);
duke@1 1390 } else {
duke@1 1391 reportSyntaxError(S.pos(), "expected2",
duke@1 1392 keywords.token2string(LPAREN),
duke@1 1393 keywords.token2string(LBRACKET));
duke@1 1394 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
duke@1 1395 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
duke@1 1396 }
duke@1 1397 }
duke@1 1398
duke@1 1399 /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
duke@1 1400 */
duke@1 1401 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
duke@1 1402 JCExpression t = toP(F.at(S.pos()).Ident(ident()));
duke@1 1403 if (S.token() == LT) {
duke@1 1404 checkGenerics();
duke@1 1405 t = typeArguments(t);
duke@1 1406 }
duke@1 1407 return classCreatorRest(newpos, encl, typeArgs, t);
duke@1 1408 }
duke@1 1409
duke@1 1410 /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
duke@1 1411 * | Expression "]" {"[" Expression "]"} BracketsOpt )
duke@1 1412 */
duke@1 1413 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
duke@1 1414 accept(LBRACKET);
duke@1 1415 if (S.token() == RBRACKET) {
duke@1 1416 accept(RBRACKET);
duke@1 1417 elemtype = bracketsOpt(elemtype);
duke@1 1418 if (S.token() == LBRACE) {
duke@1 1419 return arrayInitializer(newpos, elemtype);
duke@1 1420 } else {
duke@1 1421 return syntaxError(S.pos(), "array.dimension.missing");
duke@1 1422 }
duke@1 1423 } else {
duke@1 1424 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
duke@1 1425 dims.append(expression());
duke@1 1426 accept(RBRACKET);
duke@1 1427 while (S.token() == LBRACKET) {
duke@1 1428 int pos = S.pos();
duke@1 1429 S.nextToken();
duke@1 1430 if (S.token() == RBRACKET) {
duke@1 1431 elemtype = bracketsOptCont(elemtype, pos);
duke@1 1432 } else {
duke@1 1433 dims.append(expression());
duke@1 1434 accept(RBRACKET);
duke@1 1435 }
duke@1 1436 }
duke@1 1437 return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
duke@1 1438 }
duke@1 1439 }
duke@1 1440
duke@1 1441 /** ClassCreatorRest = Arguments [ClassBody]
duke@1 1442 */
duke@1 1443 JCExpression classCreatorRest(int newpos,
duke@1 1444 JCExpression encl,
duke@1 1445 List<JCExpression> typeArgs,
duke@1 1446 JCExpression t)
duke@1 1447 {
duke@1 1448 List<JCExpression> args = arguments();
duke@1 1449 JCClassDecl body = null;
duke@1 1450 if (S.token() == LBRACE) {
duke@1 1451 int pos = S.pos();
duke@1 1452 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
duke@1 1453 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
duke@1 1454 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
duke@1 1455 }
duke@1 1456 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
duke@1 1457 }
duke@1 1458
duke@1 1459 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
duke@1 1460 */
duke@1 1461 JCExpression arrayInitializer(int newpos, JCExpression t) {
duke@1 1462 accept(LBRACE);
duke@1 1463 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
duke@1 1464 if (S.token() == COMMA) {
duke@1 1465 S.nextToken();
duke@1 1466 } else if (S.token() != RBRACE) {
duke@1 1467 elems.append(variableInitializer());
duke@1 1468 while (S.token() == COMMA) {
duke@1 1469 S.nextToken();
duke@1 1470 if (S.token() == RBRACE) break;
duke@1 1471 elems.append(variableInitializer());
duke@1 1472 }
duke@1 1473 }
duke@1 1474 accept(RBRACE);
duke@1 1475 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
duke@1 1476 }
duke@1 1477
duke@1 1478 /** VariableInitializer = ArrayInitializer | Expression
duke@1 1479 */
duke@1 1480 public JCExpression variableInitializer() {
duke@1 1481 return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : expression();
duke@1 1482 }
duke@1 1483
duke@1 1484 /** ParExpression = "(" Expression ")"
duke@1 1485 */
duke@1 1486 JCExpression parExpression() {
duke@1 1487 accept(LPAREN);
duke@1 1488 JCExpression t = expression();
duke@1 1489 accept(RPAREN);
duke@1 1490 return t;
duke@1 1491 }
duke@1 1492
duke@1 1493 /** Block = "{" BlockStatements "}"
duke@1 1494 */
duke@1 1495 JCBlock block(int pos, long flags) {
duke@1 1496 accept(LBRACE);
duke@1 1497 List<JCStatement> stats = blockStatements();
duke@1 1498 JCBlock t = F.at(pos).Block(flags, stats);
duke@1 1499 while (S.token() == CASE || S.token() == DEFAULT) {
duke@1 1500 syntaxError("orphaned", keywords.token2string(S.token()));
duke@1 1501 switchBlockStatementGroups();
duke@1 1502 }
duke@1 1503 // the Block node has a field "endpos" for first char of last token, which is
duke@1 1504 // usually but not necessarily the last char of the last token.
duke@1 1505 t.endpos = S.pos();
duke@1 1506 accept(RBRACE);
duke@1 1507 return toP(t);
duke@1 1508 }
duke@1 1509
duke@1 1510 public JCBlock block() {
duke@1 1511 return block(S.pos(), 0);
duke@1 1512 }
duke@1 1513
duke@1 1514 /** BlockStatements = { BlockStatement }
duke@1 1515 * BlockStatement = LocalVariableDeclarationStatement
duke@1 1516 * | ClassOrInterfaceOrEnumDeclaration
duke@1 1517 * | [Ident ":"] Statement
duke@1 1518 * LocalVariableDeclarationStatement
duke@1 1519 * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
duke@1 1520 */
duke@1 1521 @SuppressWarnings("fallthrough")
duke@1 1522 List<JCStatement> blockStatements() {
duke@1 1523 //todo: skip to anchor on error(?)
duke@1 1524 int lastErrPos = -1;
duke@1 1525 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
duke@1 1526 while (true) {
duke@1 1527 int pos = S.pos();
duke@1 1528 switch (S.token()) {
duke@1 1529 case RBRACE: case CASE: case DEFAULT: case EOF:
duke@1 1530 return stats.toList();
duke@1 1531 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
duke@1 1532 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
duke@1 1533 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
duke@1 1534 stats.append(statement());
duke@1 1535 break;
duke@1 1536 case MONKEYS_AT:
duke@1 1537 case FINAL: {
duke@1 1538 String dc = S.docComment();
duke@1 1539 JCModifiers mods = modifiersOpt();
duke@1 1540 if (S.token() == INTERFACE ||
duke@1 1541 S.token() == CLASS ||
duke@1 1542 allowEnums && S.token() == ENUM) {
duke@1 1543 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
duke@1 1544 } else {
duke@1 1545 JCExpression t = type();
duke@1 1546 stats.appendList(variableDeclarators(mods, t,
duke@1 1547 new ListBuffer<JCStatement>()));
duke@1 1548 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
duke@1 1549 storeEnd(stats.elems.last(), S.endPos());
duke@1 1550 accept(SEMI);
duke@1 1551 }
duke@1 1552 break;
duke@1 1553 }
duke@1 1554 case ABSTRACT: case STRICTFP: {
duke@1 1555 String dc = S.docComment();
duke@1 1556 JCModifiers mods = modifiersOpt();
duke@1 1557 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
duke@1 1558 break;
duke@1 1559 }
duke@1 1560 case INTERFACE:
duke@1 1561 case CLASS:
duke@1 1562 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
duke@1 1563 S.docComment()));
duke@1 1564 break;
duke@1 1565 case ENUM:
duke@1 1566 case ASSERT:
duke@1 1567 if (allowEnums && S.token() == ENUM) {
duke@1 1568 log.error(S.pos(), "local.enum");
duke@1 1569 stats.
duke@1 1570 append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
duke@1 1571 S.docComment()));
duke@1 1572 break;
duke@1 1573 } else if (allowAsserts && S.token() == ASSERT) {
duke@1 1574 stats.append(statement());
duke@1 1575 break;
duke@1 1576 }
duke@1 1577 /* fall through to default */
duke@1 1578 default:
duke@1 1579 Name name = S.name();
duke@1 1580 JCExpression t = term(EXPR | TYPE);
duke@1 1581 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
duke@1 1582 S.nextToken();
duke@1 1583 JCStatement stat = statement();
duke@1 1584 stats.append(F.at(pos).Labelled(name, stat));
duke@1 1585 } else if ((lastmode & TYPE) != 0 &&
duke@1 1586 (S.token() == IDENTIFIER ||
duke@1 1587 S.token() == ASSERT ||
duke@1 1588 S.token() == ENUM)) {
duke@1 1589 pos = S.pos();
duke@1 1590 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
duke@1 1591 F.at(pos);
duke@1 1592 stats.appendList(variableDeclarators(mods, t,
duke@1 1593 new ListBuffer<JCStatement>()));
duke@1 1594 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
duke@1 1595 storeEnd(stats.elems.last(), S.endPos());
duke@1 1596 accept(SEMI);
duke@1 1597 } else {
duke@1 1598 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
duke@1 1599 stats.append(to(F.at(pos).Exec(checkExprStat(t))));
duke@1 1600 accept(SEMI);
duke@1 1601 }
duke@1 1602 }
duke@1 1603
duke@1 1604 // error recovery
duke@1 1605 if (S.pos() == lastErrPos)
duke@1 1606 return stats.toList();
duke@1 1607 if (S.pos() <= errorEndPos) {
duke@1 1608 skip(false, true, true, true);
duke@1 1609 lastErrPos = S.pos();
duke@1 1610 }
duke@1 1611
duke@1 1612 // ensure no dangling /** @deprecated */ active
duke@1 1613 S.resetDeprecatedFlag();
duke@1 1614 }
duke@1 1615 }
duke@1 1616
duke@1 1617 /** Statement =
duke@1 1618 * Block
duke@1 1619 * | IF ParExpression Statement [ELSE Statement]
duke@1 1620 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
duke@1 1621 * | FOR "(" FormalParameter : Expression ")" Statement
duke@1 1622 * | WHILE ParExpression Statement
duke@1 1623 * | DO Statement WHILE ParExpression ";"
duke@1 1624 * | TRY Block ( Catches | [Catches] FinallyPart )
duke@1 1625 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
duke@1 1626 * | SYNCHRONIZED ParExpression Block
duke@1 1627 * | RETURN [Expression] ";"
duke@1 1628 * | THROW Expression ";"
duke@1 1629 * | BREAK [Ident] ";"
duke@1 1630 * | CONTINUE [Ident] ";"
duke@1 1631 * | ASSERT Expression [ ":" Expression ] ";"
duke@1 1632 * | ";"
duke@1 1633 * | ExpressionStatement
duke@1 1634 * | Ident ":" Statement
duke@1 1635 */
duke@1 1636 @SuppressWarnings("fallthrough")
duke@1 1637 public JCStatement statement() {
duke@1 1638 int pos = S.pos();
duke@1 1639 switch (S.token()) {
duke@1 1640 case LBRACE:
duke@1 1641 return block();
duke@1 1642 case IF: {
duke@1 1643 S.nextToken();
duke@1 1644 JCExpression cond = parExpression();
duke@1 1645 JCStatement thenpart = statement();
duke@1 1646 JCStatement elsepart = null;
duke@1 1647 if (S.token() == ELSE) {
duke@1 1648 S.nextToken();
duke@1 1649 elsepart = statement();
duke@1 1650 }
duke@1 1651 return F.at(pos).If(cond, thenpart, elsepart);
duke@1 1652 }
duke@1 1653 case FOR: {
duke@1 1654 S.nextToken();
duke@1 1655 accept(LPAREN);
duke@1 1656 List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
duke@1 1657 if (inits.length() == 1 &&
duke@1 1658 inits.head.getTag() == JCTree.VARDEF &&
duke@1 1659 ((JCVariableDecl) inits.head).init == null &&
duke@1 1660 S.token() == COLON) {
duke@1 1661 checkForeach();
duke@1 1662 JCVariableDecl var = (JCVariableDecl)inits.head;
duke@1 1663 accept(COLON);
duke@1 1664 JCExpression expr = expression();
duke@1 1665 accept(RPAREN);
duke@1 1666 JCStatement body = statement();
duke@1 1667 return F.at(pos).ForeachLoop(var, expr, body);
duke@1 1668 } else {
duke@1 1669 accept(SEMI);
duke@1 1670 JCExpression cond = S.token() == SEMI ? null : expression();
duke@1 1671 accept(SEMI);
duke@1 1672 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
duke@1 1673 accept(RPAREN);
duke@1 1674 JCStatement body = statement();
duke@1 1675 return F.at(pos).ForLoop(inits, cond, steps, body);
duke@1 1676 }
duke@1 1677 }
duke@1 1678 case WHILE: {
duke@1 1679 S.nextToken();
duke@1 1680 JCExpression cond = parExpression();
duke@1 1681 JCStatement body = statement();
duke@1 1682 return F.at(pos).WhileLoop(cond, body);
duke@1 1683 }
duke@1 1684 case DO: {
duke@1 1685 S.nextToken();
duke@1 1686 JCStatement body = statement();
duke@1 1687 accept(WHILE);
duke@1 1688 JCExpression cond = parExpression();
duke@1 1689 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
duke@1 1690 accept(SEMI);
duke@1 1691 return t;
duke@1 1692 }
duke@1 1693 case TRY: {
duke@1 1694 S.nextToken();
duke@1 1695 JCBlock body = block();
duke@1 1696 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
duke@1 1697 JCBlock finalizer = null;
duke@1 1698 if (S.token() == CATCH || S.token() == FINALLY) {
duke@1 1699 while (S.token() == CATCH) catchers.append(catchClause());
duke@1 1700 if (S.token() == FINALLY) {
duke@1 1701 S.nextToken();
duke@1 1702 finalizer = block();
duke@1 1703 }
duke@1 1704 } else {
duke@1 1705 log.error(pos, "try.without.catch.or.finally");
duke@1 1706 }
duke@1 1707 return F.at(pos).Try(body, catchers.toList(), finalizer);
duke@1 1708 }
duke@1 1709 case SWITCH: {
duke@1 1710 S.nextToken();
duke@1 1711 JCExpression selector = parExpression();
duke@1 1712 accept(LBRACE);
duke@1 1713 List<JCCase> cases = switchBlockStatementGroups();
duke@1 1714 JCSwitch t = to(F.at(pos).Switch(selector, cases));
duke@1 1715 accept(RBRACE);
duke@1 1716 return t;
duke@1 1717 }
duke@1 1718 case SYNCHRONIZED: {
duke@1 1719 S.nextToken();
duke@1 1720 JCExpression lock = parExpression();
duke@1 1721 JCBlock body = block();
duke@1 1722 return F.at(pos).Synchronized(lock, body);
duke@1 1723 }
duke@1 1724 case RETURN: {
duke@1 1725 S.nextToken();
duke@1 1726 JCExpression result = S.token() == SEMI ? null : expression();
duke@1 1727 JCReturn t = to(F.at(pos).Return(result));
duke@1 1728 accept(SEMI);
duke@1 1729 return t;
duke@1 1730 }
duke@1 1731 case THROW: {
duke@1 1732 S.nextToken();
duke@1 1733 JCExpression exc = expression();
duke@1 1734 JCThrow t = to(F.at(pos).Throw(exc));
duke@1 1735 accept(SEMI);
duke@1 1736 return t;
duke@1 1737 }
duke@1 1738 case BREAK: {
duke@1 1739 S.nextToken();
duke@1 1740 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
duke@1 1741 JCBreak t = to(F.at(pos).Break(label));
duke@1 1742 accept(SEMI);
duke@1 1743 return t;
duke@1 1744 }
duke@1 1745 case CONTINUE: {
duke@1 1746 S.nextToken();
duke@1 1747 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
duke@1 1748 JCContinue t = to(F.at(pos).Continue(label));
duke@1 1749 accept(SEMI);
duke@1 1750 return t;
duke@1 1751 }
duke@1 1752 case SEMI:
duke@1 1753 S.nextToken();
duke@1 1754 return toP(F.at(pos).Skip());
duke@1 1755 case ELSE:
duke@1 1756 return toP(F.Exec(syntaxError("else.without.if")));
duke@1 1757 case FINALLY:
duke@1 1758 return toP(F.Exec(syntaxError("finally.without.try")));
duke@1 1759 case CATCH:
duke@1 1760 return toP(F.Exec(syntaxError("catch.without.try")));
duke@1 1761 case ASSERT: {
duke@1 1762 if (allowAsserts && S.token() == ASSERT) {
duke@1 1763 S.nextToken();
duke@1 1764 JCExpression assertion = expression();
duke@1 1765 JCExpression message = null;
duke@1 1766 if (S.token() == COLON) {
duke@1 1767 S.nextToken();
duke@1 1768 message = expression();
duke@1 1769 }
duke@1 1770 JCAssert t = to(F.at(pos).Assert(assertion, message));
duke@1 1771 accept(SEMI);
duke@1 1772 return t;
duke@1 1773 }
duke@1 1774 /* else fall through to default case */
duke@1 1775 }
duke@1 1776 case ENUM:
duke@1 1777 default:
duke@1 1778 Name name = S.name();
duke@1 1779 JCExpression expr = expression();
duke@1 1780 if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
duke@1 1781 S.nextToken();
duke@1 1782 JCStatement stat = statement();
duke@1 1783 return F.at(pos).Labelled(name, stat);
duke@1 1784 } else {
duke@1 1785 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
duke@1 1786 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
duke@1 1787 accept(SEMI);
duke@1 1788 return stat;
duke@1 1789 }
duke@1 1790 }
duke@1 1791 }
duke@1 1792
duke@1 1793 /** CatchClause = CATCH "(" FormalParameter ")" Block
duke@1 1794 */
duke@1 1795 JCCatch catchClause() {
duke@1 1796 int pos = S.pos();
duke@1 1797 accept(CATCH);
duke@1 1798 accept(LPAREN);
duke@1 1799 JCVariableDecl formal =
duke@1 1800 variableDeclaratorId(optFinal(Flags.PARAMETER),
duke@1 1801 qualident());
duke@1 1802 accept(RPAREN);
duke@1 1803 JCBlock body = block();
duke@1 1804 return F.at(pos).Catch(formal, body);
duke@1 1805 }
duke@1 1806
duke@1 1807 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
duke@1 1808 * SwitchBlockStatementGroup = SwitchLabel BlockStatements
duke@1 1809 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
duke@1 1810 */
duke@1 1811 List<JCCase> switchBlockStatementGroups() {
duke@1 1812 ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
duke@1 1813 while (true) {
duke@1 1814 int pos = S.pos();
duke@1 1815 switch (S.token()) {
duke@1 1816 case CASE: {
duke@1 1817 S.nextToken();
duke@1 1818 JCExpression pat = expression();
duke@1 1819 accept(COLON);
duke@1 1820 List<JCStatement> stats = blockStatements();
duke@1 1821 JCCase c = F.at(pos).Case(pat, stats);
duke@1 1822 if (stats.isEmpty())
duke@1 1823 storeEnd(c, S.prevEndPos());
duke@1 1824 cases.append(c);
duke@1 1825 break;
duke@1 1826 }
duke@1 1827 case DEFAULT: {
duke@1 1828 S.nextToken();
duke@1 1829 accept(COLON);
duke@1 1830 List<JCStatement> stats = blockStatements();
duke@1 1831 JCCase c = F.at(pos).Case(null, stats);
duke@1 1832 if (stats.isEmpty())
duke@1 1833 storeEnd(c, S.prevEndPos());
duke@1 1834 cases.append(c);
duke@1 1835 break;
duke@1 1836 }
duke@1 1837 case RBRACE: case EOF:
duke@1 1838 return cases.toList();
duke@1 1839 default:
duke@1 1840 S.nextToken(); // to ensure progress
duke@1 1841 syntaxError(pos, "expected3",
duke@1 1842 keywords.token2string(CASE),
duke@1 1843 keywords.token2string(DEFAULT),
duke@1 1844 keywords.token2string(RBRACE));
duke@1 1845 }
duke@1 1846 }
duke@1 1847 }
duke@1 1848
duke@1 1849 /** MoreStatementExpressions = { COMMA StatementExpression }
duke@1 1850 */
duke@1 1851 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
duke@1 1852 JCExpression first,
duke@1 1853 T stats) {
duke@1 1854 // This Exec is a "StatementExpression"; it subsumes no terminating token
duke@1 1855 stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
duke@1 1856 while (S.token() == COMMA) {
duke@1 1857 S.nextToken();
duke@1 1858 pos = S.pos();
duke@1 1859 JCExpression t = expression();
duke@1 1860 // This Exec is a "StatementExpression"; it subsumes no terminating token
duke@1 1861 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
duke@1 1862 }
duke@1 1863 return stats;
duke@1 1864 }
duke@1 1865
duke@1 1866 /** ForInit = StatementExpression MoreStatementExpressions
duke@1 1867 * | { FINAL | '@' Annotation } Type VariableDeclarators
duke@1 1868 */
duke@1 1869 List<JCStatement> forInit() {
duke@1 1870 ListBuffer<JCStatement> stats = lb();
duke@1 1871 int pos = S.pos();
duke@1 1872 if (S.token() == FINAL || S.token() == MONKEYS_AT) {
duke@1 1873 return variableDeclarators(optFinal(0), type(), stats).toList();
duke@1 1874 } else {
duke@1 1875 JCExpression t = term(EXPR | TYPE);
duke@1 1876 if ((lastmode & TYPE) != 0 &&
duke@1 1877 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
duke@1 1878 return variableDeclarators(modifiersOpt(), t, stats).toList();
duke@1 1879 else
duke@1 1880 return moreStatementExpressions(pos, t, stats).toList();
duke@1 1881 }
duke@1 1882 }
duke@1 1883
duke@1 1884 /** ForUpdate = StatementExpression MoreStatementExpressions
duke@1 1885 */
duke@1 1886 List<JCExpressionStatement> forUpdate() {
duke@1 1887 return moreStatementExpressions(S.pos(),
duke@1 1888 expression(),
duke@1 1889 new ListBuffer<JCExpressionStatement>()).toList();
duke@1 1890 }
duke@1 1891
duke@1 1892 /** AnnotationsOpt = { '@' Annotation }
duke@1 1893 */
duke@1 1894 List<JCAnnotation> annotationsOpt() {
duke@1 1895 if (S.token() != MONKEYS_AT) return List.nil(); // optimization
duke@1 1896 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
duke@1 1897 while (S.token() == MONKEYS_AT) {
duke@1 1898 int pos = S.pos();
duke@1 1899 S.nextToken();
duke@1 1900 buf.append(annotation(pos));
duke@1 1901 }
duke@1 1902 return buf.toList();
duke@1 1903 }
duke@1 1904
duke@1 1905 /** ModifiersOpt = { Modifier }
duke@1 1906 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
duke@1 1907 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
duke@1 1908 * | "@" Annotation
duke@1 1909 */
duke@1 1910 JCModifiers modifiersOpt() {
duke@1 1911 return modifiersOpt(null);
duke@1 1912 }
duke@1 1913 JCModifiers modifiersOpt(JCModifiers partial) {
duke@1 1914 long flags = (partial == null) ? 0 : partial.flags;
duke@1 1915 if (S.deprecatedFlag()) {
duke@1 1916 flags |= Flags.DEPRECATED;
duke@1 1917 S.resetDeprecatedFlag();
duke@1 1918 }
duke@1 1919 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
duke@1 1920 if (partial != null) annotations.appendList(partial.annotations);
duke@1 1921 int pos = S.pos();
duke@1 1922 int lastPos = Position.NOPOS;
duke@1 1923 loop:
duke@1 1924 while (true) {
duke@1 1925 long flag;
duke@1 1926 switch (S.token()) {
duke@1 1927 case PRIVATE : flag = Flags.PRIVATE; break;
duke@1 1928 case PROTECTED : flag = Flags.PROTECTED; break;
duke@1 1929 case PUBLIC : flag = Flags.PUBLIC; break;
duke@1 1930 case STATIC : flag = Flags.STATIC; break;
duke@1 1931 case TRANSIENT : flag = Flags.TRANSIENT; break;
duke@1 1932 case FINAL : flag = Flags.FINAL; break;
duke@1 1933 case ABSTRACT : flag = Flags.ABSTRACT; break;
duke@1 1934 case NATIVE : flag = Flags.NATIVE; break;
duke@1 1935 case VOLATILE : flag = Flags.VOLATILE; break;
duke@1 1936 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
duke@1 1937 case STRICTFP : flag = Flags.STRICTFP; break;
duke@1 1938 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
duke@1 1939 default: break loop;
duke@1 1940 }
duke@1 1941 if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
duke@1 1942 lastPos = S.pos();
duke@1 1943 S.nextToken();
duke@1 1944 if (flag == Flags.ANNOTATION) {
duke@1 1945 checkAnnotations();
duke@1 1946 if (S.token() != INTERFACE) {
duke@1 1947 JCAnnotation ann = annotation(lastPos);
duke@1 1948 // if first modifier is an annotation, set pos to annotation's.
duke@1 1949 if (flags == 0 && annotations.isEmpty())
duke@1 1950 pos = ann.pos;
duke@1 1951 annotations.append(ann);
duke@1 1952 lastPos = ann.pos;
duke@1 1953 flag = 0;
duke@1 1954 }
duke@1 1955 }
duke@1 1956 flags |= flag;
duke@1 1957 }
duke@1 1958 switch (S.token()) {
duke@1 1959 case ENUM: flags |= Flags.ENUM; break;
duke@1 1960 case INTERFACE: flags |= Flags.INTERFACE; break;
duke@1 1961 default: break;
duke@1 1962 }
duke@1 1963
duke@1 1964 /* A modifiers tree with no modifier tokens or annotations
duke@1 1965 * has no text position. */
duke@1 1966 if (flags == 0 && annotations.isEmpty())
duke@1 1967 pos = Position.NOPOS;
duke@1 1968
duke@1 1969 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
duke@1 1970 if (pos != Position.NOPOS)
duke@1 1971 storeEnd(mods, S.prevEndPos());
duke@1 1972 return mods;
duke@1 1973 }
duke@1 1974
duke@1 1975 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
duke@1 1976 * @param pos position of "@" token
duke@1 1977 */
duke@1 1978 JCAnnotation annotation(int pos) {
duke@1 1979 // accept(AT); // AT consumed by caller
duke@1 1980 checkAnnotations();
duke@1 1981 JCTree ident = qualident();
duke@1 1982 List<JCExpression> fieldValues = annotationFieldValuesOpt();
duke@1 1983 JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
duke@1 1984 storeEnd(ann, S.prevEndPos());
duke@1 1985 return ann;
duke@1 1986 }
duke@1 1987
duke@1 1988 List<JCExpression> annotationFieldValuesOpt() {
duke@1 1989 return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
duke@1 1990 }
duke@1 1991
duke@1 1992 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
duke@1 1993 List<JCExpression> annotationFieldValues() {
duke@1 1994 accept(LPAREN);
duke@1 1995 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
duke@1 1996 if (S.token() != RPAREN) {
duke@1 1997 buf.append(annotationFieldValue());
duke@1 1998 while (S.token() == COMMA) {
duke@1 1999 S.nextToken();
duke@1 2000 buf.append(annotationFieldValue());
duke@1 2001 }
duke@1 2002 }
duke@1 2003 accept(RPAREN);
duke@1 2004 return buf.toList();
duke@1 2005 }
duke@1 2006
duke@1 2007 /** AnnotationFieldValue = AnnotationValue
duke@1 2008 * | Identifier "=" AnnotationValue
duke@1 2009 */
duke@1 2010 JCExpression annotationFieldValue() {
duke@1 2011 if (S.token() == IDENTIFIER) {
duke@1 2012 mode = EXPR;
duke@1 2013 JCExpression t1 = term1();
duke@1 2014 if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
duke@1 2015 int pos = S.pos();
duke@1 2016 accept(EQ);
duke@1 2017 return toP(F.at(pos).Assign(t1, annotationValue()));
duke@1 2018 } else {
duke@1 2019 return t1;
duke@1 2020 }
duke@1 2021 }
duke@1 2022 return annotationValue();
duke@1 2023 }
duke@1 2024
duke@1 2025 /* AnnotationValue = ConditionalExpression
duke@1 2026 * | Annotation
duke@1 2027 * | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
duke@1 2028 */
duke@1 2029 JCExpression annotationValue() {
duke@1 2030 int pos;
duke@1 2031 switch (S.token()) {
duke@1 2032 case MONKEYS_AT:
duke@1 2033 pos = S.pos();
duke@1 2034 S.nextToken();
duke@1 2035 return annotation(pos);
duke@1 2036 case LBRACE:
duke@1 2037 pos = S.pos();
duke@1 2038 accept(LBRACE);
duke@1 2039 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
duke@1 2040 if (S.token() != RBRACE) {
duke@1 2041 buf.append(annotationValue());
duke@1 2042 while (S.token() == COMMA) {
duke@1 2043 S.nextToken();
duke@1 2044 if (S.token() == RPAREN) break;
duke@1 2045 buf.append(annotationValue());
duke@1 2046 }
duke@1 2047 }
duke@1 2048 accept(RBRACE);
duke@1 2049 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
duke@1 2050 default:
duke@1 2051 mode = EXPR;
duke@1 2052 return term1();
duke@1 2053 }
duke@1 2054 }
duke@1 2055
duke@1 2056 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
duke@1 2057 */
duke@1 2058 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
duke@1 2059 JCExpression type,
duke@1 2060 T vdefs)
duke@1 2061 {
duke@1 2062 return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
duke@1 2063 }
duke@1 2064
duke@1 2065 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
duke@1 2066 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
duke@1 2067 *
duke@1 2068 * @param reqInit Is an initializer always required?
duke@1 2069 * @param dc The documentation comment for the variable declarations, or null.
duke@1 2070 */
duke@1 2071 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
duke@1 2072 JCModifiers mods,
duke@1 2073 JCExpression type,
duke@1 2074 Name name,
duke@1 2075 boolean reqInit,
duke@1 2076 String dc,
duke@1 2077 T vdefs)
duke@1 2078 {
duke@1 2079 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
duke@1 2080 while (S.token() == COMMA) {
duke@1 2081 // All but last of multiple declarators subsume a comma
duke@1 2082 storeEnd((JCTree)vdefs.elems.last(), S.endPos());
duke@1 2083 S.nextToken();
duke@1 2084 vdefs.append(variableDeclarator(mods, type, reqInit, dc));
duke@1 2085 }
duke@1 2086 return vdefs;
duke@1 2087 }
duke@1 2088
duke@1 2089 /** VariableDeclarator = Ident VariableDeclaratorRest
duke@1 2090 * ConstantDeclarator = Ident ConstantDeclaratorRest
duke@1 2091 */
duke@1 2092 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
duke@1 2093 return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
duke@1 2094 }
duke@1 2095
duke@1 2096 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
duke@1 2097 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
duke@1 2098 *
duke@1 2099 * @param reqInit Is an initializer always required?
duke@1 2100 * @param dc The documentation comment for the variable declarations, or null.
duke@1 2101 */
duke@1 2102 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
duke@1 2103 boolean reqInit, String dc) {
duke@1 2104 type = bracketsOpt(type);
duke@1 2105 JCExpression init = null;
duke@1 2106 if (S.token() == EQ) {
duke@1 2107 S.nextToken();
duke@1 2108 init = variableInitializer();
duke@1 2109 }
duke@1 2110 else if (reqInit) syntaxError(S.pos(), "expected", keywords.token2string(EQ));
duke@1 2111 JCVariableDecl result =
duke@1 2112 toP(F.at(pos).VarDef(mods, name, type, init));
duke@1 2113 attach(result, dc);
duke@1 2114 return result;
duke@1 2115 }
duke@1 2116
duke@1 2117 /** VariableDeclaratorId = Ident BracketsOpt
duke@1 2118 */
duke@1 2119 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
duke@1 2120 int pos = S.pos();
duke@1 2121 Name name = ident();
duke@1 2122 if ((mods.flags & Flags.VARARGS) == 0)
duke@1 2123 type = bracketsOpt(type);
duke@1 2124 return toP(F.at(pos).VarDef(mods, name, type, null));
duke@1 2125 }
duke@1 2126
duke@1 2127 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
duke@1 2128 */
duke@1 2129 public JCTree.JCCompilationUnit compilationUnit() {
duke@1 2130 int pos = S.pos();
duke@1 2131 JCExpression pid = null;
duke@1 2132 String dc = S.docComment();
duke@1 2133 JCModifiers mods = null;
duke@1 2134 List<JCAnnotation> packageAnnotations = List.nil();
duke@1 2135 if (S.token() == MONKEYS_AT)
duke@1 2136 mods = modifiersOpt();
duke@1 2137
duke@1 2138 if (S.token() == PACKAGE) {
duke@1 2139 if (mods != null) {
duke@1 2140 checkNoMods(mods.flags);
duke@1 2141 packageAnnotations = mods.annotations;
duke@1 2142 mods = null;
duke@1 2143 }
duke@1 2144 S.nextToken();
duke@1 2145 pid = qualident();
duke@1 2146 accept(SEMI);
duke@1 2147 }
duke@1 2148 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
duke@1 2149 boolean checkForImports = true;
duke@1 2150 while (S.token() != EOF) {
duke@1 2151 if (S.pos() <= errorEndPos) {
duke@1 2152 // error recovery
duke@1 2153 skip(checkForImports, false, false, false);
duke@1 2154 if (S.token() == EOF)
duke@1 2155 break;
duke@1 2156 }
duke@1 2157 if (checkForImports && mods == null && S.token() == IMPORT) {
duke@1 2158 defs.append(importDeclaration());
duke@1 2159 } else {
duke@1 2160 JCTree def = typeDeclaration(mods);
duke@1 2161 if (def instanceof JCExpressionStatement)
duke@1 2162 def = ((JCExpressionStatement)def).expr;
duke@1 2163 defs.append(def);
duke@1 2164 if (def instanceof JCClassDecl)
duke@1 2165 checkForImports = false;
duke@1 2166 mods = null;
duke@1 2167 }
duke@1 2168 }
duke@1 2169 JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
duke@1 2170 attach(toplevel, dc);
duke@1 2171 if (defs.elems.isEmpty())
duke@1 2172 storeEnd(toplevel, S.prevEndPos());
duke@1 2173 if (keepDocComments) toplevel.docComments = docComments;
duke@1 2174 return toplevel;
duke@1 2175 }
duke@1 2176
duke@1 2177 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
duke@1 2178 */
duke@1 2179 JCTree importDeclaration() {
duke@1 2180 int pos = S.pos();
duke@1 2181 S.nextToken();
duke@1 2182 boolean importStatic = false;
duke@1 2183 if (S.token() == STATIC) {
duke@1 2184 checkStaticImports();
duke@1 2185 importStatic = true;
duke@1 2186 S.nextToken();
duke@1 2187 }
duke@1 2188 JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
duke@1 2189 do {
duke@1 2190 int pos1 = S.pos();
duke@1 2191 accept(DOT);
duke@1 2192 if (S.token() == STAR) {
duke@1 2193 pid = to(F.at(pos1).Select(pid, names.asterisk));
duke@1 2194 S.nextToken();
duke@1 2195 break;
duke@1 2196 } else {
duke@1 2197 pid = toP(F.at(pos1).Select(pid, ident()));
duke@1 2198 }
duke@1 2199 } while (S.token() == DOT);
duke@1 2200 accept(SEMI);
duke@1 2201 return toP(F.at(pos).Import(pid, importStatic));
duke@1 2202 }
duke@1 2203
duke@1 2204 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
duke@1 2205 * | ";"
duke@1 2206 */
duke@1 2207 JCTree typeDeclaration(JCModifiers mods) {
duke@1 2208 int pos = S.pos();
duke@1 2209 if (mods == null && S.token() == SEMI) {
duke@1 2210 S.nextToken();
duke@1 2211 return toP(F.at(pos).Skip());
duke@1 2212 } else {
duke@1 2213 String dc = S.docComment();
duke@1 2214 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
duke@1 2215 }
duke@1 2216 }
duke@1 2217
duke@1 2218 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
duke@1 2219 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
duke@1 2220 * @param mods Any modifiers starting the class or interface declaration
duke@1 2221 * @param dc The documentation comment for the class, or null.
duke@1 2222 */
duke@1 2223 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
duke@1 2224 if (S.token() == CLASS) {
duke@1 2225 return classDeclaration(mods, dc);
duke@1 2226 } else if (S.token() == INTERFACE) {
duke@1 2227 return interfaceDeclaration(mods, dc);
duke@1 2228 } else if (allowEnums) {
duke@1 2229 if (S.token() == ENUM) {
duke@1 2230 return enumDeclaration(mods, dc);
duke@1 2231 } else {
duke@1 2232 int pos = S.pos();
duke@1 2233 List<JCTree> errs;
duke@1 2234 if (S.token() == IDENTIFIER) {
duke@1 2235 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
duke@1 2236 setErrorEndPos(S.pos());
duke@1 2237 } else {
duke@1 2238 errs = List.<JCTree>of(mods);
duke@1 2239 }
duke@1 2240 return toP(F.Exec(syntaxError(pos, errs, "expected3",
duke@1 2241 keywords.token2string(CLASS),
duke@1 2242 keywords.token2string(INTERFACE),
duke@1 2243 keywords.token2string(ENUM))));
duke@1 2244 }
duke@1 2245 } else {
duke@1 2246 if (S.token() == ENUM) {
duke@1 2247 log.error(S.pos(), "enums.not.supported.in.source", source.name);
duke@1 2248 allowEnums = true;
duke@1 2249 return enumDeclaration(mods, dc);
duke@1 2250 }
duke@1 2251 int pos = S.pos();
duke@1 2252 List<JCTree> errs;
duke@1 2253 if (S.token() == IDENTIFIER) {
duke@1 2254 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
duke@1 2255 setErrorEndPos(S.pos());
duke@1 2256 } else {
duke@1 2257 errs = List.<JCTree>of(mods);
duke@1 2258 }
duke@1 2259 return toP(F.Exec(syntaxError(pos, errs, "expected2",
duke@1 2260 keywords.token2string(CLASS),
duke@1 2261 keywords.token2string(INTERFACE))));
duke@1 2262 }
duke@1 2263 }
duke@1 2264
duke@1 2265 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
duke@1 2266 * [IMPLEMENTS TypeList] ClassBody
duke@1 2267 * @param mods The modifiers starting the class declaration
duke@1 2268 * @param dc The documentation comment for the class, or null.
duke@1 2269 */
duke@1 2270 JCClassDecl classDeclaration(JCModifiers mods, String dc) {
duke@1 2271 int pos = S.pos();
duke@1 2272 accept(CLASS);
duke@1 2273 Name name = ident();
duke@1 2274
duke@1 2275 List<JCTypeParameter> typarams = typeParametersOpt();
duke@1 2276
duke@1 2277 JCTree extending = null;
duke@1 2278 if (S.token() == EXTENDS) {
duke@1 2279 S.nextToken();
duke@1 2280 extending = type();
duke@1 2281 }
duke@1 2282 List<JCExpression> implementing = List.nil();
duke@1 2283 if (S.token() == IMPLEMENTS) {
duke@1 2284 S.nextToken();
duke@1 2285 implementing = typeList();
duke@1 2286 }
duke@1 2287 List<JCTree> defs = classOrInterfaceBody(name, false);
duke@1 2288 JCClassDecl result = toP(F.at(pos).ClassDef(
duke@1 2289 mods, name, typarams, extending, implementing, defs));
duke@1 2290 attach(result, dc);
duke@1 2291 return result;
duke@1 2292 }
duke@1 2293
duke@1 2294 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
duke@1 2295 * [EXTENDS TypeList] InterfaceBody
duke@1 2296 * @param mods The modifiers starting the interface declaration
duke@1 2297 * @param dc The documentation comment for the interface, or null.
duke@1 2298 */
duke@1 2299 JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
duke@1 2300 int pos = S.pos();
duke@1 2301 accept(INTERFACE);
duke@1 2302 Name name = ident();
duke@1 2303
duke@1 2304 List<JCTypeParameter> typarams = typeParametersOpt();
duke@1 2305
duke@1 2306 List<JCExpression> extending = List.nil();
duke@1 2307 if (S.token() == EXTENDS) {
duke@1 2308 S.nextToken();
duke@1 2309 extending = typeList();
duke@1 2310 }
duke@1 2311 List<JCTree> defs = classOrInterfaceBody(name, true);
duke@1 2312 JCClassDecl result = toP(F.at(pos).ClassDef(
duke@1 2313 mods, name, typarams, null, extending, defs));
duke@1 2314 attach(result, dc);
duke@1 2315 return result;
duke@1 2316 }
duke@1 2317
duke@1 2318 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
duke@1 2319 * @param mods The modifiers starting the enum declaration
duke@1 2320 * @param dc The documentation comment for the enum, or null.
duke@1 2321 */
duke@1 2322 JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
duke@1 2323 int pos = S.pos();
duke@1 2324 accept(ENUM);
duke@1 2325 Name name = ident();
duke@1 2326
duke@1 2327 List<JCExpression> implementing = List.nil();
duke@1 2328 if (S.token() == IMPLEMENTS) {
duke@1 2329 S.nextToken();
duke@1 2330 implementing = typeList();
duke@1 2331 }
duke@1 2332
duke@1 2333 List<JCTree> defs = enumBody(name);
duke@1 2334 JCModifiers newMods =
duke@1 2335 F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
duke@1 2336 JCClassDecl result = toP(F.at(pos).
duke@1 2337 ClassDef(newMods, name, List.<JCTypeParameter>nil(),
duke@1 2338 null, implementing, defs));
duke@1 2339 attach(result, dc);
duke@1 2340 return result;
duke@1 2341 }
duke@1 2342
duke@1 2343 /** EnumBody = "{" { EnumeratorDeclarationList } [","]
duke@1 2344 * [ ";" {ClassBodyDeclaration} ] "}"
duke@1 2345 */
duke@1 2346 List<JCTree> enumBody(Name enumName) {
duke@1 2347 accept(LBRACE);
duke@1 2348 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
duke@1 2349 if (S.token() == COMMA) {
duke@1 2350 S.nextToken();
duke@1 2351 } else if (S.token() != RBRACE && S.token() != SEMI) {
duke@1 2352 defs.append(enumeratorDeclaration(enumName));
duke@1 2353 while (S.token() == COMMA) {
duke@1 2354 S.nextToken();
duke@1 2355 if (S.token() == RBRACE || S.token() == SEMI) break;
duke@1 2356 defs.append(enumeratorDeclaration(enumName));
duke@1 2357 }
duke@1 2358 if (S.token() != SEMI && S.token() != RBRACE) {
duke@1 2359 defs.append(syntaxError(S.pos(), "expected3",
duke@1 2360 keywords.token2string(COMMA),
duke@1 2361 keywords.token2string(RBRACE),
duke@1 2362 keywords.token2string(SEMI)));
duke@1 2363 S.nextToken();
duke@1 2364 }
duke@1 2365 }
duke@1 2366 if (S.token() == SEMI) {
duke@1 2367 S.nextToken();
duke@1 2368 while (S.token() != RBRACE && S.token() != EOF) {
duke@1 2369 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
duke@1 2370 false));
duke@1 2371 if (S.pos() <= errorEndPos) {
duke@1 2372 // error recovery
duke@1 2373 skip(false, true, true, false);
duke@1 2374 }
duke@1 2375 }
duke@1 2376 }
duke@1 2377 accept(RBRACE);
duke@1 2378 return defs.toList();
duke@1 2379 }
duke@1 2380
duke@1 2381 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
duke@1 2382 */
duke@1 2383 JCTree enumeratorDeclaration(Name enumName) {
duke@1 2384 String dc = S.docComment();
duke@1 2385 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
duke@1 2386 if (S.deprecatedFlag()) {
duke@1 2387 flags |= Flags.DEPRECATED;
duke@1 2388 S.resetDeprecatedFlag();
duke@1 2389 }
duke@1 2390 int pos = S.pos();
duke@1 2391 List<JCAnnotation> annotations = annotationsOpt();
duke@1 2392 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
duke@1 2393 List<JCExpression> typeArgs = typeArgumentsOpt();
duke@1 2394 int identPos = S.pos();
duke@1 2395 Name name = ident();
duke@1 2396 int createPos = S.pos();
duke@1 2397 List<JCExpression> args = (S.token() == LPAREN)
duke@1 2398 ? arguments() : List.<JCExpression>nil();
duke@1 2399 JCClassDecl body = null;
duke@1 2400 if (S.token() == LBRACE) {
duke@1 2401 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
duke@1 2402 List<JCTree> defs = classOrInterfaceBody(names.empty, false);
duke@1 2403 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
duke@1 2404 }
duke@1 2405 if (args.isEmpty() && body == null)
duke@1 2406 createPos = Position.NOPOS;
duke@1 2407 JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
duke@1 2408 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
duke@1 2409 if (createPos != Position.NOPOS)
duke@1 2410 storeEnd(create, S.prevEndPos());
duke@1 2411 ident = F.at(Position.NOPOS).Ident(enumName);
duke@1 2412 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
duke@1 2413 attach(result, dc);
duke@1 2414 return result;
duke@1 2415 }
duke@1 2416
duke@1 2417 /** TypeList = Type {"," Type}
duke@1 2418 */
duke@1 2419 List<JCExpression> typeList() {
duke@1 2420 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
duke@1 2421 ts.append(type());
duke@1 2422 while (S.token() == COMMA) {
duke@1 2423 S.nextToken();
duke@1 2424 ts.append(type());
duke@1 2425 }
duke@1 2426 return ts.toList();
duke@1 2427 }
duke@1 2428
duke@1 2429 /** ClassBody = "{" {ClassBodyDeclaration} "}"
duke@1 2430 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
duke@1 2431 */
duke@1 2432 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
duke@1 2433 accept(LBRACE);
duke@1 2434 if (S.pos() <= errorEndPos) {
duke@1 2435 // error recovery
duke@1 2436 skip(false, true, false, false);
duke@1 2437 if (S.token() == LBRACE)
duke@1 2438 S.nextToken();
duke@1 2439 }
duke@1 2440 ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
duke@1 2441 while (S.token() != RBRACE && S.token() != EOF) {
duke@1 2442 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
duke@1 2443 if (S.pos() <= errorEndPos) {
duke@1 2444 // error recovery
duke@1 2445 skip(false, true, true, false);
duke@1 2446 }
duke@1 2447 }
duke@1 2448 accept(RBRACE);
duke@1 2449 return defs.toList();
duke@1 2450 }
duke@1 2451
duke@1 2452 /** ClassBodyDeclaration =
duke@1 2453 * ";"
duke@1 2454 * | [STATIC] Block
duke@1 2455 * | ModifiersOpt
duke@1 2456 * ( Type Ident
duke@1 2457 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
duke@1 2458 * | VOID Ident MethodDeclaratorRest
duke@1 2459 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
duke@1 2460 * | Ident ConstructorDeclaratorRest
duke@1 2461 * | TypeParameters Ident ConstructorDeclaratorRest
duke@1 2462 * | ClassOrInterfaceOrEnumDeclaration
duke@1 2463 * )
duke@1 2464 * InterfaceBodyDeclaration =
duke@1 2465 * ";"
duke@1 2466 * | ModifiersOpt Type Ident
duke@1 2467 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
duke@1 2468 */
duke@1 2469 List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
duke@1 2470 if (S.token() == SEMI) {
duke@1 2471 S.nextToken();
duke@1 2472 return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
duke@1 2473 } else {
duke@1 2474 String dc = S.docComment();
duke@1 2475 int pos = S.pos();
duke@1 2476 JCModifiers mods = modifiersOpt();
duke@1 2477 if (S.token() == CLASS ||
duke@1 2478 S.token() == INTERFACE ||
duke@1 2479 allowEnums && S.token() == ENUM) {
duke@1 2480 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
duke@1 2481 } else if (S.token() == LBRACE && !isInterface &&
duke@1 2482 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
duke@1 2483 mods.annotations.isEmpty()) {
duke@1 2484 return List.<JCTree>of(block(pos, mods.flags));
duke@1 2485 } else {
duke@1 2486 pos = S.pos();
duke@1 2487 List<JCTypeParameter> typarams = typeParametersOpt();
duke@1 2488 // Hack alert: if there are type arguments but no Modifiers, the start
duke@1 2489 // position will be lost unless we set the Modifiers position. There
duke@1 2490 // should be an AST node for type parameters (BugId 5005090).
duke@1 2491 if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
duke@1 2492 mods.pos = pos;
duke@1 2493 }
duke@1 2494 Token token = S.token();
duke@1 2495 Name name = S.name();
duke@1 2496 pos = S.pos();
duke@1 2497 JCExpression type;
duke@1 2498 boolean isVoid = S.token() == VOID;
duke@1 2499 if (isVoid) {
duke@1 2500 type = to(F.at(pos).TypeIdent(TypeTags.VOID));
duke@1 2501 S.nextToken();
duke@1 2502 } else {
duke@1 2503 type = type();
duke@1 2504 }
duke@1 2505 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
duke@1 2506 if (isInterface || name != className)
duke@1 2507 log.error(pos, "invalid.meth.decl.ret.type.req");
duke@1 2508 return List.of(methodDeclaratorRest(
duke@1 2509 pos, mods, null, names.init, typarams,
duke@1 2510 isInterface, true, dc));
duke@1 2511 } else {
duke@1 2512 pos = S.pos();
duke@1 2513 name = ident();
duke@1 2514 if (S.token() == LPAREN) {
duke@1 2515 return List.of(methodDeclaratorRest(
duke@1 2516 pos, mods, type, name, typarams,
duke@1 2517 isInterface, isVoid, dc));
duke@1 2518 } else if (!isVoid && typarams.isEmpty()) {
duke@1 2519 List<JCTree> defs =
duke@1 2520 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
duke@1 2521 new ListBuffer<JCTree>()).toList();
duke@1 2522 storeEnd(defs.last(), S.endPos());
duke@1 2523 accept(SEMI);
duke@1 2524 return defs;
duke@1 2525 } else {
duke@1 2526 pos = S.pos();
duke@1 2527 List<JCTree> err = isVoid
duke@1 2528 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
duke@1 2529 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
duke@1 2530 : null;
duke@1 2531 return List.<JCTree>of(syntaxError(S.pos(), err, "expected", keywords.token2string(LPAREN)));
duke@1 2532 }
duke@1 2533 }
duke@1 2534 }
duke@1 2535 }
duke@1 2536 }
duke@1 2537
duke@1 2538 /** MethodDeclaratorRest =
duke@1 2539 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
duke@1 2540 * VoidMethodDeclaratorRest =
duke@1 2541 * FormalParameters [Throws TypeList] ( MethodBody | ";")
duke@1 2542 * InterfaceMethodDeclaratorRest =
duke@1 2543 * FormalParameters BracketsOpt [THROWS TypeList] ";"
duke@1 2544 * VoidInterfaceMethodDeclaratorRest =
duke@1 2545 * FormalParameters [THROWS TypeList] ";"
duke@1 2546 * ConstructorDeclaratorRest =
duke@1 2547 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
duke@1 2548 */
duke@1 2549 JCTree methodDeclaratorRest(int pos,
duke@1 2550 JCModifiers mods,
duke@1 2551 JCExpression type,
duke@1 2552 Name name,
duke@1 2553 List<JCTypeParameter> typarams,
duke@1 2554 boolean isInterface, boolean isVoid,
duke@1 2555 String dc) {
duke@1 2556 List<JCVariableDecl> params = formalParameters();
duke@1 2557 if (!isVoid) type = bracketsOpt(type);
duke@1 2558 List<JCExpression> thrown = List.nil();
duke@1 2559 if (S.token() == THROWS) {
duke@1 2560 S.nextToken();
duke@1 2561 thrown = qualidentList();
duke@1 2562 }
duke@1 2563 JCBlock body = null;
duke@1 2564 JCExpression defaultValue;
duke@1 2565 if (S.token() == LBRACE) {
duke@1 2566 body = block();
duke@1 2567 defaultValue = null;
duke@1 2568 } else {
duke@1 2569 if (S.token() == DEFAULT) {
duke@1 2570 accept(DEFAULT);
duke@1 2571 defaultValue = annotationValue();
duke@1 2572 } else {
duke@1 2573 defaultValue = null;
duke@1 2574 }
duke@1 2575 accept(SEMI);
duke@1 2576 if (S.pos() <= errorEndPos) {
duke@1 2577 // error recovery
duke@1 2578 skip(false, true, false, false);
duke@1 2579 if (S.token() == LBRACE) {
duke@1 2580 body = block();
duke@1 2581 }
duke@1 2582 }
duke@1 2583 }
duke@1 2584 JCMethodDecl result =
duke@1 2585 toP(F.at(pos).MethodDef(mods, name, type, typarams,
duke@1 2586 params, thrown,
duke@1 2587 body, defaultValue));
duke@1 2588 attach(result, dc);
duke@1 2589 return result;
duke@1 2590 }
duke@1 2591
duke@1 2592 /** QualidentList = Qualident {"," Qualident}
duke@1 2593 */
duke@1 2594 List<JCExpression> qualidentList() {
duke@1 2595 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
duke@1 2596 ts.append(qualident());
duke@1 2597 while (S.token() == COMMA) {
duke@1 2598 S.nextToken();
duke@1 2599 ts.append(qualident());
duke@1 2600 }
duke@1 2601 return ts.toList();
duke@1 2602 }
duke@1 2603
duke@1 2604 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
duke@1 2605 */
duke@1 2606 List<JCTypeParameter> typeParametersOpt() {
duke@1 2607 if (S.token() == LT) {
duke@1 2608 checkGenerics();
duke@1 2609 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
duke@1 2610 S.nextToken();
duke@1 2611 typarams.append(typeParameter());
duke@1 2612 while (S.token() == COMMA) {
duke@1 2613 S.nextToken();
duke@1 2614 typarams.append(typeParameter());
duke@1 2615 }
duke@1 2616 accept(GT);
duke@1 2617 return typarams.toList();
duke@1 2618 } else {
duke@1 2619 return List.nil();
duke@1 2620 }
duke@1 2621 }
duke@1 2622
duke@1 2623 /** TypeParameter = TypeVariable [TypeParameterBound]
duke@1 2624 * TypeParameterBound = EXTENDS Type {"&" Type}
duke@1 2625 * TypeVariable = Ident
duke@1 2626 */
duke@1 2627 JCTypeParameter typeParameter() {
duke@1 2628 int pos = S.pos();
duke@1 2629 Name name = ident();
duke@1 2630 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
duke@1 2631 if (S.token() == EXTENDS) {
duke@1 2632 S.nextToken();
duke@1 2633 bounds.append(type());
duke@1 2634 while (S.token() == AMP) {
duke@1 2635 S.nextToken();
duke@1 2636 bounds.append(type());
duke@1 2637 }
duke@1 2638 }
duke@1 2639 return toP(F.at(pos).TypeParameter(name, bounds.toList()));
duke@1 2640 }
duke@1 2641
duke@1 2642 /** FormalParameters = "(" [ FormalParameterList ] ")"
duke@1 2643 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
duke@1 2644 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
duke@1 2645 */
duke@1 2646 List<JCVariableDecl> formalParameters() {
duke@1 2647 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
duke@1 2648 JCVariableDecl lastParam = null;
duke@1 2649 accept(LPAREN);
duke@1 2650 if (S.token() != RPAREN) {
duke@1 2651 params.append(lastParam = formalParameter());
duke@1 2652 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
duke@1 2653 S.nextToken();
duke@1 2654 params.append(lastParam = formalParameter());
duke@1 2655 }
duke@1 2656 }
duke@1 2657 accept(RPAREN);
duke@1 2658 return params.toList();
duke@1 2659 }
duke@1 2660
duke@1 2661 JCModifiers optFinal(long flags) {
duke@1 2662 JCModifiers mods = modifiersOpt();
duke@1 2663 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
duke@1 2664 mods.flags |= flags;
duke@1 2665 return mods;
duke@1 2666 }
duke@1 2667
duke@1 2668 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
duke@1 2669 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
duke@1 2670 */
duke@1 2671 JCVariableDecl formalParameter() {
duke@1 2672 JCModifiers mods = optFinal(Flags.PARAMETER);
duke@1 2673 JCExpression type = type();
duke@1 2674 if (S.token() == ELLIPSIS) {
duke@1 2675 checkVarargs();
duke@1 2676 mods.flags |= Flags.VARARGS;
duke@1 2677 type = to(F.at(S.pos()).TypeArray(type));
duke@1 2678 S.nextToken();
duke@1 2679 }
duke@1 2680 return variableDeclaratorId(mods, type);
duke@1 2681 }
duke@1 2682
duke@1 2683 /* ---------- auxiliary methods -------------- */
duke@1 2684
duke@1 2685 /** Check that given tree is a legal expression statement.
duke@1 2686 */
duke@1 2687 protected JCExpression checkExprStat(JCExpression t) {
duke@1 2688 switch(t.getTag()) {
duke@1 2689 case JCTree.PREINC: case JCTree.PREDEC:
duke@1 2690 case JCTree.POSTINC: case JCTree.POSTDEC:
duke@1 2691 case JCTree.ASSIGN:
duke@1 2692 case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
duke@1 2693 case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
duke@1 2694 case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
duke@1 2695 case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
duke@1 2696 case JCTree.APPLY: case JCTree.NEWCLASS:
duke@1 2697 case JCTree.ERRONEOUS:
duke@1 2698 return t;
duke@1 2699 default:
duke@1 2700 log.error(t.pos, "not.stmt");
duke@1 2701 return F.at(t.pos).Erroneous(List.<JCTree>of(t));
duke@1 2702 }
duke@1 2703 }
duke@1 2704
duke@1 2705 /** Return precedence of operator represented by token,
duke@1 2706 * -1 if token is not a binary operator. @see TreeInfo.opPrec
duke@1 2707 */
duke@1 2708 static int prec(Token token) {
duke@1 2709 int oc = optag(token);
duke@1 2710 return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
duke@1 2711 }
duke@1 2712
duke@1 2713 /** Return operation tag of binary operator represented by token,
duke@1 2714 * -1 if token is not a binary operator.
duke@1 2715 */
duke@1 2716 static int optag(Token token) {
duke@1 2717 switch (token) {
duke@1 2718 case BARBAR:
duke@1 2719 return JCTree.OR;
duke@1 2720 case AMPAMP:
duke@1 2721 return JCTree.AND;
duke@1 2722 case BAR:
duke@1 2723 return JCTree.BITOR;
duke@1 2724 case BAREQ:
duke@1 2725 return JCTree.BITOR_ASG;
duke@1 2726 case CARET:
duke@1 2727 return JCTree.BITXOR;
duke@1 2728 case CARETEQ:
duke@1 2729 return JCTree.BITXOR_ASG;
duke@1 2730 case AMP:
duke@1 2731 return JCTree.BITAND;
duke@1 2732 case AMPEQ:
duke@1 2733 return JCTree.BITAND_ASG;
duke@1 2734 case EQEQ:
duke@1 2735 return JCTree.EQ;
duke@1 2736 case BANGEQ:
duke@1 2737 return JCTree.NE;
duke@1 2738 case LT:
duke@1 2739 return JCTree.LT;
duke@1 2740 case GT:
duke@1 2741 return JCTree.GT;
duke@1 2742 case LTEQ:
duke@1 2743 return JCTree.LE;
duke@1 2744 case GTEQ:
duke@1 2745 return JCTree.GE;
duke@1 2746 case LTLT:
duke@1 2747 return JCTree.SL;
duke@1 2748 case LTLTEQ:
duke@1 2749 return JCTree.SL_ASG;
duke@1 2750 case GTGT:
duke@1 2751 return JCTree.SR;
duke@1 2752 case GTGTEQ:
duke@1 2753 return JCTree.SR_ASG;
duke@1 2754 case GTGTGT:
duke@1 2755 return JCTree.USR;
duke@1 2756 case GTGTGTEQ:
duke@1 2757 return JCTree.USR_ASG;
duke@1 2758 case PLUS:
duke@1 2759 return JCTree.PLUS;
duke@1 2760 case PLUSEQ:
duke@1 2761 return JCTree.PLUS_ASG;
duke@1 2762 case SUB:
duke@1 2763 return JCTree.MINUS;
duke@1 2764 case SUBEQ:
duke@1 2765 return JCTree.MINUS_ASG;
duke@1 2766 case STAR:
duke@1 2767 return JCTree.MUL;
duke@1 2768 case STAREQ:
duke@1 2769 return JCTree.MUL_ASG;
duke@1 2770 case SLASH:
duke@1 2771 return JCTree.DIV;
duke@1 2772 case SLASHEQ:
duke@1 2773 return JCTree.DIV_ASG;
duke@1 2774 case PERCENT:
duke@1 2775 return JCTree.MOD;
duke@1 2776 case PERCENTEQ:
duke@1 2777 return JCTree.MOD_ASG;
duke@1 2778 case INSTANCEOF:
duke@1 2779 return JCTree.TYPETEST;
duke@1 2780 default:
duke@1 2781 return -1;
duke@1 2782 }
duke@1 2783 }
duke@1 2784
duke@1 2785 /** Return operation tag of unary operator represented by token,
duke@1 2786 * -1 if token is not a binary operator.
duke@1 2787 */
duke@1 2788 static int unoptag(Token token) {
duke@1 2789 switch (token) {
duke@1 2790 case PLUS:
duke@1 2791 return JCTree.POS;
duke@1 2792 case SUB:
duke@1 2793 return JCTree.NEG;
duke@1 2794 case BANG:
duke@1 2795 return JCTree.NOT;
duke@1 2796 case TILDE:
duke@1 2797 return JCTree.COMPL;
duke@1 2798 case PLUSPLUS:
duke@1 2799 return JCTree.PREINC;
duke@1 2800 case SUBSUB:
duke@1 2801 return JCTree.PREDEC;
duke@1 2802 default:
duke@1 2803 return -1;
duke@1 2804 }
duke@1 2805 }
duke@1 2806
duke@1 2807 /** Return type tag of basic type represented by token,
duke@1 2808 * -1 if token is not a basic type identifier.
duke@1 2809 */
duke@1 2810 static int typetag(Token token) {
duke@1 2811 switch (token) {
duke@1 2812 case BYTE:
duke@1 2813 return TypeTags.BYTE;
duke@1 2814 case CHAR:
duke@1 2815 return TypeTags.CHAR;
duke@1 2816 case SHORT:
duke@1 2817 return TypeTags.SHORT;
duke@1 2818 case INT:
duke@1 2819 return TypeTags.INT;
duke@1 2820 case LONG:
duke@1 2821 return TypeTags.LONG;
duke@1 2822 case FLOAT:
duke@1 2823 return TypeTags.FLOAT;
duke@1 2824 case DOUBLE:
duke@1 2825 return TypeTags.DOUBLE;
duke@1 2826 case BOOLEAN:
duke@1 2827 return TypeTags.BOOLEAN;
duke@1 2828 default:
duke@1 2829 return -1;
duke@1 2830 }
duke@1 2831 }
duke@1 2832
duke@1 2833 void checkGenerics() {
duke@1 2834 if (!allowGenerics) {
duke@1 2835 log.error(S.pos(), "generics.not.supported.in.source", source.name);
duke@1 2836 allowGenerics = true;
duke@1 2837 }
duke@1 2838 }
duke@1 2839 void checkVarargs() {
duke@1 2840 if (!allowVarargs) {
duke@1 2841 log.error(S.pos(), "varargs.not.supported.in.source", source.name);
duke@1 2842 allowVarargs = true;
duke@1 2843 }
duke@1 2844 }
duke@1 2845 void checkForeach() {
duke@1 2846 if (!allowForeach) {
duke@1 2847 log.error(S.pos(), "foreach.not.supported.in.source", source.name);
duke@1 2848 allowForeach = true;
duke@1 2849 }
duke@1 2850 }
duke@1 2851 void checkStaticImports() {
duke@1 2852 if (!allowStaticImport) {
duke@1 2853 log.error(S.pos(), "static.import.not.supported.in.source", source.name);
duke@1 2854 allowStaticImport = true;
duke@1 2855 }
duke@1 2856 }
duke@1 2857 void checkAnnotations() {
duke@1 2858 if (!allowAnnotations) {
duke@1 2859 log.error(S.pos(), "annotations.not.supported.in.source", source.name);
duke@1 2860 allowAnnotations = true;
duke@1 2861 }
duke@1 2862 }
duke@1 2863 }

mercurial