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

Tue, 13 Jan 2009 13:28:20 +0000

author
mcimadamore
date
Tue, 13 Jan 2009 13:28:20 +0000
changeset 185
d57378c34fdb
parent 113
eff38cc97183
child 195
83c59a9d4b94
permissions
-rw-r--r--

6665356: Cast not allowed when both qualifying type and inner class are parameterized
Summary: Fixed parser and cats conversion in order to allow cast between generic inner classes
Reviewed-by: jjg

     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 Names 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.isEmpty() ? 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                         while (S.token() == DOT) {
   868                             S.nextToken();
   869                             mode = TYPE;
   870                             t = toP(F.at(S.pos()).Select(t, ident()));
   871                             t = typeArgumentsOpt(t);
   872                         }
   873                     } else if ((mode & EXPR) != 0) {
   874                         mode = EXPR;
   875                         t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec));
   876                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   877                     } else {
   878                         accept(GT);
   879                     }
   880                 }
   881                 else {
   882                     t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   883                 }
   884                 accept(RPAREN);
   885                 lastmode = mode;
   886                 mode = EXPR;
   887                 if ((lastmode & EXPR) == 0) {
   888                     JCExpression t1 = term3();
   889                     return F.at(pos).TypeCast(t, t1);
   890                 } else if ((lastmode & TYPE) != 0) {
   891                     switch (S.token()) {
   892                     /*case PLUSPLUS: case SUBSUB: */
   893                     case BANG: case TILDE:
   894                     case LPAREN: case THIS: case SUPER:
   895                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
   896                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
   897                     case TRUE: case FALSE: case NULL:
   898                     case NEW: case IDENTIFIER: case ASSERT: case ENUM:
   899                     case BYTE: case SHORT: case CHAR: case INT:
   900                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
   901                         JCExpression t1 = term3();
   902                         return F.at(pos).TypeCast(t, t1);
   903                     }
   904                 }
   905             } else return illegal();
   906             t = toP(F.at(pos).Parens(t));
   907             break;
   908         case THIS:
   909             if ((mode & EXPR) != 0) {
   910                 mode = EXPR;
   911                 t = to(F.at(pos).Ident(names._this));
   912                 S.nextToken();
   913                 if (typeArgs == null)
   914                     t = argumentsOpt(null, t);
   915                 else
   916                     t = arguments(typeArgs, t);
   917                 typeArgs = null;
   918             } else return illegal();
   919             break;
   920         case SUPER:
   921             if ((mode & EXPR) != 0) {
   922                 mode = EXPR;
   923                 t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super)));
   924                 typeArgs = null;
   925             } else return illegal();
   926             break;
   927         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
   928         case CHARLITERAL: case STRINGLITERAL:
   929         case TRUE: case FALSE: case NULL:
   930             if (typeArgs == null && (mode & EXPR) != 0) {
   931                 mode = EXPR;
   932                 t = literal(names.empty);
   933             } else return illegal();
   934             break;
   935         case NEW:
   936             if (typeArgs != null) return illegal();
   937             if ((mode & EXPR) != 0) {
   938                 mode = EXPR;
   939                 S.nextToken();
   940                 if (S.token() == LT) typeArgs = typeArguments();
   941                 t = creator(pos, typeArgs);
   942                 typeArgs = null;
   943             } else return illegal();
   944             break;
   945         case IDENTIFIER: case ASSERT: case ENUM:
   946             if (typeArgs != null) return illegal();
   947             t = toP(F.at(S.pos()).Ident(ident()));
   948             loop: while (true) {
   949                 pos = S.pos();
   950                 switch (S.token()) {
   951                 case LBRACKET:
   952                     S.nextToken();
   953                     if (S.token() == RBRACKET) {
   954                         S.nextToken();
   955                         t = bracketsOpt(t);
   956                         t = toP(F.at(pos).TypeArray(t));
   957                         t = bracketsSuffix(t);
   958                     } else {
   959                         if ((mode & EXPR) != 0) {
   960                             mode = EXPR;
   961                             JCExpression t1 = term();
   962                             t = to(F.at(pos).Indexed(t, t1));
   963                         }
   964                         accept(RBRACKET);
   965                     }
   966                     break loop;
   967                 case LPAREN:
   968                     if ((mode & EXPR) != 0) {
   969                         mode = EXPR;
   970                         t = arguments(typeArgs, t);
   971                         typeArgs = null;
   972                     }
   973                     break loop;
   974                 case DOT:
   975                     S.nextToken();
   976                     int oldmode = mode;
   977                     mode &= ~NOPARAMS;
   978                     typeArgs = typeArgumentsOpt(EXPR);
   979                     mode = oldmode;
   980                     if ((mode & EXPR) != 0) {
   981                         switch (S.token()) {
   982                         case CLASS:
   983                             if (typeArgs != null) return illegal();
   984                             mode = EXPR;
   985                             t = to(F.at(pos).Select(t, names._class));
   986                             S.nextToken();
   987                             break loop;
   988                         case THIS:
   989                             if (typeArgs != null) return illegal();
   990                             mode = EXPR;
   991                             t = to(F.at(pos).Select(t, names._this));
   992                             S.nextToken();
   993                             break loop;
   994                         case SUPER:
   995                             mode = EXPR;
   996                             t = to(F.at(pos).Select(t, names._super));
   997                             t = superSuffix(typeArgs, t);
   998                             typeArgs = null;
   999                             break loop;
  1000                         case NEW:
  1001                             if (typeArgs != null) return illegal();
  1002                             mode = EXPR;
  1003                             int pos1 = S.pos();
  1004                             S.nextToken();
  1005                             if (S.token() == LT) typeArgs = typeArguments();
  1006                             t = innerCreator(pos1, typeArgs, t);
  1007                             typeArgs = null;
  1008                             break loop;
  1011                     // typeArgs saved for next loop iteration.
  1012                     t = toP(F.at(pos).Select(t, ident()));
  1013                     break;
  1014                 default:
  1015                     break loop;
  1018             if (typeArgs != null) illegal();
  1019             t = typeArgumentsOpt(t);
  1020             break;
  1021         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1022         case DOUBLE: case BOOLEAN:
  1023             if (typeArgs != null) illegal();
  1024             t = bracketsSuffix(bracketsOpt(basicType()));
  1025             break;
  1026         case VOID:
  1027             if (typeArgs != null) illegal();
  1028             if ((mode & EXPR) != 0) {
  1029                 S.nextToken();
  1030                 if (S.token() == DOT) {
  1031                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
  1032                     t = bracketsSuffix(ti);
  1033                 } else {
  1034                     return illegal(pos);
  1036             } else {
  1037                 return illegal();
  1039             break;
  1040         default:
  1041             return illegal();
  1043         if (typeArgs != null) illegal();
  1044         while (true) {
  1045             int pos1 = S.pos();
  1046             if (S.token() == LBRACKET) {
  1047                 S.nextToken();
  1048                 if ((mode & TYPE) != 0) {
  1049                     int oldmode = mode;
  1050                     mode = TYPE;
  1051                     if (S.token() == RBRACKET) {
  1052                         S.nextToken();
  1053                         t = bracketsOpt(t);
  1054                         t = toP(F.at(pos1).TypeArray(t));
  1055                         return t;
  1057                     mode = oldmode;
  1059                 if ((mode & EXPR) != 0) {
  1060                     mode = EXPR;
  1061                     JCExpression t1 = term();
  1062                     t = to(F.at(pos1).Indexed(t, t1));
  1064                 accept(RBRACKET);
  1065             } else if (S.token() == DOT) {
  1066                 S.nextToken();
  1067                 typeArgs = typeArgumentsOpt(EXPR);
  1068                 if (S.token() == SUPER && (mode & EXPR) != 0) {
  1069                     mode = EXPR;
  1070                     t = to(F.at(pos1).Select(t, names._super));
  1071                     S.nextToken();
  1072                     t = arguments(typeArgs, t);
  1073                     typeArgs = null;
  1074                 } else if (S.token() == NEW && (mode & EXPR) != 0) {
  1075                     if (typeArgs != null) return illegal();
  1076                     mode = EXPR;
  1077                     int pos2 = S.pos();
  1078                     S.nextToken();
  1079                     if (S.token() == LT) typeArgs = typeArguments();
  1080                     t = innerCreator(pos2, typeArgs, t);
  1081                     typeArgs = null;
  1082                 } else {
  1083                     t = toP(F.at(pos1).Select(t, ident()));
  1084                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1085                     typeArgs = null;
  1087             } else {
  1088                 break;
  1091         while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
  1092             mode = EXPR;
  1093             t = to(F.at(S.pos()).Unary(
  1094                   S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
  1095             S.nextToken();
  1097         return toP(t);
  1100     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1101      */
  1102     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1103         S.nextToken();
  1104         if (S.token() == LPAREN || typeArgs != null) {
  1105             t = arguments(typeArgs, t);
  1106         } else {
  1107             int pos = S.pos();
  1108             accept(DOT);
  1109             typeArgs = (S.token() == LT) ? typeArguments() : null;
  1110             t = toP(F.at(pos).Select(t, ident()));
  1111             t = argumentsOpt(typeArgs, t);
  1113         return t;
  1116     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1117      */
  1118     JCPrimitiveTypeTree basicType() {
  1119         JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
  1120         S.nextToken();
  1121         return t;
  1124     /** ArgumentsOpt = [ Arguments ]
  1125      */
  1126     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1127         if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
  1128             mode = EXPR;
  1129             return arguments(typeArgs, t);
  1130         } else {
  1131             return t;
  1135     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1136      */
  1137     List<JCExpression> arguments() {
  1138         ListBuffer<JCExpression> args = lb();
  1139         if (S.token() == LPAREN) {
  1140             S.nextToken();
  1141             if (S.token() != RPAREN) {
  1142                 args.append(parseExpression());
  1143                 while (S.token() == COMMA) {
  1144                     S.nextToken();
  1145                     args.append(parseExpression());
  1148             accept(RPAREN);
  1149         } else {
  1150             syntaxError(S.pos(), "expected", LPAREN);
  1152         return args.toList();
  1155     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1156         int pos = S.pos();
  1157         List<JCExpression> args = arguments();
  1158         return toP(F.at(pos).Apply(typeArgs, t, args));
  1161     /**  TypeArgumentsOpt = [ TypeArguments ]
  1162      */
  1163     JCExpression typeArgumentsOpt(JCExpression t) {
  1164         if (S.token() == LT &&
  1165             (mode & TYPE) != 0 &&
  1166             (mode & NOPARAMS) == 0) {
  1167             mode = TYPE;
  1168             checkGenerics();
  1169             return typeArguments(t);
  1170         } else {
  1171             return t;
  1174     List<JCExpression> typeArgumentsOpt() {
  1175         return typeArgumentsOpt(TYPE);
  1178     List<JCExpression> typeArgumentsOpt(int useMode) {
  1179         if (S.token() == LT) {
  1180             checkGenerics();
  1181             if ((mode & useMode) == 0 ||
  1182                 (mode & NOPARAMS) != 0) {
  1183                 illegal();
  1185             mode = useMode;
  1186             return typeArguments();
  1188         return null;
  1191     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1192      */
  1193     List<JCExpression> typeArguments() {
  1194         ListBuffer<JCExpression> args = lb();
  1195         if (S.token() == LT) {
  1196             S.nextToken();
  1197             args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1198             while (S.token() == COMMA) {
  1199                 S.nextToken();
  1200                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1202             switch (S.token()) {
  1203             case GTGTGTEQ:
  1204                 S.token(GTGTEQ);
  1205                 break;
  1206             case GTGTEQ:
  1207                 S.token(GTEQ);
  1208                 break;
  1209             case GTEQ:
  1210                 S.token(EQ);
  1211                 break;
  1212             case GTGTGT:
  1213                 S.token(GTGT);
  1214                 break;
  1215             case GTGT:
  1216                 S.token(GT);
  1217                 break;
  1218             default:
  1219                 accept(GT);
  1220                 break;
  1222         } else {
  1223             syntaxError(S.pos(), "expected", LT);
  1225         return args.toList();
  1228     /** TypeArgument = Type
  1229      *               | "?"
  1230      *               | "?" EXTENDS Type {"&" Type}
  1231      *               | "?" SUPER Type
  1232      */
  1233     JCExpression typeArgument() {
  1234         if (S.token() != QUES) return parseType();
  1235         int pos = S.pos();
  1236         S.nextToken();
  1237         if (S.token() == EXTENDS) {
  1238             TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
  1239             S.nextToken();
  1240             return F.at(pos).Wildcard(t, parseType());
  1241         } else if (S.token() == SUPER) {
  1242             TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
  1243             S.nextToken();
  1244             return F.at(pos).Wildcard(t, parseType());
  1245         } else if (S.token() == IDENTIFIER) {
  1246             //error recovery
  1247             reportSyntaxError(S.prevEndPos(), "expected3",
  1248                     GT, EXTENDS, SUPER);
  1249             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1250             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1251             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
  1252             return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1253         } else {
  1254             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1255             return toP(F.at(pos).Wildcard(t, null));
  1259     JCTypeApply typeArguments(JCExpression t) {
  1260         int pos = S.pos();
  1261         List<JCExpression> args = typeArguments();
  1262         return toP(F.at(pos).TypeApply(t, args));
  1265     /** BracketsOpt = {"[" "]"}
  1266      */
  1267     private JCExpression bracketsOpt(JCExpression t) {
  1268         if (S.token() == LBRACKET) {
  1269             int pos = S.pos();
  1270             S.nextToken();
  1271             t = bracketsOptCont(t, pos);
  1272             F.at(pos);
  1274         return t;
  1277     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1278         accept(RBRACKET);
  1279         t = bracketsOpt(t);
  1280         return toP(F.at(pos).TypeArray(t));
  1283     /** BracketsSuffixExpr = "." CLASS
  1284      *  BracketsSuffixType =
  1285      */
  1286     JCExpression bracketsSuffix(JCExpression t) {
  1287         if ((mode & EXPR) != 0 && S.token() == DOT) {
  1288             mode = EXPR;
  1289             int pos = S.pos();
  1290             S.nextToken();
  1291             accept(CLASS);
  1292             if (S.pos() == errorEndPos) {
  1293                 // error recovery
  1294                 Name name = null;
  1295                 if (S.token() == IDENTIFIER) {
  1296                     name = S.name();
  1297                     S.nextToken();
  1298                 } else {
  1299                     name = names.error;
  1301                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1302             } else {
  1303                 t = toP(F.at(pos).Select(t, names._class));
  1305         } else if ((mode & TYPE) != 0) {
  1306             mode = TYPE;
  1307         } else {
  1308             syntaxError(S.pos(), "dot.class.expected");
  1310         return t;
  1313     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1314      */
  1315     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1316         switch (S.token()) {
  1317         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1318         case DOUBLE: case BOOLEAN:
  1319             if (typeArgs == null)
  1320                 return arrayCreatorRest(newpos, basicType());
  1321             break;
  1322         default:
  1324         JCExpression t = qualident();
  1325         int oldmode = mode;
  1326         mode = TYPE;
  1327         if (S.token() == LT) {
  1328             checkGenerics();
  1329             t = typeArguments(t);
  1331         while (S.token() == DOT) {
  1332             int pos = S.pos();
  1333             S.nextToken();
  1334             t = toP(F.at(pos).Select(t, ident()));
  1335             if (S.token() == LT) {
  1336                 checkGenerics();
  1337                 t = typeArguments(t);
  1340         mode = oldmode;
  1341         if (S.token() == LBRACKET) {
  1342             JCExpression e = arrayCreatorRest(newpos, t);
  1343             if (typeArgs != null) {
  1344                 int pos = newpos;
  1345                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1346                     // note: this should always happen but we should
  1347                     // not rely on this as the parser is continuously
  1348                     // modified to improve error recovery.
  1349                     pos = typeArgs.head.pos;
  1351                 setErrorEndPos(S.prevEndPos());
  1352                 reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
  1353                 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
  1355             return e;
  1356         } else if (S.token() == LPAREN) {
  1357             return classCreatorRest(newpos, null, typeArgs, t);
  1358         } else {
  1359             reportSyntaxError(S.pos(), "expected2",
  1360                                LPAREN, LBRACKET);
  1361             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1362             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1366     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1367      */
  1368     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1369         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
  1370         if (S.token() == LT) {
  1371             checkGenerics();
  1372             t = typeArguments(t);
  1374         return classCreatorRest(newpos, encl, typeArgs, t);
  1377     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1378      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1379      */
  1380     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1381         accept(LBRACKET);
  1382         if (S.token() == RBRACKET) {
  1383             accept(RBRACKET);
  1384             elemtype = bracketsOpt(elemtype);
  1385             if (S.token() == LBRACE) {
  1386                 return arrayInitializer(newpos, elemtype);
  1387             } else {
  1388                 return syntaxError(S.pos(), "array.dimension.missing");
  1390         } else {
  1391             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1392             dims.append(parseExpression());
  1393             accept(RBRACKET);
  1394             while (S.token() == LBRACKET) {
  1395                 int pos = S.pos();
  1396                 S.nextToken();
  1397                 if (S.token() == RBRACKET) {
  1398                     elemtype = bracketsOptCont(elemtype, pos);
  1399                 } else {
  1400                     dims.append(parseExpression());
  1401                     accept(RBRACKET);
  1404             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1408     /** ClassCreatorRest = Arguments [ClassBody]
  1409      */
  1410     JCExpression classCreatorRest(int newpos,
  1411                                   JCExpression encl,
  1412                                   List<JCExpression> typeArgs,
  1413                                   JCExpression t)
  1415         List<JCExpression> args = arguments();
  1416         JCClassDecl body = null;
  1417         if (S.token() == LBRACE) {
  1418             int pos = S.pos();
  1419             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1420             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1421             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1423         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1426     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1427      */
  1428     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1429         accept(LBRACE);
  1430         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1431         if (S.token() == COMMA) {
  1432             S.nextToken();
  1433         } else if (S.token() != RBRACE) {
  1434             elems.append(variableInitializer());
  1435             while (S.token() == COMMA) {
  1436                 S.nextToken();
  1437                 if (S.token() == RBRACE) break;
  1438                 elems.append(variableInitializer());
  1441         accept(RBRACE);
  1442         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1445     /** VariableInitializer = ArrayInitializer | Expression
  1446      */
  1447     public JCExpression variableInitializer() {
  1448         return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
  1451     /** ParExpression = "(" Expression ")"
  1452      */
  1453     JCExpression parExpression() {
  1454         accept(LPAREN);
  1455         JCExpression t = parseExpression();
  1456         accept(RPAREN);
  1457         return t;
  1460     /** Block = "{" BlockStatements "}"
  1461      */
  1462     JCBlock block(int pos, long flags) {
  1463         accept(LBRACE);
  1464         List<JCStatement> stats = blockStatements();
  1465         JCBlock t = F.at(pos).Block(flags, stats);
  1466         while (S.token() == CASE || S.token() == DEFAULT) {
  1467             syntaxError("orphaned", S.token());
  1468             switchBlockStatementGroups();
  1470         // the Block node has a field "endpos" for first char of last token, which is
  1471         // usually but not necessarily the last char of the last token.
  1472         t.endpos = S.pos();
  1473         accept(RBRACE);
  1474         return toP(t);
  1477     public JCBlock block() {
  1478         return block(S.pos(), 0);
  1481     /** BlockStatements = { BlockStatement }
  1482      *  BlockStatement  = LocalVariableDeclarationStatement
  1483      *                  | ClassOrInterfaceOrEnumDeclaration
  1484      *                  | [Ident ":"] Statement
  1485      *  LocalVariableDeclarationStatement
  1486      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1487      */
  1488     @SuppressWarnings("fallthrough")
  1489     List<JCStatement> blockStatements() {
  1490 //todo: skip to anchor on error(?)
  1491         int lastErrPos = -1;
  1492         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1493         while (true) {
  1494             int pos = S.pos();
  1495             switch (S.token()) {
  1496             case RBRACE: case CASE: case DEFAULT: case EOF:
  1497                 return stats.toList();
  1498             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1499             case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1500             case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1501                 stats.append(parseStatement());
  1502                 break;
  1503             case MONKEYS_AT:
  1504             case FINAL: {
  1505                 String dc = S.docComment();
  1506                 JCModifiers mods = modifiersOpt();
  1507                 if (S.token() == INTERFACE ||
  1508                     S.token() == CLASS ||
  1509                     allowEnums && S.token() == ENUM) {
  1510                     stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1511                 } else {
  1512                     JCExpression t = parseType();
  1513                     stats.appendList(variableDeclarators(mods, t,
  1514                                                          new ListBuffer<JCStatement>()));
  1515                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1516                     storeEnd(stats.elems.last(), S.endPos());
  1517                     accept(SEMI);
  1519                 break;
  1521             case ABSTRACT: case STRICTFP: {
  1522                 String dc = S.docComment();
  1523                 JCModifiers mods = modifiersOpt();
  1524                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1525                 break;
  1527             case INTERFACE:
  1528             case CLASS:
  1529                 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1530                                                                S.docComment()));
  1531                 break;
  1532             case ENUM:
  1533             case ASSERT:
  1534                 if (allowEnums && S.token() == ENUM) {
  1535                     log.error(S.pos(), "local.enum");
  1536                     stats.
  1537                         append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1538                                                                  S.docComment()));
  1539                     break;
  1540                 } else if (allowAsserts && S.token() == ASSERT) {
  1541                     stats.append(parseStatement());
  1542                     break;
  1544                 /* fall through to default */
  1545             default:
  1546                 Name name = S.name();
  1547                 JCExpression t = term(EXPR | TYPE);
  1548                 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
  1549                     S.nextToken();
  1550                     JCStatement stat = parseStatement();
  1551                     stats.append(F.at(pos).Labelled(name, stat));
  1552                 } else if ((lastmode & TYPE) != 0 &&
  1553                            (S.token() == IDENTIFIER ||
  1554                             S.token() == ASSERT ||
  1555                             S.token() == ENUM)) {
  1556                     pos = S.pos();
  1557                     JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1558                     F.at(pos);
  1559                     stats.appendList(variableDeclarators(mods, t,
  1560                                                          new ListBuffer<JCStatement>()));
  1561                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1562                     storeEnd(stats.elems.last(), S.endPos());
  1563                     accept(SEMI);
  1564                 } else {
  1565                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1566                     stats.append(to(F.at(pos).Exec(checkExprStat(t))));
  1567                     accept(SEMI);
  1571             // error recovery
  1572             if (S.pos() == lastErrPos)
  1573                 return stats.toList();
  1574             if (S.pos() <= errorEndPos) {
  1575                 skip(false, true, true, true);
  1576                 lastErrPos = S.pos();
  1579             // ensure no dangling /** @deprecated */ active
  1580             S.resetDeprecatedFlag();
  1584     /** Statement =
  1585      *       Block
  1586      *     | IF ParExpression Statement [ELSE Statement]
  1587      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1588      *     | FOR "(" FormalParameter : Expression ")" Statement
  1589      *     | WHILE ParExpression Statement
  1590      *     | DO Statement WHILE ParExpression ";"
  1591      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1592      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1593      *     | SYNCHRONIZED ParExpression Block
  1594      *     | RETURN [Expression] ";"
  1595      *     | THROW Expression ";"
  1596      *     | BREAK [Ident] ";"
  1597      *     | CONTINUE [Ident] ";"
  1598      *     | ASSERT Expression [ ":" Expression ] ";"
  1599      *     | ";"
  1600      *     | ExpressionStatement
  1601      *     | Ident ":" Statement
  1602      */
  1603     @SuppressWarnings("fallthrough")
  1604     public JCStatement parseStatement() {
  1605         int pos = S.pos();
  1606         switch (S.token()) {
  1607         case LBRACE:
  1608             return block();
  1609         case IF: {
  1610             S.nextToken();
  1611             JCExpression cond = parExpression();
  1612             JCStatement thenpart = parseStatement();
  1613             JCStatement elsepart = null;
  1614             if (S.token() == ELSE) {
  1615                 S.nextToken();
  1616                 elsepart = parseStatement();
  1618             return F.at(pos).If(cond, thenpart, elsepart);
  1620         case FOR: {
  1621             S.nextToken();
  1622             accept(LPAREN);
  1623             List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
  1624             if (inits.length() == 1 &&
  1625                 inits.head.getTag() == JCTree.VARDEF &&
  1626                 ((JCVariableDecl) inits.head).init == null &&
  1627                 S.token() == COLON) {
  1628                 checkForeach();
  1629                 JCVariableDecl var = (JCVariableDecl)inits.head;
  1630                 accept(COLON);
  1631                 JCExpression expr = parseExpression();
  1632                 accept(RPAREN);
  1633                 JCStatement body = parseStatement();
  1634                 return F.at(pos).ForeachLoop(var, expr, body);
  1635             } else {
  1636                 accept(SEMI);
  1637                 JCExpression cond = S.token() == SEMI ? null : parseExpression();
  1638                 accept(SEMI);
  1639                 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  1640                 accept(RPAREN);
  1641                 JCStatement body = parseStatement();
  1642                 return F.at(pos).ForLoop(inits, cond, steps, body);
  1645         case WHILE: {
  1646             S.nextToken();
  1647             JCExpression cond = parExpression();
  1648             JCStatement body = parseStatement();
  1649             return F.at(pos).WhileLoop(cond, body);
  1651         case DO: {
  1652             S.nextToken();
  1653             JCStatement body = parseStatement();
  1654             accept(WHILE);
  1655             JCExpression cond = parExpression();
  1656             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  1657             accept(SEMI);
  1658             return t;
  1660         case TRY: {
  1661             S.nextToken();
  1662             JCBlock body = block();
  1663             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  1664             JCBlock finalizer = null;
  1665             if (S.token() == CATCH || S.token() == FINALLY) {
  1666                 while (S.token() == CATCH) catchers.append(catchClause());
  1667                 if (S.token() == FINALLY) {
  1668                     S.nextToken();
  1669                     finalizer = block();
  1671             } else {
  1672                 log.error(pos, "try.without.catch.or.finally");
  1674             return F.at(pos).Try(body, catchers.toList(), finalizer);
  1676         case SWITCH: {
  1677             S.nextToken();
  1678             JCExpression selector = parExpression();
  1679             accept(LBRACE);
  1680             List<JCCase> cases = switchBlockStatementGroups();
  1681             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  1682             accept(RBRACE);
  1683             return t;
  1685         case SYNCHRONIZED: {
  1686             S.nextToken();
  1687             JCExpression lock = parExpression();
  1688             JCBlock body = block();
  1689             return F.at(pos).Synchronized(lock, body);
  1691         case RETURN: {
  1692             S.nextToken();
  1693             JCExpression result = S.token() == SEMI ? null : parseExpression();
  1694             JCReturn t = to(F.at(pos).Return(result));
  1695             accept(SEMI);
  1696             return t;
  1698         case THROW: {
  1699             S.nextToken();
  1700             JCExpression exc = parseExpression();
  1701             JCThrow t = to(F.at(pos).Throw(exc));
  1702             accept(SEMI);
  1703             return t;
  1705         case BREAK: {
  1706             S.nextToken();
  1707             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1708             JCBreak t = to(F.at(pos).Break(label));
  1709             accept(SEMI);
  1710             return t;
  1712         case CONTINUE: {
  1713             S.nextToken();
  1714             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1715             JCContinue t =  to(F.at(pos).Continue(label));
  1716             accept(SEMI);
  1717             return t;
  1719         case SEMI:
  1720             S.nextToken();
  1721             return toP(F.at(pos).Skip());
  1722         case ELSE:
  1723             return toP(F.Exec(syntaxError("else.without.if")));
  1724         case FINALLY:
  1725             return toP(F.Exec(syntaxError("finally.without.try")));
  1726         case CATCH:
  1727             return toP(F.Exec(syntaxError("catch.without.try")));
  1728         case ASSERT: {
  1729             if (allowAsserts && S.token() == ASSERT) {
  1730                 S.nextToken();
  1731                 JCExpression assertion = parseExpression();
  1732                 JCExpression message = null;
  1733                 if (S.token() == COLON) {
  1734                     S.nextToken();
  1735                     message = parseExpression();
  1737                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  1738                 accept(SEMI);
  1739                 return t;
  1741             /* else fall through to default case */
  1743         case ENUM:
  1744         default:
  1745             Name name = S.name();
  1746             JCExpression expr = parseExpression();
  1747             if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
  1748                 S.nextToken();
  1749                 JCStatement stat = parseStatement();
  1750                 return F.at(pos).Labelled(name, stat);
  1751             } else {
  1752                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1753                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  1754                 accept(SEMI);
  1755                 return stat;
  1760     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  1761      */
  1762     JCCatch catchClause() {
  1763         int pos = S.pos();
  1764         accept(CATCH);
  1765         accept(LPAREN);
  1766         JCVariableDecl formal =
  1767             variableDeclaratorId(optFinal(Flags.PARAMETER),
  1768                                  qualident());
  1769         accept(RPAREN);
  1770         JCBlock body = block();
  1771         return F.at(pos).Catch(formal, body);
  1774     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  1775      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  1776      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  1777      */
  1778     List<JCCase> switchBlockStatementGroups() {
  1779         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  1780         while (true) {
  1781             int pos = S.pos();
  1782             switch (S.token()) {
  1783             case CASE: {
  1784                 S.nextToken();
  1785                 JCExpression pat = parseExpression();
  1786                 accept(COLON);
  1787                 List<JCStatement> stats = blockStatements();
  1788                 JCCase c = F.at(pos).Case(pat, stats);
  1789                 if (stats.isEmpty())
  1790                     storeEnd(c, S.prevEndPos());
  1791                 cases.append(c);
  1792                 break;
  1794             case DEFAULT: {
  1795                 S.nextToken();
  1796                 accept(COLON);
  1797                 List<JCStatement> stats = blockStatements();
  1798                 JCCase c = F.at(pos).Case(null, stats);
  1799                 if (stats.isEmpty())
  1800                     storeEnd(c, S.prevEndPos());
  1801                 cases.append(c);
  1802                 break;
  1804             case RBRACE: case EOF:
  1805                 return cases.toList();
  1806             default:
  1807                 S.nextToken(); // to ensure progress
  1808                 syntaxError(pos, "expected3",
  1809                     CASE, DEFAULT, RBRACE);
  1814     /** MoreStatementExpressions = { COMMA StatementExpression }
  1815      */
  1816     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  1817                                                                     JCExpression first,
  1818                                                                     T stats) {
  1819         // This Exec is a "StatementExpression"; it subsumes no terminating token
  1820         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  1821         while (S.token() == COMMA) {
  1822             S.nextToken();
  1823             pos = S.pos();
  1824             JCExpression t = parseExpression();
  1825             // This Exec is a "StatementExpression"; it subsumes no terminating token
  1826             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  1828         return stats;
  1831     /** ForInit = StatementExpression MoreStatementExpressions
  1832      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  1833      */
  1834     List<JCStatement> forInit() {
  1835         ListBuffer<JCStatement> stats = lb();
  1836         int pos = S.pos();
  1837         if (S.token() == FINAL || S.token() == MONKEYS_AT) {
  1838             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  1839         } else {
  1840             JCExpression t = term(EXPR | TYPE);
  1841             if ((lastmode & TYPE) != 0 &&
  1842                 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
  1843                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  1844             else
  1845                 return moreStatementExpressions(pos, t, stats).toList();
  1849     /** ForUpdate = StatementExpression MoreStatementExpressions
  1850      */
  1851     List<JCExpressionStatement> forUpdate() {
  1852         return moreStatementExpressions(S.pos(),
  1853                                         parseExpression(),
  1854                                         new ListBuffer<JCExpressionStatement>()).toList();
  1857     /** AnnotationsOpt = { '@' Annotation }
  1858      */
  1859     List<JCAnnotation> annotationsOpt() {
  1860         if (S.token() != MONKEYS_AT) return List.nil(); // optimization
  1861         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  1862         while (S.token() == MONKEYS_AT) {
  1863             int pos = S.pos();
  1864             S.nextToken();
  1865             buf.append(annotation(pos));
  1867         return buf.toList();
  1870     /** ModifiersOpt = { Modifier }
  1871      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  1872      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  1873      *           | "@" Annotation
  1874      */
  1875     JCModifiers modifiersOpt() {
  1876         return modifiersOpt(null);
  1878     JCModifiers modifiersOpt(JCModifiers partial) {
  1879         long flags = (partial == null) ? 0 : partial.flags;
  1880         if (S.deprecatedFlag()) {
  1881             flags |= Flags.DEPRECATED;
  1882             S.resetDeprecatedFlag();
  1884         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  1885         if (partial != null) annotations.appendList(partial.annotations);
  1886         int pos = S.pos();
  1887         int lastPos = Position.NOPOS;
  1888     loop:
  1889         while (true) {
  1890             long flag;
  1891             switch (S.token()) {
  1892             case PRIVATE     : flag = Flags.PRIVATE; break;
  1893             case PROTECTED   : flag = Flags.PROTECTED; break;
  1894             case PUBLIC      : flag = Flags.PUBLIC; break;
  1895             case STATIC      : flag = Flags.STATIC; break;
  1896             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  1897             case FINAL       : flag = Flags.FINAL; break;
  1898             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  1899             case NATIVE      : flag = Flags.NATIVE; break;
  1900             case VOLATILE    : flag = Flags.VOLATILE; break;
  1901             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  1902             case STRICTFP    : flag = Flags.STRICTFP; break;
  1903             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  1904             default: break loop;
  1906             if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
  1907             lastPos = S.pos();
  1908             S.nextToken();
  1909             if (flag == Flags.ANNOTATION) {
  1910                 checkAnnotations();
  1911                 if (S.token() != INTERFACE) {
  1912                 JCAnnotation ann = annotation(lastPos);
  1913                 // if first modifier is an annotation, set pos to annotation's.
  1914                 if (flags == 0 && annotations.isEmpty())
  1915                     pos = ann.pos;
  1916                 annotations.append(ann);
  1917                 lastPos = ann.pos;
  1918                     flag = 0;
  1921             flags |= flag;
  1923         switch (S.token()) {
  1924         case ENUM: flags |= Flags.ENUM; break;
  1925         case INTERFACE: flags |= Flags.INTERFACE; break;
  1926         default: break;
  1929         /* A modifiers tree with no modifier tokens or annotations
  1930          * has no text position. */
  1931         if (flags == 0 && annotations.isEmpty())
  1932             pos = Position.NOPOS;
  1934         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  1935         if (pos != Position.NOPOS)
  1936             storeEnd(mods, S.prevEndPos());
  1937         return mods;
  1940     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  1941      * @param pos position of "@" token
  1942      */
  1943     JCAnnotation annotation(int pos) {
  1944         // accept(AT); // AT consumed by caller
  1945         checkAnnotations();
  1946         JCTree ident = qualident();
  1947         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  1948         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  1949         storeEnd(ann, S.prevEndPos());
  1950         return ann;
  1953     List<JCExpression> annotationFieldValuesOpt() {
  1954         return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  1957     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  1958     List<JCExpression> annotationFieldValues() {
  1959         accept(LPAREN);
  1960         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  1961         if (S.token() != RPAREN) {
  1962             buf.append(annotationFieldValue());
  1963             while (S.token() == COMMA) {
  1964                 S.nextToken();
  1965                 buf.append(annotationFieldValue());
  1968         accept(RPAREN);
  1969         return buf.toList();
  1972     /** AnnotationFieldValue    = AnnotationValue
  1973      *                          | Identifier "=" AnnotationValue
  1974      */
  1975     JCExpression annotationFieldValue() {
  1976         if (S.token() == IDENTIFIER) {
  1977             mode = EXPR;
  1978             JCExpression t1 = term1();
  1979             if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
  1980                 int pos = S.pos();
  1981                 accept(EQ);
  1982                 return toP(F.at(pos).Assign(t1, annotationValue()));
  1983             } else {
  1984                 return t1;
  1987         return annotationValue();
  1990     /* AnnotationValue          = ConditionalExpression
  1991      *                          | Annotation
  1992      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
  1993      */
  1994     JCExpression annotationValue() {
  1995         int pos;
  1996         switch (S.token()) {
  1997         case MONKEYS_AT:
  1998             pos = S.pos();
  1999             S.nextToken();
  2000             return annotation(pos);
  2001         case LBRACE:
  2002             pos = S.pos();
  2003             accept(LBRACE);
  2004             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2005             if (S.token() != RBRACE) {
  2006                 buf.append(annotationValue());
  2007                 while (S.token() == COMMA) {
  2008                     S.nextToken();
  2009                     if (S.token() == RPAREN) break;
  2010                     buf.append(annotationValue());
  2013             accept(RBRACE);
  2014             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2015         default:
  2016             mode = EXPR;
  2017             return term1();
  2021     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2022      */
  2023     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2024                                                                          JCExpression type,
  2025                                                                          T vdefs)
  2027         return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
  2030     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2031      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2033      *  @param reqInit  Is an initializer always required?
  2034      *  @param dc       The documentation comment for the variable declarations, or null.
  2035      */
  2036     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2037                                                                      JCModifiers mods,
  2038                                                                      JCExpression type,
  2039                                                                      Name name,
  2040                                                                      boolean reqInit,
  2041                                                                      String dc,
  2042                                                                      T vdefs)
  2044         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2045         while (S.token() == COMMA) {
  2046             // All but last of multiple declarators subsume a comma
  2047             storeEnd((JCTree)vdefs.elems.last(), S.endPos());
  2048             S.nextToken();
  2049             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2051         return vdefs;
  2054     /** VariableDeclarator = Ident VariableDeclaratorRest
  2055      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2056      */
  2057     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
  2058         return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
  2061     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2062      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2064      *  @param reqInit  Is an initializer always required?
  2065      *  @param dc       The documentation comment for the variable declarations, or null.
  2066      */
  2067     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2068                                   boolean reqInit, String dc) {
  2069         type = bracketsOpt(type);
  2070         JCExpression init = null;
  2071         if (S.token() == EQ) {
  2072             S.nextToken();
  2073             init = variableInitializer();
  2075         else if (reqInit) syntaxError(S.pos(), "expected", EQ);
  2076         JCVariableDecl result =
  2077             toP(F.at(pos).VarDef(mods, name, type, init));
  2078         attach(result, dc);
  2079         return result;
  2082     /** VariableDeclaratorId = Ident BracketsOpt
  2083      */
  2084     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2085         int pos = S.pos();
  2086         Name name = ident();
  2087         if ((mods.flags & Flags.VARARGS) == 0)
  2088             type = bracketsOpt(type);
  2089         return toP(F.at(pos).VarDef(mods, name, type, null));
  2092     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2093      */
  2094     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2095         int pos = S.pos();
  2096         JCExpression pid = null;
  2097         String dc = S.docComment();
  2098         JCModifiers mods = null;
  2099         List<JCAnnotation> packageAnnotations = List.nil();
  2100         if (S.token() == MONKEYS_AT)
  2101             mods = modifiersOpt();
  2103         if (S.token() == PACKAGE) {
  2104             if (mods != null) {
  2105                 checkNoMods(mods.flags);
  2106                 packageAnnotations = mods.annotations;
  2107                 mods = null;
  2109             S.nextToken();
  2110             pid = qualident();
  2111             accept(SEMI);
  2113         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2114         boolean checkForImports = true;
  2115         while (S.token() != EOF) {
  2116             if (S.pos() <= errorEndPos) {
  2117                 // error recovery
  2118                 skip(checkForImports, false, false, false);
  2119                 if (S.token() == EOF)
  2120                     break;
  2122             if (checkForImports && mods == null && S.token() == IMPORT) {
  2123                 defs.append(importDeclaration());
  2124             } else {
  2125                 JCTree def = typeDeclaration(mods);
  2126                 if (def instanceof JCExpressionStatement)
  2127                     def = ((JCExpressionStatement)def).expr;
  2128                 defs.append(def);
  2129                 if (def instanceof JCClassDecl)
  2130                     checkForImports = false;
  2131                 mods = null;
  2134         JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
  2135         attach(toplevel, dc);
  2136         if (defs.elems.isEmpty())
  2137             storeEnd(toplevel, S.prevEndPos());
  2138         if (keepDocComments)
  2139             toplevel.docComments = docComments;
  2140         if (keepLineMap)
  2141             toplevel.lineMap = S.getLineMap();
  2142         return toplevel;
  2145     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2146      */
  2147     JCTree importDeclaration() {
  2148         int pos = S.pos();
  2149         S.nextToken();
  2150         boolean importStatic = false;
  2151         if (S.token() == STATIC) {
  2152             checkStaticImports();
  2153             importStatic = true;
  2154             S.nextToken();
  2156         JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
  2157         do {
  2158             int pos1 = S.pos();
  2159             accept(DOT);
  2160             if (S.token() == STAR) {
  2161                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2162                 S.nextToken();
  2163                 break;
  2164             } else {
  2165                 pid = toP(F.at(pos1).Select(pid, ident()));
  2167         } while (S.token() == DOT);
  2168         accept(SEMI);
  2169         return toP(F.at(pos).Import(pid, importStatic));
  2172     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2173      *                  | ";"
  2174      */
  2175     JCTree typeDeclaration(JCModifiers mods) {
  2176         int pos = S.pos();
  2177         if (mods == null && S.token() == SEMI) {
  2178             S.nextToken();
  2179             return toP(F.at(pos).Skip());
  2180         } else {
  2181             String dc = S.docComment();
  2182             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
  2186     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2187      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2188      *  @param mods     Any modifiers starting the class or interface declaration
  2189      *  @param dc       The documentation comment for the class, or null.
  2190      */
  2191     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
  2192         if (S.token() == CLASS) {
  2193             return classDeclaration(mods, dc);
  2194         } else if (S.token() == INTERFACE) {
  2195             return interfaceDeclaration(mods, dc);
  2196         } else if (allowEnums) {
  2197             if (S.token() == ENUM) {
  2198                 return enumDeclaration(mods, dc);
  2199             } else {
  2200                 int pos = S.pos();
  2201                 List<JCTree> errs;
  2202                 if (S.token() == IDENTIFIER) {
  2203                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2204                     setErrorEndPos(S.pos());
  2205                 } else {
  2206                     errs = List.<JCTree>of(mods);
  2208                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2209                                               CLASS, INTERFACE, ENUM)));
  2211         } else {
  2212             if (S.token() == ENUM) {
  2213                 log.error(S.pos(), "enums.not.supported.in.source", source.name);
  2214                 allowEnums = true;
  2215                 return enumDeclaration(mods, dc);
  2217             int pos = S.pos();
  2218             List<JCTree> errs;
  2219             if (S.token() == IDENTIFIER) {
  2220                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2221                 setErrorEndPos(S.pos());
  2222             } else {
  2223                 errs = List.<JCTree>of(mods);
  2225             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2226                                           CLASS, INTERFACE)));
  2230     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2231      *                     [IMPLEMENTS TypeList] ClassBody
  2232      *  @param mods    The modifiers starting the class declaration
  2233      *  @param dc       The documentation comment for the class, or null.
  2234      */
  2235     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
  2236         int pos = S.pos();
  2237         accept(CLASS);
  2238         Name name = ident();
  2240         List<JCTypeParameter> typarams = typeParametersOpt();
  2242         JCTree extending = null;
  2243         if (S.token() == EXTENDS) {
  2244             S.nextToken();
  2245             extending = parseType();
  2247         List<JCExpression> implementing = List.nil();
  2248         if (S.token() == IMPLEMENTS) {
  2249             S.nextToken();
  2250             implementing = typeList();
  2252         List<JCTree> defs = classOrInterfaceBody(name, false);
  2253         JCClassDecl result = toP(F.at(pos).ClassDef(
  2254             mods, name, typarams, extending, implementing, defs));
  2255         attach(result, dc);
  2256         return result;
  2259     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2260      *                         [EXTENDS TypeList] InterfaceBody
  2261      *  @param mods    The modifiers starting the interface declaration
  2262      *  @param dc       The documentation comment for the interface, or null.
  2263      */
  2264     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
  2265         int pos = S.pos();
  2266         accept(INTERFACE);
  2267         Name name = ident();
  2269         List<JCTypeParameter> typarams = typeParametersOpt();
  2271         List<JCExpression> extending = List.nil();
  2272         if (S.token() == EXTENDS) {
  2273             S.nextToken();
  2274             extending = typeList();
  2276         List<JCTree> defs = classOrInterfaceBody(name, true);
  2277         JCClassDecl result = toP(F.at(pos).ClassDef(
  2278             mods, name, typarams, null, extending, defs));
  2279         attach(result, dc);
  2280         return result;
  2283     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2284      *  @param mods    The modifiers starting the enum declaration
  2285      *  @param dc       The documentation comment for the enum, or null.
  2286      */
  2287     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
  2288         int pos = S.pos();
  2289         accept(ENUM);
  2290         Name name = ident();
  2292         List<JCExpression> implementing = List.nil();
  2293         if (S.token() == IMPLEMENTS) {
  2294             S.nextToken();
  2295             implementing = typeList();
  2298         List<JCTree> defs = enumBody(name);
  2299         JCModifiers newMods =
  2300             F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
  2301         JCClassDecl result = toP(F.at(pos).
  2302             ClassDef(newMods, name, List.<JCTypeParameter>nil(),
  2303                 null, implementing, defs));
  2304         attach(result, dc);
  2305         return result;
  2308     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2309      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2310      */
  2311     List<JCTree> enumBody(Name enumName) {
  2312         accept(LBRACE);
  2313         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2314         if (S.token() == COMMA) {
  2315             S.nextToken();
  2316         } else if (S.token() != RBRACE && S.token() != SEMI) {
  2317             defs.append(enumeratorDeclaration(enumName));
  2318             while (S.token() == COMMA) {
  2319                 S.nextToken();
  2320                 if (S.token() == RBRACE || S.token() == SEMI) break;
  2321                 defs.append(enumeratorDeclaration(enumName));
  2323             if (S.token() != SEMI && S.token() != RBRACE) {
  2324                 defs.append(syntaxError(S.pos(), "expected3",
  2325                                 COMMA, RBRACE, SEMI));
  2326                 S.nextToken();
  2329         if (S.token() == SEMI) {
  2330             S.nextToken();
  2331             while (S.token() != RBRACE && S.token() != EOF) {
  2332                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2333                                                                 false));
  2334                 if (S.pos() <= errorEndPos) {
  2335                     // error recovery
  2336                    skip(false, true, true, false);
  2340         accept(RBRACE);
  2341         return defs.toList();
  2344     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2345      */
  2346     JCTree enumeratorDeclaration(Name enumName) {
  2347         String dc = S.docComment();
  2348         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2349         if (S.deprecatedFlag()) {
  2350             flags |= Flags.DEPRECATED;
  2351             S.resetDeprecatedFlag();
  2353         int pos = S.pos();
  2354         List<JCAnnotation> annotations = annotationsOpt();
  2355         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2356         List<JCExpression> typeArgs = typeArgumentsOpt();
  2357         int identPos = S.pos();
  2358         Name name = ident();
  2359         int createPos = S.pos();
  2360         List<JCExpression> args = (S.token() == LPAREN)
  2361             ? arguments() : List.<JCExpression>nil();
  2362         JCClassDecl body = null;
  2363         if (S.token() == LBRACE) {
  2364             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2365             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2366             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2368         if (args.isEmpty() && body == null)
  2369             createPos = Position.NOPOS;
  2370         JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
  2371         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2372         if (createPos != Position.NOPOS)
  2373             storeEnd(create, S.prevEndPos());
  2374         ident = F.at(Position.NOPOS).Ident(enumName);
  2375         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2376         attach(result, dc);
  2377         return result;
  2380     /** TypeList = Type {"," Type}
  2381      */
  2382     List<JCExpression> typeList() {
  2383         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2384         ts.append(parseType());
  2385         while (S.token() == COMMA) {
  2386             S.nextToken();
  2387             ts.append(parseType());
  2389         return ts.toList();
  2392     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2393      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2394      */
  2395     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2396         accept(LBRACE);
  2397         if (S.pos() <= errorEndPos) {
  2398             // error recovery
  2399             skip(false, true, false, false);
  2400             if (S.token() == LBRACE)
  2401                 S.nextToken();
  2403         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2404         while (S.token() != RBRACE && S.token() != EOF) {
  2405             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2406             if (S.pos() <= errorEndPos) {
  2407                // error recovery
  2408                skip(false, true, true, false);
  2411         accept(RBRACE);
  2412         return defs.toList();
  2415     /** ClassBodyDeclaration =
  2416      *      ";"
  2417      *    | [STATIC] Block
  2418      *    | ModifiersOpt
  2419      *      ( Type Ident
  2420      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2421      *      | VOID Ident MethodDeclaratorRest
  2422      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2423      *      | Ident ConstructorDeclaratorRest
  2424      *      | TypeParameters Ident ConstructorDeclaratorRest
  2425      *      | ClassOrInterfaceOrEnumDeclaration
  2426      *      )
  2427      *  InterfaceBodyDeclaration =
  2428      *      ";"
  2429      *    | ModifiersOpt Type Ident
  2430      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2431      */
  2432     List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2433         if (S.token() == SEMI) {
  2434             S.nextToken();
  2435             return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
  2436         } else {
  2437             String dc = S.docComment();
  2438             int pos = S.pos();
  2439             JCModifiers mods = modifiersOpt();
  2440             if (S.token() == CLASS ||
  2441                 S.token() == INTERFACE ||
  2442                 allowEnums && S.token() == ENUM) {
  2443                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2444             } else if (S.token() == LBRACE && !isInterface &&
  2445                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2446                        mods.annotations.isEmpty()) {
  2447                 return List.<JCTree>of(block(pos, mods.flags));
  2448             } else {
  2449                 pos = S.pos();
  2450                 List<JCTypeParameter> typarams = typeParametersOpt();
  2451                 // Hack alert:  if there are type arguments but no Modifiers, the start
  2452                 // position will be lost unless we set the Modifiers position.  There
  2453                 // should be an AST node for type parameters (BugId 5005090).
  2454                 if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
  2455                     mods.pos = pos;
  2457                 Token token = S.token();
  2458                 Name name = S.name();
  2459                 pos = S.pos();
  2460                 JCExpression type;
  2461                 boolean isVoid = S.token() == VOID;
  2462                 if (isVoid) {
  2463                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  2464                     S.nextToken();
  2465                 } else {
  2466                     type = parseType();
  2468                 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
  2469                     if (isInterface || name != className)
  2470                         log.error(pos, "invalid.meth.decl.ret.type.req");
  2471                     return List.of(methodDeclaratorRest(
  2472                         pos, mods, null, names.init, typarams,
  2473                         isInterface, true, dc));
  2474                 } else {
  2475                     pos = S.pos();
  2476                     name = ident();
  2477                     if (S.token() == LPAREN) {
  2478                         return List.of(methodDeclaratorRest(
  2479                             pos, mods, type, name, typarams,
  2480                             isInterface, isVoid, dc));
  2481                     } else if (!isVoid && typarams.isEmpty()) {
  2482                         List<JCTree> defs =
  2483                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2484                                                     new ListBuffer<JCTree>()).toList();
  2485                         storeEnd(defs.last(), S.endPos());
  2486                         accept(SEMI);
  2487                         return defs;
  2488                     } else {
  2489                         pos = S.pos();
  2490                         List<JCTree> err = isVoid
  2491                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2492                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2493                             : null;
  2494                         return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
  2501     /** MethodDeclaratorRest =
  2502      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2503      *  VoidMethodDeclaratorRest =
  2504      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  2505      *  InterfaceMethodDeclaratorRest =
  2506      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  2507      *  VoidInterfaceMethodDeclaratorRest =
  2508      *      FormalParameters [THROWS TypeList] ";"
  2509      *  ConstructorDeclaratorRest =
  2510      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  2511      */
  2512     JCTree methodDeclaratorRest(int pos,
  2513                               JCModifiers mods,
  2514                               JCExpression type,
  2515                               Name name,
  2516                               List<JCTypeParameter> typarams,
  2517                               boolean isInterface, boolean isVoid,
  2518                               String dc) {
  2519         List<JCVariableDecl> params = formalParameters();
  2520         if (!isVoid) type = bracketsOpt(type);
  2521         List<JCExpression> thrown = List.nil();
  2522         if (S.token() == THROWS) {
  2523             S.nextToken();
  2524             thrown = qualidentList();
  2526         JCBlock body = null;
  2527         JCExpression defaultValue;
  2528         if (S.token() == LBRACE) {
  2529             body = block();
  2530             defaultValue = null;
  2531         } else {
  2532             if (S.token() == DEFAULT) {
  2533                 accept(DEFAULT);
  2534                 defaultValue = annotationValue();
  2535             } else {
  2536                 defaultValue = null;
  2538             accept(SEMI);
  2539             if (S.pos() <= errorEndPos) {
  2540                 // error recovery
  2541                 skip(false, true, false, false);
  2542                 if (S.token() == LBRACE) {
  2543                     body = block();
  2547         JCMethodDecl result =
  2548             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2549                                     params, thrown,
  2550                                     body, defaultValue));
  2551         attach(result, dc);
  2552         return result;
  2555     /** QualidentList = Qualident {"," Qualident}
  2556      */
  2557     List<JCExpression> qualidentList() {
  2558         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2559         ts.append(qualident());
  2560         while (S.token() == COMMA) {
  2561             S.nextToken();
  2562             ts.append(qualident());
  2564         return ts.toList();
  2567     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  2568      */
  2569     List<JCTypeParameter> typeParametersOpt() {
  2570         if (S.token() == LT) {
  2571             checkGenerics();
  2572             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  2573             S.nextToken();
  2574             typarams.append(typeParameter());
  2575             while (S.token() == COMMA) {
  2576                 S.nextToken();
  2577                 typarams.append(typeParameter());
  2579             accept(GT);
  2580             return typarams.toList();
  2581         } else {
  2582             return List.nil();
  2586     /** TypeParameter = TypeVariable [TypeParameterBound]
  2587      *  TypeParameterBound = EXTENDS Type {"&" Type}
  2588      *  TypeVariable = Ident
  2589      */
  2590     JCTypeParameter typeParameter() {
  2591         int pos = S.pos();
  2592         Name name = ident();
  2593         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  2594         if (S.token() == EXTENDS) {
  2595             S.nextToken();
  2596             bounds.append(parseType());
  2597             while (S.token() == AMP) {
  2598                 S.nextToken();
  2599                 bounds.append(parseType());
  2602         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  2605     /** FormalParameters = "(" [ FormalParameterList ] ")"
  2606      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  2607      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  2608      */
  2609     List<JCVariableDecl> formalParameters() {
  2610         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  2611         JCVariableDecl lastParam = null;
  2612         accept(LPAREN);
  2613         if (S.token() != RPAREN) {
  2614             params.append(lastParam = formalParameter());
  2615             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
  2616                 S.nextToken();
  2617                 params.append(lastParam = formalParameter());
  2620         accept(RPAREN);
  2621         return params.toList();
  2624     JCModifiers optFinal(long flags) {
  2625         JCModifiers mods = modifiersOpt();
  2626         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  2627         mods.flags |= flags;
  2628         return mods;
  2631     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  2632      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  2633      */
  2634     JCVariableDecl formalParameter() {
  2635         JCModifiers mods = optFinal(Flags.PARAMETER);
  2636         JCExpression type = parseType();
  2637         if (S.token() == ELLIPSIS) {
  2638             checkVarargs();
  2639             mods.flags |= Flags.VARARGS;
  2640             type = to(F.at(S.pos()).TypeArray(type));
  2641             S.nextToken();
  2643         return variableDeclaratorId(mods, type);
  2646 /* ---------- auxiliary methods -------------- */
  2648     /** Check that given tree is a legal expression statement.
  2649      */
  2650     protected JCExpression checkExprStat(JCExpression t) {
  2651         switch(t.getTag()) {
  2652         case JCTree.PREINC: case JCTree.PREDEC:
  2653         case JCTree.POSTINC: case JCTree.POSTDEC:
  2654         case JCTree.ASSIGN:
  2655         case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
  2656         case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
  2657         case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
  2658         case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
  2659         case JCTree.APPLY: case JCTree.NEWCLASS:
  2660         case JCTree.ERRONEOUS:
  2661             return t;
  2662         default:
  2663             log.error(t.pos, "not.stmt");
  2664             return F.at(t.pos).Erroneous(List.<JCTree>of(t));
  2668     /** Return precedence of operator represented by token,
  2669      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  2670      */
  2671     static int prec(Token token) {
  2672         int oc = optag(token);
  2673         return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
  2676     /** Return operation tag of binary operator represented by token,
  2677      *  -1 if token is not a binary operator.
  2678      */
  2679     static int optag(Token token) {
  2680         switch (token) {
  2681         case BARBAR:
  2682             return JCTree.OR;
  2683         case AMPAMP:
  2684             return JCTree.AND;
  2685         case BAR:
  2686             return JCTree.BITOR;
  2687         case BAREQ:
  2688             return JCTree.BITOR_ASG;
  2689         case CARET:
  2690             return JCTree.BITXOR;
  2691         case CARETEQ:
  2692             return JCTree.BITXOR_ASG;
  2693         case AMP:
  2694             return JCTree.BITAND;
  2695         case AMPEQ:
  2696             return JCTree.BITAND_ASG;
  2697         case EQEQ:
  2698             return JCTree.EQ;
  2699         case BANGEQ:
  2700             return JCTree.NE;
  2701         case LT:
  2702             return JCTree.LT;
  2703         case GT:
  2704             return JCTree.GT;
  2705         case LTEQ:
  2706             return JCTree.LE;
  2707         case GTEQ:
  2708             return JCTree.GE;
  2709         case LTLT:
  2710             return JCTree.SL;
  2711         case LTLTEQ:
  2712             return JCTree.SL_ASG;
  2713         case GTGT:
  2714             return JCTree.SR;
  2715         case GTGTEQ:
  2716             return JCTree.SR_ASG;
  2717         case GTGTGT:
  2718             return JCTree.USR;
  2719         case GTGTGTEQ:
  2720             return JCTree.USR_ASG;
  2721         case PLUS:
  2722             return JCTree.PLUS;
  2723         case PLUSEQ:
  2724             return JCTree.PLUS_ASG;
  2725         case SUB:
  2726             return JCTree.MINUS;
  2727         case SUBEQ:
  2728             return JCTree.MINUS_ASG;
  2729         case STAR:
  2730             return JCTree.MUL;
  2731         case STAREQ:
  2732             return JCTree.MUL_ASG;
  2733         case SLASH:
  2734             return JCTree.DIV;
  2735         case SLASHEQ:
  2736             return JCTree.DIV_ASG;
  2737         case PERCENT:
  2738             return JCTree.MOD;
  2739         case PERCENTEQ:
  2740             return JCTree.MOD_ASG;
  2741         case INSTANCEOF:
  2742             return JCTree.TYPETEST;
  2743         default:
  2744             return -1;
  2748     /** Return operation tag of unary operator represented by token,
  2749      *  -1 if token is not a binary operator.
  2750      */
  2751     static int unoptag(Token token) {
  2752         switch (token) {
  2753         case PLUS:
  2754             return JCTree.POS;
  2755         case SUB:
  2756             return JCTree.NEG;
  2757         case BANG:
  2758             return JCTree.NOT;
  2759         case TILDE:
  2760             return JCTree.COMPL;
  2761         case PLUSPLUS:
  2762             return JCTree.PREINC;
  2763         case SUBSUB:
  2764             return JCTree.PREDEC;
  2765         default:
  2766             return -1;
  2770     /** Return type tag of basic type represented by token,
  2771      *  -1 if token is not a basic type identifier.
  2772      */
  2773     static int typetag(Token token) {
  2774         switch (token) {
  2775         case BYTE:
  2776             return TypeTags.BYTE;
  2777         case CHAR:
  2778             return TypeTags.CHAR;
  2779         case SHORT:
  2780             return TypeTags.SHORT;
  2781         case INT:
  2782             return TypeTags.INT;
  2783         case LONG:
  2784             return TypeTags.LONG;
  2785         case FLOAT:
  2786             return TypeTags.FLOAT;
  2787         case DOUBLE:
  2788             return TypeTags.DOUBLE;
  2789         case BOOLEAN:
  2790             return TypeTags.BOOLEAN;
  2791         default:
  2792             return -1;
  2796     void checkGenerics() {
  2797         if (!allowGenerics) {
  2798             log.error(S.pos(), "generics.not.supported.in.source", source.name);
  2799             allowGenerics = true;
  2802     void checkVarargs() {
  2803         if (!allowVarargs) {
  2804             log.error(S.pos(), "varargs.not.supported.in.source", source.name);
  2805             allowVarargs = true;
  2808     void checkForeach() {
  2809         if (!allowForeach) {
  2810             log.error(S.pos(), "foreach.not.supported.in.source", source.name);
  2811             allowForeach = true;
  2814     void checkStaticImports() {
  2815         if (!allowStaticImport) {
  2816             log.error(S.pos(), "static.import.not.supported.in.source", source.name);
  2817             allowStaticImport = true;
  2820     void checkAnnotations() {
  2821         if (!allowAnnotations) {
  2822             log.error(S.pos(), "annotations.not.supported.in.source", source.name);
  2823             allowAnnotations = true;

mercurial