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

Wed, 14 Apr 2010 12:31:55 +0100

author
mcimadamore
date
Wed, 14 Apr 2010 12:31:55 +0100
changeset 537
9d9d08922405
parent 536
396b117c1743
child 550
a6f2911a7c55
permissions
-rw-r--r--

6939620: Switch to 'complex' diamond inference scheme
Summary: Implement new inference scheme for diamond operator that takes into account type of actual arguments supplied to constructor
Reviewed-by: jjg, darcy

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

mercurial