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

Thu, 06 Oct 2011 18:39:31 +0100

author
mcimadamore
date
Thu, 06 Oct 2011 18:39:31 +0100
changeset 1103
47147081d5b4
parent 1074
04f983e3e825
child 1113
d346ab55031b
permissions
-rw-r--r--

7090499: missing rawtypes warnings in anonymous inner class
Summary: javac does not detect raw types inside anonymous inner classes
Reviewed-by: jjg

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

mercurial