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