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