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

Tue, 09 Sep 2008 10:40:50 -0700

author
jjg
date
Tue, 09 Sep 2008 10:40:50 -0700
changeset 111
a92b756a888f
parent 80
src/share/classes/com/sun/tools/javac/parser/Parser.java@5c9cdeb740f2
child 113
eff38cc97183
permissions
-rw-r--r--

6724118: change JavaCompiler to not use Scanner directly
6736119: refactor Parser and Parser.Factory
Reviewed-by: mcimadamore

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

mercurial