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

Wed, 20 May 2009 13:36:23 -0700

author
jjg
date
Wed, 20 May 2009 13:36:23 -0700
changeset 286
79eb8795a1de
parent 267
e2722bd43f3a
child 308
03944ee4fac4
permissions
-rw-r--r--

6827026: Change javac source and target default to 7
Reviewed-by: darcy, ohair

     1 /*
     2  * Copyright 1999-2009 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                         while (S.token() == DOT) {
   867                             S.nextToken();
   868                             mode = TYPE;
   869                             t = toP(F.at(S.pos()).Select(t, ident()));
   870                             t = typeArgumentsOpt(t);
   871                         }
   872                         t = bracketsOpt(toP(t));
   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                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1038                 // a void type (like other primitive types) to the next phase.
  1039                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1040                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
  1041                 S.nextToken();
  1042                 return ti;
  1043                 //return illegal();
  1045             break;
  1046         default:
  1047             return illegal();
  1049         if (typeArgs != null) illegal();
  1050         while (true) {
  1051             int pos1 = S.pos();
  1052             if (S.token() == LBRACKET) {
  1053                 S.nextToken();
  1054                 if ((mode & TYPE) != 0) {
  1055                     int oldmode = mode;
  1056                     mode = TYPE;
  1057                     if (S.token() == RBRACKET) {
  1058                         S.nextToken();
  1059                         t = bracketsOpt(t);
  1060                         t = toP(F.at(pos1).TypeArray(t));
  1061                         return t;
  1063                     mode = oldmode;
  1065                 if ((mode & EXPR) != 0) {
  1066                     mode = EXPR;
  1067                     JCExpression t1 = term();
  1068                     t = to(F.at(pos1).Indexed(t, t1));
  1070                 accept(RBRACKET);
  1071             } else if (S.token() == DOT) {
  1072                 S.nextToken();
  1073                 typeArgs = typeArgumentsOpt(EXPR);
  1074                 if (S.token() == SUPER && (mode & EXPR) != 0) {
  1075                     mode = EXPR;
  1076                     t = to(F.at(pos1).Select(t, names._super));
  1077                     S.nextToken();
  1078                     t = arguments(typeArgs, t);
  1079                     typeArgs = null;
  1080                 } else if (S.token() == NEW && (mode & EXPR) != 0) {
  1081                     if (typeArgs != null) return illegal();
  1082                     mode = EXPR;
  1083                     int pos2 = S.pos();
  1084                     S.nextToken();
  1085                     if (S.token() == LT) typeArgs = typeArguments();
  1086                     t = innerCreator(pos2, typeArgs, t);
  1087                     typeArgs = null;
  1088                 } else {
  1089                     t = toP(F.at(pos1).Select(t, ident()));
  1090                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1091                     typeArgs = null;
  1093             } else {
  1094                 break;
  1097         while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
  1098             mode = EXPR;
  1099             t = to(F.at(S.pos()).Unary(
  1100                   S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
  1101             S.nextToken();
  1103         return toP(t);
  1106     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1107      */
  1108     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1109         S.nextToken();
  1110         if (S.token() == LPAREN || typeArgs != null) {
  1111             t = arguments(typeArgs, t);
  1112         } else {
  1113             int pos = S.pos();
  1114             accept(DOT);
  1115             typeArgs = (S.token() == LT) ? typeArguments() : null;
  1116             t = toP(F.at(pos).Select(t, ident()));
  1117             t = argumentsOpt(typeArgs, t);
  1119         return t;
  1122     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1123      */
  1124     JCPrimitiveTypeTree basicType() {
  1125         JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
  1126         S.nextToken();
  1127         return t;
  1130     /** ArgumentsOpt = [ Arguments ]
  1131      */
  1132     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1133         if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
  1134             mode = EXPR;
  1135             return arguments(typeArgs, t);
  1136         } else {
  1137             return t;
  1141     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1142      */
  1143     List<JCExpression> arguments() {
  1144         ListBuffer<JCExpression> args = lb();
  1145         if (S.token() == LPAREN) {
  1146             S.nextToken();
  1147             if (S.token() != RPAREN) {
  1148                 args.append(parseExpression());
  1149                 while (S.token() == COMMA) {
  1150                     S.nextToken();
  1151                     args.append(parseExpression());
  1154             accept(RPAREN);
  1155         } else {
  1156             syntaxError(S.pos(), "expected", LPAREN);
  1158         return args.toList();
  1161     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1162         int pos = S.pos();
  1163         List<JCExpression> args = arguments();
  1164         return toP(F.at(pos).Apply(typeArgs, t, args));
  1167     /**  TypeArgumentsOpt = [ TypeArguments ]
  1168      */
  1169     JCExpression typeArgumentsOpt(JCExpression t) {
  1170         if (S.token() == LT &&
  1171             (mode & TYPE) != 0 &&
  1172             (mode & NOPARAMS) == 0) {
  1173             mode = TYPE;
  1174             checkGenerics();
  1175             return typeArguments(t);
  1176         } else {
  1177             return t;
  1180     List<JCExpression> typeArgumentsOpt() {
  1181         return typeArgumentsOpt(TYPE);
  1184     List<JCExpression> typeArgumentsOpt(int useMode) {
  1185         if (S.token() == LT) {
  1186             checkGenerics();
  1187             if ((mode & useMode) == 0 ||
  1188                 (mode & NOPARAMS) != 0) {
  1189                 illegal();
  1191             mode = useMode;
  1192             return typeArguments();
  1194         return null;
  1197     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1198      */
  1199     List<JCExpression> typeArguments() {
  1200         ListBuffer<JCExpression> args = lb();
  1201         if (S.token() == LT) {
  1202             S.nextToken();
  1203             args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1204             while (S.token() == COMMA) {
  1205                 S.nextToken();
  1206                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1208             switch (S.token()) {
  1209             case GTGTGTEQ:
  1210                 S.token(GTGTEQ);
  1211                 break;
  1212             case GTGTEQ:
  1213                 S.token(GTEQ);
  1214                 break;
  1215             case GTEQ:
  1216                 S.token(EQ);
  1217                 break;
  1218             case GTGTGT:
  1219                 S.token(GTGT);
  1220                 break;
  1221             case GTGT:
  1222                 S.token(GT);
  1223                 break;
  1224             default:
  1225                 accept(GT);
  1226                 break;
  1228         } else {
  1229             syntaxError(S.pos(), "expected", LT);
  1231         return args.toList();
  1234     /** TypeArgument = Type
  1235      *               | "?"
  1236      *               | "?" EXTENDS Type {"&" Type}
  1237      *               | "?" SUPER Type
  1238      */
  1239     JCExpression typeArgument() {
  1240         if (S.token() != QUES) return parseType();
  1241         int pos = S.pos();
  1242         S.nextToken();
  1243         if (S.token() == EXTENDS) {
  1244             TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
  1245             S.nextToken();
  1246             return F.at(pos).Wildcard(t, parseType());
  1247         } else if (S.token() == SUPER) {
  1248             TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
  1249             S.nextToken();
  1250             return F.at(pos).Wildcard(t, parseType());
  1251         } else if (S.token() == IDENTIFIER) {
  1252             //error recovery
  1253             reportSyntaxError(S.prevEndPos(), "expected3",
  1254                     GT, EXTENDS, SUPER);
  1255             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1256             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1257             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
  1258             return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1259         } else {
  1260             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1261             return toP(F.at(pos).Wildcard(t, null));
  1265     JCTypeApply typeArguments(JCExpression t) {
  1266         int pos = S.pos();
  1267         List<JCExpression> args = typeArguments();
  1268         return toP(F.at(pos).TypeApply(t, args));
  1271     /** BracketsOpt = {"[" "]"}
  1272      */
  1273     private JCExpression bracketsOpt(JCExpression t) {
  1274         if (S.token() == LBRACKET) {
  1275             int pos = S.pos();
  1276             S.nextToken();
  1277             t = bracketsOptCont(t, pos);
  1278             F.at(pos);
  1280         return t;
  1283     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1284         accept(RBRACKET);
  1285         t = bracketsOpt(t);
  1286         return toP(F.at(pos).TypeArray(t));
  1289     /** BracketsSuffixExpr = "." CLASS
  1290      *  BracketsSuffixType =
  1291      */
  1292     JCExpression bracketsSuffix(JCExpression t) {
  1293         if ((mode & EXPR) != 0 && S.token() == DOT) {
  1294             mode = EXPR;
  1295             int pos = S.pos();
  1296             S.nextToken();
  1297             accept(CLASS);
  1298             if (S.pos() == errorEndPos) {
  1299                 // error recovery
  1300                 Name name = null;
  1301                 if (S.token() == IDENTIFIER) {
  1302                     name = S.name();
  1303                     S.nextToken();
  1304                 } else {
  1305                     name = names.error;
  1307                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1308             } else {
  1309                 t = toP(F.at(pos).Select(t, names._class));
  1311         } else if ((mode & TYPE) != 0) {
  1312             mode = TYPE;
  1313         } else {
  1314             syntaxError(S.pos(), "dot.class.expected");
  1316         return t;
  1319     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1320      */
  1321     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1322         switch (S.token()) {
  1323         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1324         case DOUBLE: case BOOLEAN:
  1325             if (typeArgs == null)
  1326                 return arrayCreatorRest(newpos, basicType());
  1327             break;
  1328         default:
  1330         JCExpression t = qualident();
  1331         int oldmode = mode;
  1332         mode = TYPE;
  1333         if (S.token() == LT) {
  1334             checkGenerics();
  1335             t = typeArguments(t);
  1337         while (S.token() == DOT) {
  1338             int pos = S.pos();
  1339             S.nextToken();
  1340             t = toP(F.at(pos).Select(t, ident()));
  1341             if (S.token() == LT) {
  1342                 checkGenerics();
  1343                 t = typeArguments(t);
  1346         mode = oldmode;
  1347         if (S.token() == LBRACKET) {
  1348             JCExpression e = arrayCreatorRest(newpos, t);
  1349             if (typeArgs != null) {
  1350                 int pos = newpos;
  1351                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1352                     // note: this should always happen but we should
  1353                     // not rely on this as the parser is continuously
  1354                     // modified to improve error recovery.
  1355                     pos = typeArgs.head.pos;
  1357                 setErrorEndPos(S.prevEndPos());
  1358                 reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
  1359                 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
  1361             return e;
  1362         } else if (S.token() == LPAREN) {
  1363             return classCreatorRest(newpos, null, typeArgs, t);
  1364         } else {
  1365             reportSyntaxError(S.pos(), "expected2",
  1366                                LPAREN, LBRACKET);
  1367             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1368             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1372     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1373      */
  1374     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1375         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
  1376         if (S.token() == LT) {
  1377             checkGenerics();
  1378             t = typeArguments(t);
  1380         return classCreatorRest(newpos, encl, typeArgs, t);
  1383     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1384      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1385      */
  1386     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1387         accept(LBRACKET);
  1388         if (S.token() == RBRACKET) {
  1389             accept(RBRACKET);
  1390             elemtype = bracketsOpt(elemtype);
  1391             if (S.token() == LBRACE) {
  1392                 return arrayInitializer(newpos, elemtype);
  1393             } else {
  1394                 return syntaxError(S.pos(), "array.dimension.missing");
  1396         } else {
  1397             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1398             dims.append(parseExpression());
  1399             accept(RBRACKET);
  1400             while (S.token() == LBRACKET) {
  1401                 int pos = S.pos();
  1402                 S.nextToken();
  1403                 if (S.token() == RBRACKET) {
  1404                     elemtype = bracketsOptCont(elemtype, pos);
  1405                 } else {
  1406                     dims.append(parseExpression());
  1407                     accept(RBRACKET);
  1410             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1414     /** ClassCreatorRest = Arguments [ClassBody]
  1415      */
  1416     JCExpression classCreatorRest(int newpos,
  1417                                   JCExpression encl,
  1418                                   List<JCExpression> typeArgs,
  1419                                   JCExpression t)
  1421         List<JCExpression> args = arguments();
  1422         JCClassDecl body = null;
  1423         if (S.token() == LBRACE) {
  1424             int pos = S.pos();
  1425             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1426             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1427             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1429         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1432     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1433      */
  1434     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1435         accept(LBRACE);
  1436         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1437         if (S.token() == COMMA) {
  1438             S.nextToken();
  1439         } else if (S.token() != RBRACE) {
  1440             elems.append(variableInitializer());
  1441             while (S.token() == COMMA) {
  1442                 S.nextToken();
  1443                 if (S.token() == RBRACE) break;
  1444                 elems.append(variableInitializer());
  1447         accept(RBRACE);
  1448         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1451     /** VariableInitializer = ArrayInitializer | Expression
  1452      */
  1453     public JCExpression variableInitializer() {
  1454         return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
  1457     /** ParExpression = "(" Expression ")"
  1458      */
  1459     JCExpression parExpression() {
  1460         accept(LPAREN);
  1461         JCExpression t = parseExpression();
  1462         accept(RPAREN);
  1463         return t;
  1466     /** Block = "{" BlockStatements "}"
  1467      */
  1468     JCBlock block(int pos, long flags) {
  1469         accept(LBRACE);
  1470         List<JCStatement> stats = blockStatements();
  1471         JCBlock t = F.at(pos).Block(flags, stats);
  1472         while (S.token() == CASE || S.token() == DEFAULT) {
  1473             syntaxError("orphaned", S.token());
  1474             switchBlockStatementGroups();
  1476         // the Block node has a field "endpos" for first char of last token, which is
  1477         // usually but not necessarily the last char of the last token.
  1478         t.endpos = S.pos();
  1479         accept(RBRACE);
  1480         return toP(t);
  1483     public JCBlock block() {
  1484         return block(S.pos(), 0);
  1487     /** BlockStatements = { BlockStatement }
  1488      *  BlockStatement  = LocalVariableDeclarationStatement
  1489      *                  | ClassOrInterfaceOrEnumDeclaration
  1490      *                  | [Ident ":"] Statement
  1491      *  LocalVariableDeclarationStatement
  1492      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1493      */
  1494     @SuppressWarnings("fallthrough")
  1495     List<JCStatement> blockStatements() {
  1496 //todo: skip to anchor on error(?)
  1497         int lastErrPos = -1;
  1498         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1499         while (true) {
  1500             int pos = S.pos();
  1501             switch (S.token()) {
  1502             case RBRACE: case CASE: case DEFAULT: case EOF:
  1503                 return stats.toList();
  1504             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1505             case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1506             case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1507                 stats.append(parseStatement());
  1508                 break;
  1509             case MONKEYS_AT:
  1510             case FINAL: {
  1511                 String dc = S.docComment();
  1512                 JCModifiers mods = modifiersOpt();
  1513                 if (S.token() == INTERFACE ||
  1514                     S.token() == CLASS ||
  1515                     allowEnums && S.token() == ENUM) {
  1516                     stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1517                 } else {
  1518                     JCExpression t = parseType();
  1519                     stats.appendList(variableDeclarators(mods, t,
  1520                                                          new ListBuffer<JCStatement>()));
  1521                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1522                     storeEnd(stats.elems.last(), S.endPos());
  1523                     accept(SEMI);
  1525                 break;
  1527             case ABSTRACT: case STRICTFP: {
  1528                 String dc = S.docComment();
  1529                 JCModifiers mods = modifiersOpt();
  1530                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1531                 break;
  1533             case INTERFACE:
  1534             case CLASS:
  1535                 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1536                                                                S.docComment()));
  1537                 break;
  1538             case ENUM:
  1539             case ASSERT:
  1540                 if (allowEnums && S.token() == ENUM) {
  1541                     log.error(S.pos(), "local.enum");
  1542                     stats.
  1543                         append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1544                                                                  S.docComment()));
  1545                     break;
  1546                 } else if (allowAsserts && S.token() == ASSERT) {
  1547                     stats.append(parseStatement());
  1548                     break;
  1550                 /* fall through to default */
  1551             default:
  1552                 Name name = S.name();
  1553                 JCExpression t = term(EXPR | TYPE);
  1554                 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
  1555                     S.nextToken();
  1556                     JCStatement stat = parseStatement();
  1557                     stats.append(F.at(pos).Labelled(name, stat));
  1558                 } else if ((lastmode & TYPE) != 0 &&
  1559                            (S.token() == IDENTIFIER ||
  1560                             S.token() == ASSERT ||
  1561                             S.token() == ENUM)) {
  1562                     pos = S.pos();
  1563                     JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1564                     F.at(pos);
  1565                     stats.appendList(variableDeclarators(mods, t,
  1566                                                          new ListBuffer<JCStatement>()));
  1567                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1568                     storeEnd(stats.elems.last(), S.endPos());
  1569                     accept(SEMI);
  1570                 } else {
  1571                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1572                     stats.append(to(F.at(pos).Exec(checkExprStat(t))));
  1573                     accept(SEMI);
  1577             // error recovery
  1578             if (S.pos() == lastErrPos)
  1579                 return stats.toList();
  1580             if (S.pos() <= errorEndPos) {
  1581                 skip(false, true, true, true);
  1582                 lastErrPos = S.pos();
  1585             // ensure no dangling /** @deprecated */ active
  1586             S.resetDeprecatedFlag();
  1590     /** Statement =
  1591      *       Block
  1592      *     | IF ParExpression Statement [ELSE Statement]
  1593      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1594      *     | FOR "(" FormalParameter : Expression ")" Statement
  1595      *     | WHILE ParExpression Statement
  1596      *     | DO Statement WHILE ParExpression ";"
  1597      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1598      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1599      *     | SYNCHRONIZED ParExpression Block
  1600      *     | RETURN [Expression] ";"
  1601      *     | THROW Expression ";"
  1602      *     | BREAK [Ident] ";"
  1603      *     | CONTINUE [Ident] ";"
  1604      *     | ASSERT Expression [ ":" Expression ] ";"
  1605      *     | ";"
  1606      *     | ExpressionStatement
  1607      *     | Ident ":" Statement
  1608      */
  1609     @SuppressWarnings("fallthrough")
  1610     public JCStatement parseStatement() {
  1611         int pos = S.pos();
  1612         switch (S.token()) {
  1613         case LBRACE:
  1614             return block();
  1615         case IF: {
  1616             S.nextToken();
  1617             JCExpression cond = parExpression();
  1618             JCStatement thenpart = parseStatement();
  1619             JCStatement elsepart = null;
  1620             if (S.token() == ELSE) {
  1621                 S.nextToken();
  1622                 elsepart = parseStatement();
  1624             return F.at(pos).If(cond, thenpart, elsepart);
  1626         case FOR: {
  1627             S.nextToken();
  1628             accept(LPAREN);
  1629             List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
  1630             if (inits.length() == 1 &&
  1631                 inits.head.getTag() == JCTree.VARDEF &&
  1632                 ((JCVariableDecl) inits.head).init == null &&
  1633                 S.token() == COLON) {
  1634                 checkForeach();
  1635                 JCVariableDecl var = (JCVariableDecl)inits.head;
  1636                 accept(COLON);
  1637                 JCExpression expr = parseExpression();
  1638                 accept(RPAREN);
  1639                 JCStatement body = parseStatement();
  1640                 return F.at(pos).ForeachLoop(var, expr, body);
  1641             } else {
  1642                 accept(SEMI);
  1643                 JCExpression cond = S.token() == SEMI ? null : parseExpression();
  1644                 accept(SEMI);
  1645                 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  1646                 accept(RPAREN);
  1647                 JCStatement body = parseStatement();
  1648                 return F.at(pos).ForLoop(inits, cond, steps, body);
  1651         case WHILE: {
  1652             S.nextToken();
  1653             JCExpression cond = parExpression();
  1654             JCStatement body = parseStatement();
  1655             return F.at(pos).WhileLoop(cond, body);
  1657         case DO: {
  1658             S.nextToken();
  1659             JCStatement body = parseStatement();
  1660             accept(WHILE);
  1661             JCExpression cond = parExpression();
  1662             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  1663             accept(SEMI);
  1664             return t;
  1666         case TRY: {
  1667             S.nextToken();
  1668             JCBlock body = block();
  1669             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  1670             JCBlock finalizer = null;
  1671             if (S.token() == CATCH || S.token() == FINALLY) {
  1672                 while (S.token() == CATCH) catchers.append(catchClause());
  1673                 if (S.token() == FINALLY) {
  1674                     S.nextToken();
  1675                     finalizer = block();
  1677             } else {
  1678                 log.error(pos, "try.without.catch.or.finally");
  1680             return F.at(pos).Try(body, catchers.toList(), finalizer);
  1682         case SWITCH: {
  1683             S.nextToken();
  1684             JCExpression selector = parExpression();
  1685             accept(LBRACE);
  1686             List<JCCase> cases = switchBlockStatementGroups();
  1687             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  1688             accept(RBRACE);
  1689             return t;
  1691         case SYNCHRONIZED: {
  1692             S.nextToken();
  1693             JCExpression lock = parExpression();
  1694             JCBlock body = block();
  1695             return F.at(pos).Synchronized(lock, body);
  1697         case RETURN: {
  1698             S.nextToken();
  1699             JCExpression result = S.token() == SEMI ? null : parseExpression();
  1700             JCReturn t = to(F.at(pos).Return(result));
  1701             accept(SEMI);
  1702             return t;
  1704         case THROW: {
  1705             S.nextToken();
  1706             JCExpression exc = parseExpression();
  1707             JCThrow t = to(F.at(pos).Throw(exc));
  1708             accept(SEMI);
  1709             return t;
  1711         case BREAK: {
  1712             S.nextToken();
  1713             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1714             JCBreak t = to(F.at(pos).Break(label));
  1715             accept(SEMI);
  1716             return t;
  1718         case CONTINUE: {
  1719             S.nextToken();
  1720             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1721             JCContinue t =  to(F.at(pos).Continue(label));
  1722             accept(SEMI);
  1723             return t;
  1725         case SEMI:
  1726             S.nextToken();
  1727             return toP(F.at(pos).Skip());
  1728         case ELSE:
  1729             return toP(F.Exec(syntaxError("else.without.if")));
  1730         case FINALLY:
  1731             return toP(F.Exec(syntaxError("finally.without.try")));
  1732         case CATCH:
  1733             return toP(F.Exec(syntaxError("catch.without.try")));
  1734         case ASSERT: {
  1735             if (allowAsserts && S.token() == ASSERT) {
  1736                 S.nextToken();
  1737                 JCExpression assertion = parseExpression();
  1738                 JCExpression message = null;
  1739                 if (S.token() == COLON) {
  1740                     S.nextToken();
  1741                     message = parseExpression();
  1743                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  1744                 accept(SEMI);
  1745                 return t;
  1747             /* else fall through to default case */
  1749         case ENUM:
  1750         default:
  1751             Name name = S.name();
  1752             JCExpression expr = parseExpression();
  1753             if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
  1754                 S.nextToken();
  1755                 JCStatement stat = parseStatement();
  1756                 return F.at(pos).Labelled(name, stat);
  1757             } else {
  1758                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1759                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  1760                 accept(SEMI);
  1761                 return stat;
  1766     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  1767      */
  1768     JCCatch catchClause() {
  1769         int pos = S.pos();
  1770         accept(CATCH);
  1771         accept(LPAREN);
  1772         JCVariableDecl formal =
  1773             variableDeclaratorId(optFinal(Flags.PARAMETER),
  1774                                  qualident());
  1775         accept(RPAREN);
  1776         JCBlock body = block();
  1777         return F.at(pos).Catch(formal, body);
  1780     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  1781      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  1782      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  1783      */
  1784     List<JCCase> switchBlockStatementGroups() {
  1785         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  1786         while (true) {
  1787             int pos = S.pos();
  1788             switch (S.token()) {
  1789             case CASE: {
  1790                 S.nextToken();
  1791                 JCExpression pat = parseExpression();
  1792                 accept(COLON);
  1793                 List<JCStatement> stats = blockStatements();
  1794                 JCCase c = F.at(pos).Case(pat, stats);
  1795                 if (stats.isEmpty())
  1796                     storeEnd(c, S.prevEndPos());
  1797                 cases.append(c);
  1798                 break;
  1800             case DEFAULT: {
  1801                 S.nextToken();
  1802                 accept(COLON);
  1803                 List<JCStatement> stats = blockStatements();
  1804                 JCCase c = F.at(pos).Case(null, stats);
  1805                 if (stats.isEmpty())
  1806                     storeEnd(c, S.prevEndPos());
  1807                 cases.append(c);
  1808                 break;
  1810             case RBRACE: case EOF:
  1811                 return cases.toList();
  1812             default:
  1813                 S.nextToken(); // to ensure progress
  1814                 syntaxError(pos, "expected3",
  1815                     CASE, DEFAULT, RBRACE);
  1820     /** MoreStatementExpressions = { COMMA StatementExpression }
  1821      */
  1822     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  1823                                                                     JCExpression first,
  1824                                                                     T stats) {
  1825         // This Exec is a "StatementExpression"; it subsumes no terminating token
  1826         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  1827         while (S.token() == COMMA) {
  1828             S.nextToken();
  1829             pos = S.pos();
  1830             JCExpression t = parseExpression();
  1831             // This Exec is a "StatementExpression"; it subsumes no terminating token
  1832             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  1834         return stats;
  1837     /** ForInit = StatementExpression MoreStatementExpressions
  1838      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  1839      */
  1840     List<JCStatement> forInit() {
  1841         ListBuffer<JCStatement> stats = lb();
  1842         int pos = S.pos();
  1843         if (S.token() == FINAL || S.token() == MONKEYS_AT) {
  1844             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  1845         } else {
  1846             JCExpression t = term(EXPR | TYPE);
  1847             if ((lastmode & TYPE) != 0 &&
  1848                 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
  1849                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  1850             else
  1851                 return moreStatementExpressions(pos, t, stats).toList();
  1855     /** ForUpdate = StatementExpression MoreStatementExpressions
  1856      */
  1857     List<JCExpressionStatement> forUpdate() {
  1858         return moreStatementExpressions(S.pos(),
  1859                                         parseExpression(),
  1860                                         new ListBuffer<JCExpressionStatement>()).toList();
  1863     /** AnnotationsOpt = { '@' Annotation }
  1864      */
  1865     List<JCAnnotation> annotationsOpt() {
  1866         if (S.token() != MONKEYS_AT) return List.nil(); // optimization
  1867         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  1868         while (S.token() == MONKEYS_AT) {
  1869             int pos = S.pos();
  1870             S.nextToken();
  1871             buf.append(annotation(pos));
  1873         return buf.toList();
  1876     /** ModifiersOpt = { Modifier }
  1877      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  1878      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  1879      *           | "@" Annotation
  1880      */
  1881     JCModifiers modifiersOpt() {
  1882         return modifiersOpt(null);
  1884     JCModifiers modifiersOpt(JCModifiers partial) {
  1885         long flags = (partial == null) ? 0 : partial.flags;
  1886         if (S.deprecatedFlag()) {
  1887             flags |= Flags.DEPRECATED;
  1888             S.resetDeprecatedFlag();
  1890         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  1891         if (partial != null) annotations.appendList(partial.annotations);
  1892         int pos = S.pos();
  1893         int lastPos = Position.NOPOS;
  1894     loop:
  1895         while (true) {
  1896             long flag;
  1897             switch (S.token()) {
  1898             case PRIVATE     : flag = Flags.PRIVATE; break;
  1899             case PROTECTED   : flag = Flags.PROTECTED; break;
  1900             case PUBLIC      : flag = Flags.PUBLIC; break;
  1901             case STATIC      : flag = Flags.STATIC; break;
  1902             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  1903             case FINAL       : flag = Flags.FINAL; break;
  1904             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  1905             case NATIVE      : flag = Flags.NATIVE; break;
  1906             case VOLATILE    : flag = Flags.VOLATILE; break;
  1907             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  1908             case STRICTFP    : flag = Flags.STRICTFP; break;
  1909             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  1910             default: break loop;
  1912             if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
  1913             lastPos = S.pos();
  1914             S.nextToken();
  1915             if (flag == Flags.ANNOTATION) {
  1916                 checkAnnotations();
  1917                 if (S.token() != INTERFACE) {
  1918                 JCAnnotation ann = annotation(lastPos);
  1919                 // if first modifier is an annotation, set pos to annotation's.
  1920                 if (flags == 0 && annotations.isEmpty())
  1921                     pos = ann.pos;
  1922                 annotations.append(ann);
  1923                 lastPos = ann.pos;
  1924                     flag = 0;
  1927             flags |= flag;
  1929         switch (S.token()) {
  1930         case ENUM: flags |= Flags.ENUM; break;
  1931         case INTERFACE: flags |= Flags.INTERFACE; break;
  1932         default: break;
  1935         /* A modifiers tree with no modifier tokens or annotations
  1936          * has no text position. */
  1937         if (flags == 0 && annotations.isEmpty())
  1938             pos = Position.NOPOS;
  1940         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  1941         if (pos != Position.NOPOS)
  1942             storeEnd(mods, S.prevEndPos());
  1943         return mods;
  1946     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  1947      * @param pos position of "@" token
  1948      */
  1949     JCAnnotation annotation(int pos) {
  1950         // accept(AT); // AT consumed by caller
  1951         checkAnnotations();
  1952         JCTree ident = qualident();
  1953         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  1954         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  1955         storeEnd(ann, S.prevEndPos());
  1956         return ann;
  1959     List<JCExpression> annotationFieldValuesOpt() {
  1960         return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  1963     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  1964     List<JCExpression> annotationFieldValues() {
  1965         accept(LPAREN);
  1966         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  1967         if (S.token() != RPAREN) {
  1968             buf.append(annotationFieldValue());
  1969             while (S.token() == COMMA) {
  1970                 S.nextToken();
  1971                 buf.append(annotationFieldValue());
  1974         accept(RPAREN);
  1975         return buf.toList();
  1978     /** AnnotationFieldValue    = AnnotationValue
  1979      *                          | Identifier "=" AnnotationValue
  1980      */
  1981     JCExpression annotationFieldValue() {
  1982         if (S.token() == IDENTIFIER) {
  1983             mode = EXPR;
  1984             JCExpression t1 = term1();
  1985             if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
  1986                 int pos = S.pos();
  1987                 accept(EQ);
  1988                 return toP(F.at(pos).Assign(t1, annotationValue()));
  1989             } else {
  1990                 return t1;
  1993         return annotationValue();
  1996     /* AnnotationValue          = ConditionalExpression
  1997      *                          | Annotation
  1998      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
  1999      */
  2000     JCExpression annotationValue() {
  2001         int pos;
  2002         switch (S.token()) {
  2003         case MONKEYS_AT:
  2004             pos = S.pos();
  2005             S.nextToken();
  2006             return annotation(pos);
  2007         case LBRACE:
  2008             pos = S.pos();
  2009             accept(LBRACE);
  2010             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2011             if (S.token() != RBRACE) {
  2012                 buf.append(annotationValue());
  2013                 while (S.token() == COMMA) {
  2014                     S.nextToken();
  2015                     if (S.token() == RPAREN) break;
  2016                     buf.append(annotationValue());
  2019             accept(RBRACE);
  2020             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2021         default:
  2022             mode = EXPR;
  2023             return term1();
  2027     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2028      */
  2029     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2030                                                                          JCExpression type,
  2031                                                                          T vdefs)
  2033         return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
  2036     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2037      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2039      *  @param reqInit  Is an initializer always required?
  2040      *  @param dc       The documentation comment for the variable declarations, or null.
  2041      */
  2042     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2043                                                                      JCModifiers mods,
  2044                                                                      JCExpression type,
  2045                                                                      Name name,
  2046                                                                      boolean reqInit,
  2047                                                                      String dc,
  2048                                                                      T vdefs)
  2050         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2051         while (S.token() == COMMA) {
  2052             // All but last of multiple declarators subsume a comma
  2053             storeEnd((JCTree)vdefs.elems.last(), S.endPos());
  2054             S.nextToken();
  2055             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2057         return vdefs;
  2060     /** VariableDeclarator = Ident VariableDeclaratorRest
  2061      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2062      */
  2063     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
  2064         return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
  2067     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2068      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2070      *  @param reqInit  Is an initializer always required?
  2071      *  @param dc       The documentation comment for the variable declarations, or null.
  2072      */
  2073     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2074                                   boolean reqInit, String dc) {
  2075         type = bracketsOpt(type);
  2076         JCExpression init = null;
  2077         if (S.token() == EQ) {
  2078             S.nextToken();
  2079             init = variableInitializer();
  2081         else if (reqInit) syntaxError(S.pos(), "expected", EQ);
  2082         JCVariableDecl result =
  2083             toP(F.at(pos).VarDef(mods, name, type, init));
  2084         attach(result, dc);
  2085         return result;
  2088     /** VariableDeclaratorId = Ident BracketsOpt
  2089      */
  2090     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2091         int pos = S.pos();
  2092         Name name = ident();
  2093         if ((mods.flags & Flags.VARARGS) == 0)
  2094             type = bracketsOpt(type);
  2095         return toP(F.at(pos).VarDef(mods, name, type, null));
  2098     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2099      */
  2100     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2101         int pos = S.pos();
  2102         JCExpression pid = null;
  2103         String dc = S.docComment();
  2104         JCModifiers mods = null;
  2105         List<JCAnnotation> packageAnnotations = List.nil();
  2106         if (S.token() == MONKEYS_AT)
  2107             mods = modifiersOpt();
  2109         if (S.token() == PACKAGE) {
  2110             if (mods != null) {
  2111                 checkNoMods(mods.flags);
  2112                 packageAnnotations = mods.annotations;
  2113                 mods = null;
  2115             S.nextToken();
  2116             pid = qualident();
  2117             accept(SEMI);
  2119         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2120         boolean checkForImports = true;
  2121         while (S.token() != EOF) {
  2122             if (S.pos() <= errorEndPos) {
  2123                 // error recovery
  2124                 skip(checkForImports, false, false, false);
  2125                 if (S.token() == EOF)
  2126                     break;
  2128             if (checkForImports && mods == null && S.token() == IMPORT) {
  2129                 defs.append(importDeclaration());
  2130             } else {
  2131                 JCTree def = typeDeclaration(mods);
  2132                 if (def instanceof JCExpressionStatement)
  2133                     def = ((JCExpressionStatement)def).expr;
  2134                 defs.append(def);
  2135                 if (def instanceof JCClassDecl)
  2136                     checkForImports = false;
  2137                 mods = null;
  2140         JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
  2141         attach(toplevel, dc);
  2142         if (defs.elems.isEmpty())
  2143             storeEnd(toplevel, S.prevEndPos());
  2144         if (keepDocComments)
  2145             toplevel.docComments = docComments;
  2146         if (keepLineMap)
  2147             toplevel.lineMap = S.getLineMap();
  2148         return toplevel;
  2151     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2152      */
  2153     JCTree importDeclaration() {
  2154         int pos = S.pos();
  2155         S.nextToken();
  2156         boolean importStatic = false;
  2157         if (S.token() == STATIC) {
  2158             checkStaticImports();
  2159             importStatic = true;
  2160             S.nextToken();
  2162         JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
  2163         do {
  2164             int pos1 = S.pos();
  2165             accept(DOT);
  2166             if (S.token() == STAR) {
  2167                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2168                 S.nextToken();
  2169                 break;
  2170             } else {
  2171                 pid = toP(F.at(pos1).Select(pid, ident()));
  2173         } while (S.token() == DOT);
  2174         accept(SEMI);
  2175         return toP(F.at(pos).Import(pid, importStatic));
  2178     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2179      *                  | ";"
  2180      */
  2181     JCTree typeDeclaration(JCModifiers mods) {
  2182         int pos = S.pos();
  2183         if (mods == null && S.token() == SEMI) {
  2184             S.nextToken();
  2185             return toP(F.at(pos).Skip());
  2186         } else {
  2187             String dc = S.docComment();
  2188             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
  2192     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2193      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2194      *  @param mods     Any modifiers starting the class or interface declaration
  2195      *  @param dc       The documentation comment for the class, or null.
  2196      */
  2197     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
  2198         if (S.token() == CLASS) {
  2199             return classDeclaration(mods, dc);
  2200         } else if (S.token() == INTERFACE) {
  2201             return interfaceDeclaration(mods, dc);
  2202         } else if (allowEnums) {
  2203             if (S.token() == ENUM) {
  2204                 return enumDeclaration(mods, dc);
  2205             } else {
  2206                 int pos = S.pos();
  2207                 List<JCTree> errs;
  2208                 if (S.token() == IDENTIFIER) {
  2209                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2210                     setErrorEndPos(S.pos());
  2211                 } else {
  2212                     errs = List.<JCTree>of(mods);
  2214                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2215                                               CLASS, INTERFACE, ENUM)));
  2217         } else {
  2218             if (S.token() == ENUM) {
  2219                 log.error(S.pos(), "enums.not.supported.in.source", source.name);
  2220                 allowEnums = true;
  2221                 return enumDeclaration(mods, dc);
  2223             int pos = S.pos();
  2224             List<JCTree> errs;
  2225             if (S.token() == IDENTIFIER) {
  2226                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2227                 setErrorEndPos(S.pos());
  2228             } else {
  2229                 errs = List.<JCTree>of(mods);
  2231             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2232                                           CLASS, INTERFACE)));
  2236     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2237      *                     [IMPLEMENTS TypeList] ClassBody
  2238      *  @param mods    The modifiers starting the class declaration
  2239      *  @param dc       The documentation comment for the class, or null.
  2240      */
  2241     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
  2242         int pos = S.pos();
  2243         accept(CLASS);
  2244         Name name = ident();
  2246         List<JCTypeParameter> typarams = typeParametersOpt();
  2248         JCTree extending = null;
  2249         if (S.token() == EXTENDS) {
  2250             S.nextToken();
  2251             extending = parseType();
  2253         List<JCExpression> implementing = List.nil();
  2254         if (S.token() == IMPLEMENTS) {
  2255             S.nextToken();
  2256             implementing = typeList();
  2258         List<JCTree> defs = classOrInterfaceBody(name, false);
  2259         JCClassDecl result = toP(F.at(pos).ClassDef(
  2260             mods, name, typarams, extending, implementing, defs));
  2261         attach(result, dc);
  2262         return result;
  2265     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2266      *                         [EXTENDS TypeList] InterfaceBody
  2267      *  @param mods    The modifiers starting the interface declaration
  2268      *  @param dc       The documentation comment for the interface, or null.
  2269      */
  2270     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
  2271         int pos = S.pos();
  2272         accept(INTERFACE);
  2273         Name name = ident();
  2275         List<JCTypeParameter> typarams = typeParametersOpt();
  2277         List<JCExpression> extending = List.nil();
  2278         if (S.token() == EXTENDS) {
  2279             S.nextToken();
  2280             extending = typeList();
  2282         List<JCTree> defs = classOrInterfaceBody(name, true);
  2283         JCClassDecl result = toP(F.at(pos).ClassDef(
  2284             mods, name, typarams, null, extending, defs));
  2285         attach(result, dc);
  2286         return result;
  2289     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2290      *  @param mods    The modifiers starting the enum declaration
  2291      *  @param dc       The documentation comment for the enum, or null.
  2292      */
  2293     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
  2294         int pos = S.pos();
  2295         accept(ENUM);
  2296         Name name = ident();
  2298         List<JCExpression> implementing = List.nil();
  2299         if (S.token() == IMPLEMENTS) {
  2300             S.nextToken();
  2301             implementing = typeList();
  2304         List<JCTree> defs = enumBody(name);
  2305         JCModifiers newMods =
  2306             F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
  2307         JCClassDecl result = toP(F.at(pos).
  2308             ClassDef(newMods, name, List.<JCTypeParameter>nil(),
  2309                 null, implementing, defs));
  2310         attach(result, dc);
  2311         return result;
  2314     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2315      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2316      */
  2317     List<JCTree> enumBody(Name enumName) {
  2318         accept(LBRACE);
  2319         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2320         if (S.token() == COMMA) {
  2321             S.nextToken();
  2322         } else if (S.token() != RBRACE && S.token() != SEMI) {
  2323             defs.append(enumeratorDeclaration(enumName));
  2324             while (S.token() == COMMA) {
  2325                 S.nextToken();
  2326                 if (S.token() == RBRACE || S.token() == SEMI) break;
  2327                 defs.append(enumeratorDeclaration(enumName));
  2329             if (S.token() != SEMI && S.token() != RBRACE) {
  2330                 defs.append(syntaxError(S.pos(), "expected3",
  2331                                 COMMA, RBRACE, SEMI));
  2332                 S.nextToken();
  2335         if (S.token() == SEMI) {
  2336             S.nextToken();
  2337             while (S.token() != RBRACE && S.token() != EOF) {
  2338                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2339                                                                 false));
  2340                 if (S.pos() <= errorEndPos) {
  2341                     // error recovery
  2342                    skip(false, true, true, false);
  2346         accept(RBRACE);
  2347         return defs.toList();
  2350     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2351      */
  2352     JCTree enumeratorDeclaration(Name enumName) {
  2353         String dc = S.docComment();
  2354         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2355         if (S.deprecatedFlag()) {
  2356             flags |= Flags.DEPRECATED;
  2357             S.resetDeprecatedFlag();
  2359         int pos = S.pos();
  2360         List<JCAnnotation> annotations = annotationsOpt();
  2361         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2362         List<JCExpression> typeArgs = typeArgumentsOpt();
  2363         int identPos = S.pos();
  2364         Name name = ident();
  2365         int createPos = S.pos();
  2366         List<JCExpression> args = (S.token() == LPAREN)
  2367             ? arguments() : List.<JCExpression>nil();
  2368         JCClassDecl body = null;
  2369         if (S.token() == LBRACE) {
  2370             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2371             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2372             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2374         if (args.isEmpty() && body == null)
  2375             createPos = Position.NOPOS;
  2376         JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
  2377         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2378         if (createPos != Position.NOPOS)
  2379             storeEnd(create, S.prevEndPos());
  2380         ident = F.at(Position.NOPOS).Ident(enumName);
  2381         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2382         attach(result, dc);
  2383         return result;
  2386     /** TypeList = Type {"," Type}
  2387      */
  2388     List<JCExpression> typeList() {
  2389         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2390         ts.append(parseType());
  2391         while (S.token() == COMMA) {
  2392             S.nextToken();
  2393             ts.append(parseType());
  2395         return ts.toList();
  2398     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2399      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2400      */
  2401     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2402         accept(LBRACE);
  2403         if (S.pos() <= errorEndPos) {
  2404             // error recovery
  2405             skip(false, true, false, false);
  2406             if (S.token() == LBRACE)
  2407                 S.nextToken();
  2409         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2410         while (S.token() != RBRACE && S.token() != EOF) {
  2411             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2412             if (S.pos() <= errorEndPos) {
  2413                // error recovery
  2414                skip(false, true, true, false);
  2417         accept(RBRACE);
  2418         return defs.toList();
  2421     /** ClassBodyDeclaration =
  2422      *      ";"
  2423      *    | [STATIC] Block
  2424      *    | ModifiersOpt
  2425      *      ( Type Ident
  2426      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2427      *      | VOID Ident MethodDeclaratorRest
  2428      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2429      *      | Ident ConstructorDeclaratorRest
  2430      *      | TypeParameters Ident ConstructorDeclaratorRest
  2431      *      | ClassOrInterfaceOrEnumDeclaration
  2432      *      )
  2433      *  InterfaceBodyDeclaration =
  2434      *      ";"
  2435      *    | ModifiersOpt Type Ident
  2436      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2437      */
  2438     List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2439         if (S.token() == SEMI) {
  2440             S.nextToken();
  2441             return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
  2442         } else {
  2443             String dc = S.docComment();
  2444             int pos = S.pos();
  2445             JCModifiers mods = modifiersOpt();
  2446             if (S.token() == CLASS ||
  2447                 S.token() == INTERFACE ||
  2448                 allowEnums && S.token() == ENUM) {
  2449                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2450             } else if (S.token() == LBRACE && !isInterface &&
  2451                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2452                        mods.annotations.isEmpty()) {
  2453                 return List.<JCTree>of(block(pos, mods.flags));
  2454             } else {
  2455                 pos = S.pos();
  2456                 List<JCTypeParameter> typarams = typeParametersOpt();
  2457                 // Hack alert:  if there are type arguments but no Modifiers, the start
  2458                 // position will be lost unless we set the Modifiers position.  There
  2459                 // should be an AST node for type parameters (BugId 5005090).
  2460                 if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
  2461                     mods.pos = pos;
  2463                 Token token = S.token();
  2464                 Name name = S.name();
  2465                 pos = S.pos();
  2466                 JCExpression type;
  2467                 boolean isVoid = S.token() == VOID;
  2468                 if (isVoid) {
  2469                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  2470                     S.nextToken();
  2471                 } else {
  2472                     type = parseType();
  2474                 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
  2475                     if (isInterface || name != className)
  2476                         log.error(pos, "invalid.meth.decl.ret.type.req");
  2477                     return List.of(methodDeclaratorRest(
  2478                         pos, mods, null, names.init, typarams,
  2479                         isInterface, true, dc));
  2480                 } else {
  2481                     pos = S.pos();
  2482                     name = ident();
  2483                     if (S.token() == LPAREN) {
  2484                         return List.of(methodDeclaratorRest(
  2485                             pos, mods, type, name, typarams,
  2486                             isInterface, isVoid, dc));
  2487                     } else if (!isVoid && typarams.isEmpty()) {
  2488                         List<JCTree> defs =
  2489                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2490                                                     new ListBuffer<JCTree>()).toList();
  2491                         storeEnd(defs.last(), S.endPos());
  2492                         accept(SEMI);
  2493                         return defs;
  2494                     } else {
  2495                         pos = S.pos();
  2496                         List<JCTree> err = isVoid
  2497                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2498                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2499                             : null;
  2500                         return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
  2507     /** MethodDeclaratorRest =
  2508      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2509      *  VoidMethodDeclaratorRest =
  2510      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  2511      *  InterfaceMethodDeclaratorRest =
  2512      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  2513      *  VoidInterfaceMethodDeclaratorRest =
  2514      *      FormalParameters [THROWS TypeList] ";"
  2515      *  ConstructorDeclaratorRest =
  2516      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  2517      */
  2518     JCTree methodDeclaratorRest(int pos,
  2519                               JCModifiers mods,
  2520                               JCExpression type,
  2521                               Name name,
  2522                               List<JCTypeParameter> typarams,
  2523                               boolean isInterface, boolean isVoid,
  2524                               String dc) {
  2525         List<JCVariableDecl> params = formalParameters();
  2526         if (!isVoid) type = bracketsOpt(type);
  2527         List<JCExpression> thrown = List.nil();
  2528         if (S.token() == THROWS) {
  2529             S.nextToken();
  2530             thrown = qualidentList();
  2532         JCBlock body = null;
  2533         JCExpression defaultValue;
  2534         if (S.token() == LBRACE) {
  2535             body = block();
  2536             defaultValue = null;
  2537         } else {
  2538             if (S.token() == DEFAULT) {
  2539                 accept(DEFAULT);
  2540                 defaultValue = annotationValue();
  2541             } else {
  2542                 defaultValue = null;
  2544             accept(SEMI);
  2545             if (S.pos() <= errorEndPos) {
  2546                 // error recovery
  2547                 skip(false, true, false, false);
  2548                 if (S.token() == LBRACE) {
  2549                     body = block();
  2553         JCMethodDecl result =
  2554             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2555                                     params, thrown,
  2556                                     body, defaultValue));
  2557         attach(result, dc);
  2558         return result;
  2561     /** QualidentList = Qualident {"," Qualident}
  2562      */
  2563     List<JCExpression> qualidentList() {
  2564         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2565         ts.append(qualident());
  2566         while (S.token() == COMMA) {
  2567             S.nextToken();
  2568             ts.append(qualident());
  2570         return ts.toList();
  2573     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  2574      */
  2575     List<JCTypeParameter> typeParametersOpt() {
  2576         if (S.token() == LT) {
  2577             checkGenerics();
  2578             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  2579             S.nextToken();
  2580             typarams.append(typeParameter());
  2581             while (S.token() == COMMA) {
  2582                 S.nextToken();
  2583                 typarams.append(typeParameter());
  2585             accept(GT);
  2586             return typarams.toList();
  2587         } else {
  2588             return List.nil();
  2592     /** TypeParameter = TypeVariable [TypeParameterBound]
  2593      *  TypeParameterBound = EXTENDS Type {"&" Type}
  2594      *  TypeVariable = Ident
  2595      */
  2596     JCTypeParameter typeParameter() {
  2597         int pos = S.pos();
  2598         Name name = ident();
  2599         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  2600         if (S.token() == EXTENDS) {
  2601             S.nextToken();
  2602             bounds.append(parseType());
  2603             while (S.token() == AMP) {
  2604                 S.nextToken();
  2605                 bounds.append(parseType());
  2608         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  2611     /** FormalParameters = "(" [ FormalParameterList ] ")"
  2612      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  2613      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  2614      */
  2615     List<JCVariableDecl> formalParameters() {
  2616         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  2617         JCVariableDecl lastParam = null;
  2618         accept(LPAREN);
  2619         if (S.token() != RPAREN) {
  2620             params.append(lastParam = formalParameter());
  2621             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
  2622                 S.nextToken();
  2623                 params.append(lastParam = formalParameter());
  2626         accept(RPAREN);
  2627         return params.toList();
  2630     JCModifiers optFinal(long flags) {
  2631         JCModifiers mods = modifiersOpt();
  2632         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  2633         mods.flags |= flags;
  2634         return mods;
  2637     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  2638      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  2639      */
  2640     JCVariableDecl formalParameter() {
  2641         JCModifiers mods = optFinal(Flags.PARAMETER);
  2642         JCExpression type = parseType();
  2643         if (S.token() == ELLIPSIS) {
  2644             checkVarargs();
  2645             mods.flags |= Flags.VARARGS;
  2646             type = to(F.at(S.pos()).TypeArray(type));
  2647             S.nextToken();
  2649         return variableDeclaratorId(mods, type);
  2652 /* ---------- auxiliary methods -------------- */
  2654     /** Check that given tree is a legal expression statement.
  2655      */
  2656     protected JCExpression checkExprStat(JCExpression t) {
  2657         switch(t.getTag()) {
  2658         case JCTree.PREINC: case JCTree.PREDEC:
  2659         case JCTree.POSTINC: case JCTree.POSTDEC:
  2660         case JCTree.ASSIGN:
  2661         case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
  2662         case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
  2663         case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
  2664         case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
  2665         case JCTree.APPLY: case JCTree.NEWCLASS:
  2666         case JCTree.ERRONEOUS:
  2667             return t;
  2668         default:
  2669             log.error(t.pos, "not.stmt");
  2670             return F.at(t.pos).Erroneous(List.<JCTree>of(t));
  2674     /** Return precedence of operator represented by token,
  2675      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  2676      */
  2677     static int prec(Token token) {
  2678         int oc = optag(token);
  2679         return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
  2682     /** Return operation tag of binary operator represented by token,
  2683      *  -1 if token is not a binary operator.
  2684      */
  2685     static int optag(Token token) {
  2686         switch (token) {
  2687         case BARBAR:
  2688             return JCTree.OR;
  2689         case AMPAMP:
  2690             return JCTree.AND;
  2691         case BAR:
  2692             return JCTree.BITOR;
  2693         case BAREQ:
  2694             return JCTree.BITOR_ASG;
  2695         case CARET:
  2696             return JCTree.BITXOR;
  2697         case CARETEQ:
  2698             return JCTree.BITXOR_ASG;
  2699         case AMP:
  2700             return JCTree.BITAND;
  2701         case AMPEQ:
  2702             return JCTree.BITAND_ASG;
  2703         case EQEQ:
  2704             return JCTree.EQ;
  2705         case BANGEQ:
  2706             return JCTree.NE;
  2707         case LT:
  2708             return JCTree.LT;
  2709         case GT:
  2710             return JCTree.GT;
  2711         case LTEQ:
  2712             return JCTree.LE;
  2713         case GTEQ:
  2714             return JCTree.GE;
  2715         case LTLT:
  2716             return JCTree.SL;
  2717         case LTLTEQ:
  2718             return JCTree.SL_ASG;
  2719         case GTGT:
  2720             return JCTree.SR;
  2721         case GTGTEQ:
  2722             return JCTree.SR_ASG;
  2723         case GTGTGT:
  2724             return JCTree.USR;
  2725         case GTGTGTEQ:
  2726             return JCTree.USR_ASG;
  2727         case PLUS:
  2728             return JCTree.PLUS;
  2729         case PLUSEQ:
  2730             return JCTree.PLUS_ASG;
  2731         case SUB:
  2732             return JCTree.MINUS;
  2733         case SUBEQ:
  2734             return JCTree.MINUS_ASG;
  2735         case STAR:
  2736             return JCTree.MUL;
  2737         case STAREQ:
  2738             return JCTree.MUL_ASG;
  2739         case SLASH:
  2740             return JCTree.DIV;
  2741         case SLASHEQ:
  2742             return JCTree.DIV_ASG;
  2743         case PERCENT:
  2744             return JCTree.MOD;
  2745         case PERCENTEQ:
  2746             return JCTree.MOD_ASG;
  2747         case INSTANCEOF:
  2748             return JCTree.TYPETEST;
  2749         default:
  2750             return -1;
  2754     /** Return operation tag of unary operator represented by token,
  2755      *  -1 if token is not a binary operator.
  2756      */
  2757     static int unoptag(Token token) {
  2758         switch (token) {
  2759         case PLUS:
  2760             return JCTree.POS;
  2761         case SUB:
  2762             return JCTree.NEG;
  2763         case BANG:
  2764             return JCTree.NOT;
  2765         case TILDE:
  2766             return JCTree.COMPL;
  2767         case PLUSPLUS:
  2768             return JCTree.PREINC;
  2769         case SUBSUB:
  2770             return JCTree.PREDEC;
  2771         default:
  2772             return -1;
  2776     /** Return type tag of basic type represented by token,
  2777      *  -1 if token is not a basic type identifier.
  2778      */
  2779     static int typetag(Token token) {
  2780         switch (token) {
  2781         case BYTE:
  2782             return TypeTags.BYTE;
  2783         case CHAR:
  2784             return TypeTags.CHAR;
  2785         case SHORT:
  2786             return TypeTags.SHORT;
  2787         case INT:
  2788             return TypeTags.INT;
  2789         case LONG:
  2790             return TypeTags.LONG;
  2791         case FLOAT:
  2792             return TypeTags.FLOAT;
  2793         case DOUBLE:
  2794             return TypeTags.DOUBLE;
  2795         case BOOLEAN:
  2796             return TypeTags.BOOLEAN;
  2797         default:
  2798             return -1;
  2802     void checkGenerics() {
  2803         if (!allowGenerics) {
  2804             log.error(S.pos(), "generics.not.supported.in.source", source.name);
  2805             allowGenerics = true;
  2808     void checkVarargs() {
  2809         if (!allowVarargs) {
  2810             log.error(S.pos(), "varargs.not.supported.in.source", source.name);
  2811             allowVarargs = true;
  2814     void checkForeach() {
  2815         if (!allowForeach) {
  2816             log.error(S.pos(), "foreach.not.supported.in.source", source.name);
  2817             allowForeach = true;
  2820     void checkStaticImports() {
  2821         if (!allowStaticImport) {
  2822             log.error(S.pos(), "static.import.not.supported.in.source", source.name);
  2823             allowStaticImport = true;
  2826     void checkAnnotations() {
  2827         if (!allowAnnotations) {
  2828             log.error(S.pos(), "annotations.not.supported.in.source", source.name);
  2829             allowAnnotations = true;

mercurial