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

Wed, 09 Apr 2008 14:05:24 +0100

author
mcimadamore
date
Wed, 09 Apr 2008 14:05:24 +0100
changeset 26
25338c55e458
parent 1
9a66ca7c79fa
child 54
eaf608c64fec
permissions
-rw-r--r--

6481655: Parser confused by combination of parens and explicit type args
Summary: Bug in the parser caused by the fact that explicit type arguments are disabled when parsing parenthesized expressions
Reviewed-by: jjg

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

mercurial