Home » openjdk-7 » com.sun.tools » javac » parser » [javadoc | source]

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

Home » openjdk-7 » com.sun.tools » javac » parser » [javadoc | source]