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