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

Mon, 27 Jul 2009 19:52:42 -0700

author
jjg
date
Mon, 27 Jul 2009 19:52:42 -0700
changeset 333
7c2d6da61646
parent 310
7c154fdc3547
child 383
8109aa93b212
permissions
-rw-r--r--

6865399: some javac files are missing Sun internal API comment
Reviewed-by: darcy

     1 /*
     2  * Copyright 1999-2009 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    26 package com.sun.tools.javac.parser;
    28 import java.util.*;
    30 import com.sun.tools.javac.tree.*;
    31 import com.sun.tools.javac.code.*;
    32 import com.sun.tools.javac.util.*;
    33 import com.sun.tools.javac.util.List;
    34 import static com.sun.tools.javac.util.ListBuffer.lb;
    36 import com.sun.tools.javac.tree.JCTree.*;
    38 import static com.sun.tools.javac.parser.Token.*;
    40 /** The parser maps a token sequence into an abstract syntax
    41  *  tree. It operates by recursive descent, with code derived
    42  *  systematically from an LL(1) grammar. For efficiency reasons, an
    43  *  operator precedence scheme is used for parsing binary operation
    44  *  expressions.
    45  *
    46  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    47  *  you write code that depends on this, you do so at your own risk.
    48  *  This code and its internal interfaces are subject to change or
    49  *  deletion without notice.</b>
    50  */
    51 public class JavacParser implements Parser {
    53     /** The number of precedence levels of infix operators.
    54      */
    55     private static final int infixPrecedenceLevels = 10;
    57     /** The scanner used for lexical analysis.
    58      */
    59     private Lexer S;
    61     /** The factory to be used for abstract syntax tree construction.
    62      */
    63     protected TreeMaker F;
    65     /** The log to be used for error diagnostics.
    66      */
    67     private Log log;
    69     /** The keyword table. */
    70     private Keywords keywords;
    72     /** The Source language setting. */
    73     private Source source;
    75     /** The name table. */
    76     private Names names;
    78     // Because of javac's limited lookahead, some contexts are ambiguous in
    79     // the presence of type annotations even though they are not ambiguous
    80     // in the absence of type annotations.  Consider this code:
    81     //   void m(String [] m) { }
    82     //   void m(String ... m) { }
    83     // After parsing "String", javac calls bracketsOpt which immediately
    84     // returns if the next character is not '['.  Similarly, javac can see
    85     // if the next token is ... and in that case parse an ellipsis.  But in
    86     // the presence of type annotations:
    87     //   void m(String @A [] m) { }
    88     //   void m(String @A ... m) { }
    89     // no finite lookahead is enough to determine whether to read array
    90     // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
    91     // bracketsOpt first reads all the leading annotations and only then
    92     // discovers that it needs to fail.  bracketsOpt needs a way to push
    93     // back the extra annotations that it read.  (But, bracketsOpt should
    94     // not *always* be allowed to push back extra annotations that it finds
    95     // -- in most contexts, any such extra annotation is an error.
    96     // Another similar case occurs with arrays and receiver annotations:
    97     //   String b() @Array [] @Receiver { }
    98     //   String b() @Receiver { }
    99     //
   100     // The following two variables permit type annotations that have
   101     // already been read to be stored for later use.  Alternate
   102     // implementations are possible but would cause much larger changes to
   103     // the parser.
   104     /** Type annotations that have already been read but have not yet been used. **/
   105     private List<JCTypeAnnotation> typeAnnotationsPushedBack = null;
   106     /**
   107      * If the parser notices extra annotations, then it either immediately
   108      * issues an error (if this variable is false) or places the extra
   109      * annotations in variable typeAnnotationsPushedBack (if this variable
   110      * is true).
   111      */
   112     private boolean permitTypeAnnotationsPushBack = false;
   114     /** Construct a parser from a given scanner, tree factory and log.
   115      */
   116     protected JavacParser(ParserFactory fac,
   117                      Lexer S,
   118                      boolean keepDocComments,
   119                      boolean keepLineMap) {
   120         this.S = S;
   121         S.nextToken(); // prime the pump
   122         this.F = fac.F;
   123         this.log = fac.log;
   124         this.names = fac.names;
   125         this.keywords = fac.keywords;
   126         this.source = fac.source;
   127         this.allowGenerics = source.allowGenerics();
   128         this.allowVarargs = source.allowVarargs();
   129         this.allowAsserts = source.allowAsserts();
   130         this.allowEnums = source.allowEnums();
   131         this.allowForeach = source.allowForeach();
   132         this.allowStaticImport = source.allowStaticImport();
   133         this.allowAnnotations = source.allowAnnotations();
   134         this.allowTypeAnnotations = source.allowTypeAnnotations();
   135         this.keepDocComments = keepDocComments;
   136         if (keepDocComments)
   137             docComments = new HashMap<JCTree,String>();
   138         this.keepLineMap = keepLineMap;
   139         this.errorTree = F.Erroneous();
   140         this.debugJSR308 = fac.options.get("TA:parser") != null;
   141     }
   143     /** Switch: debug output for type-annotations operations
   144      */
   145     boolean debugJSR308;
   147     /** Switch: Should generics be recognized?
   148      */
   149     boolean allowGenerics;
   151     /** Switch: Should varargs be recognized?
   152      */
   153     boolean allowVarargs;
   155     /** Switch: should we recognize assert statements, or just give a warning?
   156      */
   157     boolean allowAsserts;
   159     /** Switch: should we recognize enums, or just give a warning?
   160      */
   161     boolean allowEnums;
   163     /** Switch: should we recognize foreach?
   164      */
   165     boolean allowForeach;
   167     /** Switch: should we recognize foreach?
   168      */
   169     boolean allowStaticImport;
   171     /** Switch: should we recognize annotations?
   172      */
   173     boolean allowAnnotations;
   175     /** Switch: should we recognize type annotations?
   176      */
   177     boolean allowTypeAnnotations;
   179     /** Switch: should we keep docComments?
   180      */
   181     boolean keepDocComments;
   183     /** Switch: should we keep line table?
   184      */
   185     boolean keepLineMap;
   187     /** When terms are parsed, the mode determines which is expected:
   188      *     mode = EXPR        : an expression
   189      *     mode = TYPE        : a type
   190      *     mode = NOPARAMS    : no parameters allowed for type
   191      *     mode = TYPEARG     : type argument
   192      */
   193     static final int EXPR = 1;
   194     static final int TYPE = 2;
   195     static final int NOPARAMS = 4;
   196     static final int TYPEARG = 8;
   198     /** The current mode.
   199      */
   200     private int mode = 0;
   202     /** The mode of the term that was parsed last.
   203      */
   204     private int lastmode = 0;
   206 /* ---------- error recovery -------------- */
   208     private JCErroneous errorTree;
   210     /** Skip forward until a suitable stop token is found.
   211      */
   212     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   213          while (true) {
   214              switch (S.token()) {
   215                 case SEMI:
   216                     S.nextToken();
   217                     return;
   218                 case PUBLIC:
   219                 case FINAL:
   220                 case ABSTRACT:
   221                 case MONKEYS_AT:
   222                 case EOF:
   223                 case CLASS:
   224                 case INTERFACE:
   225                 case ENUM:
   226                     return;
   227                 case IMPORT:
   228                     if (stopAtImport)
   229                         return;
   230                     break;
   231                 case LBRACE:
   232                 case RBRACE:
   233                 case PRIVATE:
   234                 case PROTECTED:
   235                 case STATIC:
   236                 case TRANSIENT:
   237                 case NATIVE:
   238                 case VOLATILE:
   239                 case SYNCHRONIZED:
   240                 case STRICTFP:
   241                 case LT:
   242                 case BYTE:
   243                 case SHORT:
   244                 case CHAR:
   245                 case INT:
   246                 case LONG:
   247                 case FLOAT:
   248                 case DOUBLE:
   249                 case BOOLEAN:
   250                 case VOID:
   251                     if (stopAtMemberDecl)
   252                         return;
   253                     break;
   254                 case IDENTIFIER:
   255                    if (stopAtIdentifier)
   256                         return;
   257                     break;
   258                 case CASE:
   259                 case DEFAULT:
   260                 case IF:
   261                 case FOR:
   262                 case WHILE:
   263                 case DO:
   264                 case TRY:
   265                 case SWITCH:
   266                 case RETURN:
   267                 case THROW:
   268                 case BREAK:
   269                 case CONTINUE:
   270                 case ELSE:
   271                 case FINALLY:
   272                 case CATCH:
   273                     if (stopAtStatement)
   274                         return;
   275                     break;
   276             }
   277             S.nextToken();
   278         }
   279     }
   281     private JCErroneous syntaxError(int pos, String key, Token... args) {
   282         return syntaxError(pos, null, key, args);
   283     }
   285     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
   286         setErrorEndPos(pos);
   287         reportSyntaxError(pos, key, (Object[])args);
   288         return toP(F.at(pos).Erroneous(errs));
   289     }
   291     private int errorPos = Position.NOPOS;
   292     /**
   293      * Report a syntax error at given position using the given
   294      * argument unless one was already reported at the same position.
   295      */
   296     private void reportSyntaxError(int pos, String key, Object... args) {
   297         if (pos > S.errPos() || pos == Position.NOPOS) {
   298             if (S.token() == EOF)
   299                 log.error(pos, "premature.eof");
   300             else
   301                 log.error(pos, key, args);
   302         }
   303         S.errPos(pos);
   304         if (S.pos() == errorPos)
   305             S.nextToken(); // guarantee progress
   306         errorPos = S.pos();
   307     }
   310     /** Generate a syntax error at current position unless one was already
   311      *  reported at the same position.
   312      */
   313     private JCErroneous syntaxError(String key) {
   314         return syntaxError(S.pos(), key);
   315     }
   317     /** Generate a syntax error at current position unless one was
   318      *  already reported at the same position.
   319      */
   320     private JCErroneous syntaxError(String key, Token arg) {
   321         return syntaxError(S.pos(), key, arg);
   322     }
   324     /** If next input token matches given token, skip it, otherwise report
   325      *  an error.
   326      */
   327     public void accept(Token token) {
   328         if (S.token() == token) {
   329             S.nextToken();
   330         } else {
   331             setErrorEndPos(S.pos());
   332             reportSyntaxError(S.prevEndPos(), "expected", token);
   333         }
   334     }
   336     /** Report an illegal start of expression/type error at given position.
   337      */
   338     JCExpression illegal(int pos) {
   339         setErrorEndPos(S.pos());
   340         if ((mode & EXPR) != 0)
   341             return syntaxError(pos, "illegal.start.of.expr");
   342         else
   343             return syntaxError(pos, "illegal.start.of.type");
   345     }
   347     /** Report an illegal start of expression/type error at current position.
   348      */
   349     JCExpression illegal() {
   350         return illegal(S.pos());
   351     }
   353     /** Diagnose a modifier flag from the set, if any. */
   354     void checkNoMods(long mods) {
   355         if (mods != 0) {
   356             long lowestMod = mods & -mods;
   357             log.error(S.pos(), "mod.not.allowed.here",
   358                       Flags.asFlagSet(lowestMod));
   359         }
   360     }
   362 /* ---------- doc comments --------- */
   364     /** A hashtable to store all documentation comments
   365      *  indexed by the tree nodes they refer to.
   366      *  defined only if option flag keepDocComment is set.
   367      */
   368     Map<JCTree, String> docComments;
   370     /** Make an entry into docComments hashtable,
   371      *  provided flag keepDocComments is set and given doc comment is non-null.
   372      *  @param tree   The tree to be used as index in the hashtable
   373      *  @param dc     The doc comment to associate with the tree, or null.
   374      */
   375     void attach(JCTree tree, String dc) {
   376         if (keepDocComments && dc != null) {
   377 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   378             docComments.put(tree, dc);
   379         }
   380     }
   382 /* -------- source positions ------- */
   384     private int errorEndPos = -1;
   386     private void setErrorEndPos(int errPos) {
   387         if (errPos > errorEndPos)
   388             errorEndPos = errPos;
   389     }
   391     protected int getErrorEndPos() {
   392         return errorEndPos;
   393     }
   395     /**
   396      * Store ending position for a tree.
   397      * @param tree   The tree.
   398      * @param endpos The ending position to associate with the tree.
   399      */
   400     protected void storeEnd(JCTree tree, int endpos) {}
   402     /**
   403      * Store ending position for a tree.  The ending position should
   404      * be the ending position of the current token.
   405      * @param t The tree.
   406      */
   407     protected <T extends JCTree> T to(T t) { return t; }
   409     /**
   410      * Store ending position for a tree.  The ending position should
   411      * be greater of the ending position of the previous token and errorEndPos.
   412      * @param t The tree.
   413      */
   414     protected <T extends JCTree> T toP(T t) { return t; }
   416     /** Get the start position for a tree node.  The start position is
   417      * defined to be the position of the first character of the first
   418      * token of the node's source text.
   419      * @param tree  The tree node
   420      */
   421     public int getStartPos(JCTree tree) {
   422         return TreeInfo.getStartPos(tree);
   423     }
   425     /**
   426      * Get the end position for a tree node.  The end position is
   427      * defined to be the position of the last character of the last
   428      * token of the node's source text.  Returns Position.NOPOS if end
   429      * positions are not generated or the position is otherwise not
   430      * found.
   431      * @param tree  The tree node
   432      */
   433     public int getEndPos(JCTree tree) {
   434         return Position.NOPOS;
   435     }
   439 /* ---------- parsing -------------- */
   441     /**
   442      * Ident = IDENTIFIER
   443      */
   444     Name ident() {
   445         if (S.token() == IDENTIFIER) {
   446             Name name = S.name();
   447             S.nextToken();
   448             return name;
   449         } else if (S.token() == ASSERT) {
   450             if (allowAsserts) {
   451                 log.error(S.pos(), "assert.as.identifier");
   452                 S.nextToken();
   453                 return names.error;
   454             } else {
   455                 log.warning(S.pos(), "assert.as.identifier");
   456                 Name name = S.name();
   457                 S.nextToken();
   458                 return name;
   459             }
   460         } else if (S.token() == ENUM) {
   461             if (allowEnums) {
   462                 log.error(S.pos(), "enum.as.identifier");
   463                 S.nextToken();
   464                 return names.error;
   465             } else {
   466                 log.warning(S.pos(), "enum.as.identifier");
   467                 Name name = S.name();
   468                 S.nextToken();
   469                 return name;
   470             }
   471         } else {
   472             accept(IDENTIFIER);
   473             return names.error;
   474         }
   475 }
   477     /**
   478      * Qualident = Ident { DOT Ident }
   479      */
   480     public JCExpression qualident() {
   481         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
   482         while (S.token() == DOT) {
   483             int pos = S.pos();
   484             S.nextToken();
   485             t = toP(F.at(pos).Select(t, ident()));
   486         }
   487         return t;
   488     }
   490     /**
   491      * Literal =
   492      *     INTLITERAL
   493      *   | LONGLITERAL
   494      *   | FLOATLITERAL
   495      *   | DOUBLELITERAL
   496      *   | CHARLITERAL
   497      *   | STRINGLITERAL
   498      *   | TRUE
   499      *   | FALSE
   500      *   | NULL
   501      */
   502     JCExpression literal(Name prefix) {
   503         int pos = S.pos();
   504         JCExpression t = errorTree;
   505         switch (S.token()) {
   506         case INTLITERAL:
   507             try {
   508                 t = F.at(pos).Literal(
   509                     TypeTags.INT,
   510                     Convert.string2int(strval(prefix), S.radix()));
   511             } catch (NumberFormatException ex) {
   512                 log.error(S.pos(), "int.number.too.large", strval(prefix));
   513             }
   514             break;
   515         case LONGLITERAL:
   516             try {
   517                 t = F.at(pos).Literal(
   518                     TypeTags.LONG,
   519                     new Long(Convert.string2long(strval(prefix), S.radix())));
   520             } catch (NumberFormatException ex) {
   521                 log.error(S.pos(), "int.number.too.large", strval(prefix));
   522             }
   523             break;
   524         case FLOATLITERAL: {
   525             String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
   526             Float n;
   527             try {
   528                 n = Float.valueOf(proper);
   529             } catch (NumberFormatException ex) {
   530                 // error already repoted in scanner
   531                 n = Float.NaN;
   532             }
   533             if (n.floatValue() == 0.0f && !isZero(proper))
   534                 log.error(S.pos(), "fp.number.too.small");
   535             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   536                 log.error(S.pos(), "fp.number.too.large");
   537             else
   538                 t = F.at(pos).Literal(TypeTags.FLOAT, n);
   539             break;
   540         }
   541         case DOUBLELITERAL: {
   542             String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
   543             Double n;
   544             try {
   545                 n = Double.valueOf(proper);
   546             } catch (NumberFormatException ex) {
   547                 // error already reported in scanner
   548                 n = Double.NaN;
   549             }
   550             if (n.doubleValue() == 0.0d && !isZero(proper))
   551                 log.error(S.pos(), "fp.number.too.small");
   552             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   553                 log.error(S.pos(), "fp.number.too.large");
   554             else
   555                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
   556             break;
   557         }
   558         case CHARLITERAL:
   559             t = F.at(pos).Literal(
   560                 TypeTags.CHAR,
   561                 S.stringVal().charAt(0) + 0);
   562             break;
   563         case STRINGLITERAL:
   564             t = F.at(pos).Literal(
   565                 TypeTags.CLASS,
   566                 S.stringVal());
   567             break;
   568         case TRUE: case FALSE:
   569             t = F.at(pos).Literal(
   570                 TypeTags.BOOLEAN,
   571                 (S.token() == TRUE ? 1 : 0));
   572             break;
   573         case NULL:
   574             t = F.at(pos).Literal(
   575                 TypeTags.BOT,
   576                 null);
   577             break;
   578         default:
   579             assert false;
   580         }
   581         if (t == errorTree)
   582             t = F.at(pos).Erroneous();
   583         storeEnd(t, S.endPos());
   584         S.nextToken();
   585         return t;
   586     }
   587 //where
   588         boolean isZero(String s) {
   589             char[] cs = s.toCharArray();
   590             int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10);
   591             int i = ((base==16) ? 2 : 0);
   592             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   593             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   594         }
   596         String strval(Name prefix) {
   597             String s = S.stringVal();
   598             return prefix.isEmpty() ? s : prefix + s;
   599         }
   601     /** terms can be either expressions or types.
   602      */
   603     public JCExpression parseExpression() {
   604         return term(EXPR);
   605     }
   607     /**
   608      * parses (optional) type annotations followed by a type. If the
   609      * annotations are present before the type and are not consumed during array
   610      * parsing, this method returns a {@link JCAnnotatedType} consisting of
   611      * these annotations and the underlying type. Otherwise, it returns the
   612      * underlying type.
   613      *
   614      * <p>
   615      *
   616      * Note that this method sets {@code mode} to {@code TYPE} first, before
   617      * parsing annotations.
   618      */
   619     public JCExpression parseType() {
   620         List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
   621         return parseType(annotations);
   622     }
   624     public JCExpression parseType(List<JCTypeAnnotation> annotations) {
   625         JCExpression result = unannotatedType();
   627         if (!annotations.isEmpty())
   628             result = F.AnnotatedType(annotations, result);
   630         return result;
   631     }
   633     public JCExpression unannotatedType() {
   634         return term(TYPE);
   635     }
   637     JCExpression term(int newmode) {
   638         int prevmode = mode;
   639         mode = newmode;
   640         JCExpression t = term();
   641         lastmode = mode;
   642         mode = prevmode;
   643         return t;
   644     }
   646     /**
   647      *  Expression = Expression1 [ExpressionRest]
   648      *  ExpressionRest = [AssignmentOperator Expression1]
   649      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   650      *                       "&=" | "|=" | "^=" |
   651      *                       "%=" | "<<=" | ">>=" | ">>>="
   652      *  Type = Type1
   653      *  TypeNoParams = TypeNoParams1
   654      *  StatementExpression = Expression
   655      *  ConstantExpression = Expression
   656      */
   657     JCExpression term() {
   658         JCExpression t = term1();
   659         if ((mode & EXPR) != 0 &&
   660             S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
   661             return termRest(t);
   662         else
   663             return t;
   664     }
   666     JCExpression termRest(JCExpression t) {
   667         switch (S.token()) {
   668         case EQ: {
   669             int pos = S.pos();
   670             S.nextToken();
   671             mode = EXPR;
   672             JCExpression t1 = term();
   673             return toP(F.at(pos).Assign(t, t1));
   674         }
   675         case PLUSEQ:
   676         case SUBEQ:
   677         case STAREQ:
   678         case SLASHEQ:
   679         case PERCENTEQ:
   680         case AMPEQ:
   681         case BAREQ:
   682         case CARETEQ:
   683         case LTLTEQ:
   684         case GTGTEQ:
   685         case GTGTGTEQ:
   686             int pos = S.pos();
   687             Token token = S.token();
   688             S.nextToken();
   689             mode = EXPR;
   690             JCExpression t1 = term();
   691             return F.at(pos).Assignop(optag(token), t, t1);
   692         default:
   693             return t;
   694         }
   695     }
   697     /** Expression1   = Expression2 [Expression1Rest]
   698      *  Type1         = Type2
   699      *  TypeNoParams1 = TypeNoParams2
   700      */
   701     JCExpression term1() {
   702         JCExpression t = term2();
   703         if ((mode & EXPR) != 0 && S.token() == QUES) {
   704             mode = EXPR;
   705             return term1Rest(t);
   706         } else {
   707             return t;
   708         }
   709     }
   711     /** Expression1Rest = ["?" Expression ":" Expression1]
   712      */
   713     JCExpression term1Rest(JCExpression t) {
   714         if (S.token() == QUES) {
   715             int pos = S.pos();
   716             S.nextToken();
   717             JCExpression t1 = term();
   718             accept(COLON);
   719             JCExpression t2 = term1();
   720             return F.at(pos).Conditional(t, t1, t2);
   721         } else {
   722             return t;
   723         }
   724     }
   726     /** Expression2   = Expression3 [Expression2Rest]
   727      *  Type2         = Type3
   728      *  TypeNoParams2 = TypeNoParams3
   729      */
   730     JCExpression term2() {
   731         JCExpression t = term3();
   732         if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
   733             mode = EXPR;
   734             return term2Rest(t, TreeInfo.orPrec);
   735         } else {
   736             return t;
   737         }
   738     }
   740     /*  Expression2Rest = {infixop Expression3}
   741      *                  | Expression3 instanceof Type
   742      *  infixop         = "||"
   743      *                  | "&&"
   744      *                  | "|"
   745      *                  | "^"
   746      *                  | "&"
   747      *                  | "==" | "!="
   748      *                  | "<" | ">" | "<=" | ">="
   749      *                  | "<<" | ">>" | ">>>"
   750      *                  | "+" | "-"
   751      *                  | "*" | "/" | "%"
   752      */
   753     JCExpression term2Rest(JCExpression t, int minprec) {
   754         List<JCExpression[]> savedOd = odStackSupply.elems;
   755         JCExpression[] odStack = newOdStack();
   756         List<Token[]> savedOp = opStackSupply.elems;
   757         Token[] opStack = newOpStack();
   758         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   759         int top = 0;
   760         odStack[0] = t;
   761         int startPos = S.pos();
   762         Token topOp = ERROR;
   763         while (prec(S.token()) >= minprec) {
   764             opStack[top] = topOp;
   765             top++;
   766             topOp = S.token();
   767             int pos = S.pos();
   768             S.nextToken();
   769             odStack[top] = topOp == INSTANCEOF ? parseType() : term3();
   770             while (top > 0 && prec(topOp) >= prec(S.token())) {
   771                 odStack[top-1] = makeOp(pos, topOp, odStack[top-1],
   772                                         odStack[top]);
   773                 top--;
   774                 topOp = opStack[top];
   775             }
   776         }
   777         assert top == 0;
   778         t = odStack[0];
   780         if (t.getTag() == JCTree.PLUS) {
   781             StringBuffer buf = foldStrings(t);
   782             if (buf != null) {
   783                 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
   784             }
   785         }
   787         odStackSupply.elems = savedOd; // optimization
   788         opStackSupply.elems = savedOp; // optimization
   789         return t;
   790     }
   791 //where
   792         /** Construct a binary or type test node.
   793          */
   794         private JCExpression makeOp(int pos,
   795                                     Token topOp,
   796                                     JCExpression od1,
   797                                     JCExpression od2)
   798         {
   799             if (topOp == INSTANCEOF) {
   800                 return F.at(pos).TypeTest(od1, od2);
   801             } else {
   802                 return F.at(pos).Binary(optag(topOp), od1, od2);
   803             }
   804         }
   805         /** If tree is a concatenation of string literals, replace it
   806          *  by a single literal representing the concatenated string.
   807          */
   808         protected StringBuffer foldStrings(JCTree tree) {
   809             List<String> buf = List.nil();
   810             while (true) {
   811                 if (tree.getTag() == JCTree.LITERAL) {
   812                     JCLiteral lit = (JCLiteral) tree;
   813                     if (lit.typetag == TypeTags.CLASS) {
   814                         StringBuffer sbuf =
   815                             new StringBuffer((String)lit.value);
   816                         while (buf.nonEmpty()) {
   817                             sbuf.append(buf.head);
   818                             buf = buf.tail;
   819                         }
   820                         return sbuf;
   821                     }
   822                 } else if (tree.getTag() == JCTree.PLUS) {
   823                     JCBinary op = (JCBinary)tree;
   824                     if (op.rhs.getTag() == JCTree.LITERAL) {
   825                         JCLiteral lit = (JCLiteral) op.rhs;
   826                         if (lit.typetag == TypeTags.CLASS) {
   827                             buf = buf.prepend((String) lit.value);
   828                             tree = op.lhs;
   829                             continue;
   830                         }
   831                     }
   832                 }
   833                 return null;
   834             }
   835         }
   837         /** optimization: To save allocating a new operand/operator stack
   838          *  for every binary operation, we use supplys.
   839          */
   840         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
   841         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
   843         private JCExpression[] newOdStack() {
   844             if (odStackSupply.elems == odStackSupply.last)
   845                 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
   846             JCExpression[] odStack = odStackSupply.elems.head;
   847             odStackSupply.elems = odStackSupply.elems.tail;
   848             return odStack;
   849         }
   851         private Token[] newOpStack() {
   852             if (opStackSupply.elems == opStackSupply.last)
   853                 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
   854             Token[] opStack = opStackSupply.elems.head;
   855             opStackSupply.elems = opStackSupply.elems.tail;
   856             return opStack;
   857         }
   859     /** Expression3    = PrefixOp Expression3
   860      *                 | "(" Expr | TypeNoParams ")" Expression3
   861      *                 | Primary {Selector} {PostfixOp}
   862      *  Primary        = "(" Expression ")"
   863      *                 | Literal
   864      *                 | [TypeArguments] THIS [Arguments]
   865      *                 | [TypeArguments] SUPER SuperSuffix
   866      *                 | NEW [TypeArguments] Creator
   867      *                 | [Annotations] Ident { "." Ident }
   868      *                   [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   869      *                   | Arguments
   870      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   871      *                   ]
   872      *                 | BasicType BracketsOpt "." CLASS
   873      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   874      *  PostfixOp      = "++" | "--"
   875      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   876      *                 | BasicType
   877      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   878      *  Selector       = "." [TypeArguments] Ident [Arguments]
   879      *                 | "." THIS
   880      *                 | "." [TypeArguments] SUPER SuperSuffix
   881      *                 | "." NEW [TypeArguments] InnerCreator
   882      *                 | "[" Expression "]"
   883      *  TypeSelector   = "." Ident [TypeArguments]
   884      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   885      */
   886     protected JCExpression term3() {
   887         int pos = S.pos();
   888         JCExpression t;
   889         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   890         switch (S.token()) {
   891         case QUES:
   892             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   893                 mode = TYPE;
   894                 return typeArgument();
   895             } else
   896                 return illegal();
   897         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   898             if (typeArgs == null && (mode & EXPR) != 0) {
   899                 Token token = S.token();
   900                 S.nextToken();
   901                 mode = EXPR;
   902                 if (token == SUB &&
   903                     (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
   904                     S.radix() == 10) {
   905                     mode = EXPR;
   906                     t = literal(names.hyphen);
   907                 } else {
   908                     t = term3();
   909                     return F.at(pos).Unary(unoptag(token), t);
   910                 }
   911             } else return illegal();
   912             break;
   913         case LPAREN:
   914             if (typeArgs == null && (mode & EXPR) != 0) {
   915                 S.nextToken();
   916                 mode = EXPR | TYPE | NOPARAMS;
   917                 t = term3();
   918                 if ((mode & TYPE) != 0 && S.token() == LT) {
   919                     // Could be a cast to a parameterized type
   920                     int op = JCTree.LT;
   921                     int pos1 = S.pos();
   922                     S.nextToken();
   923                     mode &= (EXPR | TYPE);
   924                     mode |= TYPEARG;
   925                     JCExpression t1 = term3();
   926                     if ((mode & TYPE) != 0 &&
   927                         (S.token() == COMMA || S.token() == GT)) {
   928                         mode = TYPE;
   929                         ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   930                         args.append(t1);
   931                         while (S.token() == COMMA) {
   932                             S.nextToken();
   933                             args.append(typeArgument());
   934                         }
   935                         accept(GT);
   936                         t = F.at(pos1).TypeApply(t, args.toList());
   937                         checkGenerics();
   938                         while (S.token() == DOT) {
   939                             S.nextToken();
   940                             mode = TYPE;
   941                             t = toP(F.at(S.pos()).Select(t, ident()));
   942                             t = typeArgumentsOpt(t);
   943                         }
   944                         t = bracketsOpt(toP(t));
   945                     } else if ((mode & EXPR) != 0) {
   946                         mode = EXPR;
   947                         t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec));
   948                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   949                     } else {
   950                         accept(GT);
   951                     }
   952                 }
   953                 else {
   954                     t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   955                 }
   956                 accept(RPAREN);
   957                 lastmode = mode;
   958                 mode = EXPR;
   959                 if ((lastmode & EXPR) == 0) {
   960                     JCExpression t1 = term3();
   961                     return F.at(pos).TypeCast(t, t1);
   962                 } else if ((lastmode & TYPE) != 0) {
   963                     switch (S.token()) {
   964                     /*case PLUSPLUS: case SUBSUB: */
   965                     case BANG: case TILDE:
   966                     case LPAREN: case THIS: case SUPER:
   967                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
   968                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
   969                     case TRUE: case FALSE: case NULL:
   970                     case NEW: case IDENTIFIER: case ASSERT: case ENUM:
   971                     case BYTE: case SHORT: case CHAR: case INT:
   972                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
   973                         JCExpression t1 = term3();
   974                         return F.at(pos).TypeCast(t, t1);
   975                     }
   976                 }
   977             } else return illegal();
   978             t = toP(F.at(pos).Parens(t));
   979             break;
   980         case THIS:
   981             if ((mode & EXPR) != 0) {
   982                 mode = EXPR;
   983                 t = to(F.at(pos).Ident(names._this));
   984                 S.nextToken();
   985                 if (typeArgs == null)
   986                     t = argumentsOpt(null, t);
   987                 else
   988                     t = arguments(typeArgs, t);
   989                 typeArgs = null;
   990             } else return illegal();
   991             break;
   992         case SUPER:
   993             if ((mode & EXPR) != 0) {
   994                 mode = EXPR;
   995                 t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super)));
   996                 typeArgs = null;
   997             } else return illegal();
   998             break;
   999         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1000         case CHARLITERAL: case STRINGLITERAL:
  1001         case TRUE: case FALSE: case NULL:
  1002             if (typeArgs == null && (mode & EXPR) != 0) {
  1003                 mode = EXPR;
  1004                 t = literal(names.empty);
  1005             } else return illegal();
  1006             break;
  1007         case NEW:
  1008             if (typeArgs != null) return illegal();
  1009             if ((mode & EXPR) != 0) {
  1010                 mode = EXPR;
  1011                 S.nextToken();
  1012                 if (S.token() == LT) typeArgs = typeArguments();
  1013                 t = creator(pos, typeArgs);
  1014                 typeArgs = null;
  1015             } else return illegal();
  1016             break;
  1017         case MONKEYS_AT:
  1019             // only annotated targetting class literals or cast types are valid
  1020             List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
  1021             if (typeAnnos.isEmpty()) {
  1022                 // else there would be no '@'
  1023                 throw new AssertionError("type annos is empty");
  1026             JCExpression expr = term3();
  1028             // Type annotations: If term3 just parsed a non-type, expect a
  1029             // class literal (and issue a syntax error if there is no class
  1030             // literal). Otherwise, create a JCAnnotatedType.
  1031             if ((mode & TYPE) == 0) {
  1032                 if (expr.getTag() != JCTree.SELECT)
  1033                     return illegal(typeAnnos.head.pos);
  1034                 JCFieldAccess sel = (JCFieldAccess)expr;
  1035                 if (sel.name != names._class)
  1036                     return illegal();
  1037                 else {
  1038                     sel.selected = F.AnnotatedType(typeAnnos, sel.selected);
  1039                     t = expr;
  1041             } else {
  1042                 // type annotation targeting a cast
  1043                 t = toP(F.at(S.pos()).AnnotatedType(typeAnnos, expr));
  1045             break;
  1046         case IDENTIFIER: case ASSERT: case ENUM:
  1047             if (typeArgs != null) return illegal();
  1048             t = toP(F.at(S.pos()).Ident(ident()));
  1049             loop: while (true) {
  1050                 pos = S.pos();
  1051                 final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
  1053                 // need to report an error later if LBRACKET is for array
  1054                 // index access rather than array creation level
  1055                 if (!annos.isEmpty() && S.token() != LBRACKET && S.token() != ELLIPSIS)
  1056                     return illegal(annos.head.pos);
  1057                 switch (S.token()) {
  1058                 case LBRACKET:
  1059                     S.nextToken();
  1061                     if (S.token() == RBRACKET) {
  1063                         S.nextToken();
  1065                         t = bracketsOpt(t, annos);
  1066                         t = toP(F.at(pos).TypeArray(t));
  1067                         t = bracketsSuffix(t);
  1068                     } else {
  1069                         if ((mode & EXPR) != 0) {
  1070                             mode = EXPR;
  1071                             JCExpression t1 = term();
  1072                             if (!annos.isEmpty()) t = illegal(annos.head.pos);
  1073                             t = to(F.at(pos).Indexed(t, t1));
  1075                         accept(RBRACKET);
  1077                     break loop;
  1078                 case LPAREN:
  1079                     if ((mode & EXPR) != 0) {
  1080                         mode = EXPR;
  1081                         t = arguments(typeArgs, t);
  1082                         typeArgs = null;
  1084                     break loop;
  1085                 case DOT:
  1086                     S.nextToken();
  1087                     int oldmode = mode;
  1088                     mode &= ~NOPARAMS;
  1089                     typeArgs = typeArgumentsOpt(EXPR);
  1090                     mode = oldmode;
  1091                     if ((mode & EXPR) != 0) {
  1092                         switch (S.token()) {
  1093                         case CLASS:
  1094                             if (typeArgs != null) return illegal();
  1095                             mode = EXPR;
  1096                             t = to(F.at(pos).Select(t, names._class));
  1097                             S.nextToken();
  1098                             break loop;
  1099                         case THIS:
  1100                             if (typeArgs != null) return illegal();
  1101                             mode = EXPR;
  1102                             t = to(F.at(pos).Select(t, names._this));
  1103                             S.nextToken();
  1104                             break loop;
  1105                         case SUPER:
  1106                             mode = EXPR;
  1107                             t = to(F.at(pos).Select(t, names._super));
  1108                             t = superSuffix(typeArgs, t);
  1109                             typeArgs = null;
  1110                             break loop;
  1111                         case NEW:
  1112                             if (typeArgs != null) return illegal();
  1113                             mode = EXPR;
  1114                             int pos1 = S.pos();
  1115                             S.nextToken();
  1116                             if (S.token() == LT) typeArgs = typeArguments();
  1117                             t = innerCreator(pos1, typeArgs, t);
  1118                             typeArgs = null;
  1119                             break loop;
  1122                     // typeArgs saved for next loop iteration.
  1123                     t = toP(F.at(pos).Select(t, ident()));
  1124                     break;
  1125                 case ELLIPSIS:
  1126                     assert this.permitTypeAnnotationsPushBack;
  1127                     typeAnnotationsPushedBack = annos;
  1128                     break loop;
  1129                 default:
  1130                     break loop;
  1133             if (typeArgs != null) illegal();
  1134             t = typeArgumentsOpt(t);
  1135             break;
  1136         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1137         case DOUBLE: case BOOLEAN:
  1138             if (typeArgs != null) illegal();
  1139             t = bracketsSuffix(bracketsOpt(basicType()));
  1140             break;
  1141         case VOID:
  1142             if (typeArgs != null) illegal();
  1143             if ((mode & EXPR) != 0) {
  1144                 S.nextToken();
  1145                 if (S.token() == DOT) {
  1146                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
  1147                     t = bracketsSuffix(ti);
  1148                 } else {
  1149                     return illegal(pos);
  1151             } else {
  1152                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1153                 // a void type (like other primitive types) to the next phase.
  1154                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1155                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
  1156                 S.nextToken();
  1157                 return ti;
  1158                 //return illegal();
  1160             break;
  1161         default:
  1162             return illegal();
  1164         if (typeArgs != null) illegal();
  1165         while (true) {
  1166             int pos1 = S.pos();
  1168             final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
  1170             if (S.token() == LBRACKET) {
  1171                 S.nextToken();
  1173                 if ((mode & TYPE) != 0) {
  1174                     int oldmode = mode;
  1175                     mode = TYPE;
  1176                     if (S.token() == RBRACKET) {
  1177                         S.nextToken();
  1178                         t = bracketsOpt(t, annos);
  1179                         t = toP(F.at(pos1).TypeArray(t));
  1180                         return t;
  1182                     mode = oldmode;
  1184                 if ((mode & EXPR) != 0) {
  1185                     mode = EXPR;
  1186                     JCExpression t1 = term();
  1187                     t = to(F.at(pos1).Indexed(t, t1));
  1189                 accept(RBRACKET);
  1190             } else if (S.token() == DOT) {
  1191                 S.nextToken();
  1192                 typeArgs = typeArgumentsOpt(EXPR);
  1193                 if (S.token() == SUPER && (mode & EXPR) != 0) {
  1194                     mode = EXPR;
  1195                     t = to(F.at(pos1).Select(t, names._super));
  1196                     S.nextToken();
  1197                     t = arguments(typeArgs, t);
  1198                     typeArgs = null;
  1199                 } else if (S.token() == NEW && (mode & EXPR) != 0) {
  1200                     if (typeArgs != null) return illegal();
  1201                     mode = EXPR;
  1202                     int pos2 = S.pos();
  1203                     S.nextToken();
  1204                     if (S.token() == LT) typeArgs = typeArguments();
  1205                     t = innerCreator(pos2, typeArgs, t);
  1206                     typeArgs = null;
  1207                 } else {
  1208                     t = toP(F.at(pos1).Select(t, ident()));
  1209                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1210                     typeArgs = null;
  1212             } else {
  1213                 if (!annos.isEmpty()) {
  1214                     if (permitTypeAnnotationsPushBack)
  1215                         typeAnnotationsPushedBack = annos;
  1216                     else
  1217                         return illegal(annos.head.pos);
  1219                 break;
  1222         while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
  1223             mode = EXPR;
  1224             t = to(F.at(S.pos()).Unary(
  1225                   S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
  1226             S.nextToken();
  1229         return toP(t);
  1232     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1233      */
  1234     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1235         S.nextToken();
  1236         if (S.token() == LPAREN || typeArgs != null) {
  1237             t = arguments(typeArgs, t);
  1238         } else {
  1239             int pos = S.pos();
  1240             accept(DOT);
  1241             typeArgs = (S.token() == LT) ? typeArguments() : null;
  1242             t = toP(F.at(pos).Select(t, ident()));
  1243             t = argumentsOpt(typeArgs, t);
  1245         return t;
  1248     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1249      */
  1250     JCPrimitiveTypeTree basicType() {
  1251         JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
  1252         S.nextToken();
  1253         return t;
  1256     /** ArgumentsOpt = [ Arguments ]
  1257      */
  1258     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1259         if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
  1260             mode = EXPR;
  1261             return arguments(typeArgs, t);
  1262         } else {
  1263             return t;
  1267     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1268      */
  1269     List<JCExpression> arguments() {
  1270         ListBuffer<JCExpression> args = lb();
  1271         if (S.token() == LPAREN) {
  1272             S.nextToken();
  1273             if (S.token() != RPAREN) {
  1274                 args.append(parseExpression());
  1275                 while (S.token() == COMMA) {
  1276                     S.nextToken();
  1277                     args.append(parseExpression());
  1280             accept(RPAREN);
  1281         } else {
  1282             syntaxError(S.pos(), "expected", LPAREN);
  1284         return args.toList();
  1287     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1288         int pos = S.pos();
  1289         List<JCExpression> args = arguments();
  1290         return toP(F.at(pos).Apply(typeArgs, t, args));
  1293     /**  TypeArgumentsOpt = [ TypeArguments ]
  1294      */
  1295     JCExpression typeArgumentsOpt(JCExpression t) {
  1296         if (S.token() == LT &&
  1297             (mode & TYPE) != 0 &&
  1298             (mode & NOPARAMS) == 0) {
  1299             mode = TYPE;
  1300             checkGenerics();
  1301             return typeArguments(t);
  1302         } else {
  1303             return t;
  1306     List<JCExpression> typeArgumentsOpt() {
  1307         return typeArgumentsOpt(TYPE);
  1310     List<JCExpression> typeArgumentsOpt(int useMode) {
  1311         if (S.token() == LT) {
  1312             checkGenerics();
  1313             if ((mode & useMode) == 0 ||
  1314                 (mode & NOPARAMS) != 0) {
  1315                 illegal();
  1317             mode = useMode;
  1318             return typeArguments();
  1320         return null;
  1323     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1324      */
  1325     List<JCExpression> typeArguments() {
  1326         ListBuffer<JCExpression> args = lb();
  1327         if (S.token() == LT) {
  1328             S.nextToken();
  1329             args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1330             while (S.token() == COMMA) {
  1331                 S.nextToken();
  1332                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1334             switch (S.token()) {
  1335             case GTGTGTEQ:
  1336                 S.token(GTGTEQ);
  1337                 break;
  1338             case GTGTEQ:
  1339                 S.token(GTEQ);
  1340                 break;
  1341             case GTEQ:
  1342                 S.token(EQ);
  1343                 break;
  1344             case GTGTGT:
  1345                 S.token(GTGT);
  1346                 break;
  1347             case GTGT:
  1348                 S.token(GT);
  1349                 break;
  1350             default:
  1351                 accept(GT);
  1352                 break;
  1354         } else {
  1355             syntaxError(S.pos(), "expected", LT);
  1357         return args.toList();
  1360     /** TypeArgument = Type
  1361      *               | [Annotations] "?"
  1362      *               | [Annotations] "?" EXTENDS Type {"&" Type}
  1363      *               | [Annotations] "?" SUPER Type
  1364      */
  1365     JCExpression typeArgument() {
  1366         List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
  1367         if (S.token() != QUES) return parseType(annotations);
  1368         int pos = S.pos();
  1369         S.nextToken();
  1370         JCExpression result;
  1371         if (S.token() == EXTENDS) {
  1372             TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
  1373             S.nextToken();
  1374             result = F.at(pos).Wildcard(t, parseType());
  1375         } else if (S.token() == SUPER) {
  1376             TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
  1377             S.nextToken();
  1378             result = F.at(pos).Wildcard(t, parseType());
  1379         } else if (S.token() == IDENTIFIER) {
  1380             //error recovery
  1381             reportSyntaxError(S.prevEndPos(), "expected3",
  1382                     GT, EXTENDS, SUPER);
  1383             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1384             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1385             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
  1386             result = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1387         } else {
  1388             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1389             result = toP(F.at(pos).Wildcard(t, null));
  1391         if (!annotations.isEmpty())
  1392             result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
  1393         return result;
  1396     JCTypeApply typeArguments(JCExpression t) {
  1397         int pos = S.pos();
  1398         List<JCExpression> args = typeArguments();
  1399         return toP(F.at(pos).TypeApply(t, args));
  1402     /**
  1403      * BracketsOpt = { [Annotations] "[" "]" }
  1405      * <p>
  1407      * <code>annotations</code> is the list of annotations targeting
  1408      * the expression <code>t</code>.
  1409      */
  1410     private JCExpression bracketsOpt(JCExpression t,
  1411             List<JCTypeAnnotation> annotations) {
  1412         List<JCTypeAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
  1414         if (S.token() == LBRACKET) {
  1415             int pos = S.pos();
  1416             S.nextToken();
  1418             JCExpression orig = t;
  1419             t = bracketsOptCont(t, pos, nextLevelAnnotations);
  1420         } else if (!nextLevelAnnotations.isEmpty()) {
  1421             if (permitTypeAnnotationsPushBack) {
  1422                 this.typeAnnotationsPushedBack = nextLevelAnnotations;
  1423             } else
  1424                 return illegal(nextLevelAnnotations.head.pos);
  1427         int apos = S.pos();
  1428         if (!annotations.isEmpty())
  1429             t = F.at(apos).AnnotatedType(annotations, t);
  1430         return t;
  1433     /** BracketsOpt = {"[" TypeAnnotations "]"}
  1434      */
  1435     private JCExpression bracketsOpt(JCExpression t) {
  1436         return bracketsOpt(t, List.<JCTypeAnnotation>nil());
  1439     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos,
  1440             List<JCTypeAnnotation> annotations) {
  1441         accept(RBRACKET);
  1442         t = bracketsOpt(t, annotations);
  1443         return toP(F.at(pos).TypeArray(t));
  1446     /** BracketsSuffixExpr = "." CLASS
  1447      *  BracketsSuffixType =
  1448      */
  1449     JCExpression bracketsSuffix(JCExpression t) {
  1450         if ((mode & EXPR) != 0 && S.token() == DOT) {
  1451             mode = EXPR;
  1452             int pos = S.pos();
  1453             S.nextToken();
  1454             accept(CLASS);
  1455             if (S.pos() == errorEndPos) {
  1456                 // error recovery
  1457                 Name name = null;
  1458                 if (S.token() == IDENTIFIER) {
  1459                     name = S.name();
  1460                     S.nextToken();
  1461                 } else {
  1462                     name = names.error;
  1464                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1465             } else {
  1466                 t = toP(F.at(pos).Select(t, names._class));
  1468         } else if ((mode & TYPE) != 0) {
  1469             mode = TYPE;
  1470         } else {
  1471             syntaxError(S.pos(), "dot.class.expected");
  1473         return t;
  1476     /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1477      */
  1478     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1480         List<JCTypeAnnotation> newAnnotations = typeAnnotationsOpt();
  1482         switch (S.token()) {
  1483         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1484         case DOUBLE: case BOOLEAN:
  1485             if (typeArgs == null) {
  1486                 if (newAnnotations.isEmpty())
  1487                     return arrayCreatorRest(newpos, basicType());
  1488                 else
  1489                     return arrayCreatorRest(newpos, F.AnnotatedType(newAnnotations, basicType()));
  1491             break;
  1492         default:
  1494         JCExpression t = qualident();
  1495         // handle type annotations for non primitive arrays
  1496         if (!newAnnotations.isEmpty())
  1497             t = F.AnnotatedType(newAnnotations, t);
  1499         int oldmode = mode;
  1500         mode = TYPE;
  1501         if (S.token() == LT) {
  1502             checkGenerics();
  1503             t = typeArguments(t);
  1505         while (S.token() == DOT) {
  1506             int pos = S.pos();
  1507             S.nextToken();
  1508             t = toP(F.at(pos).Select(t, ident()));
  1509             if (S.token() == LT) {
  1510                 checkGenerics();
  1511                 t = typeArguments(t);
  1514         mode = oldmode;
  1515         if (S.token() == LBRACKET || S.token() == MONKEYS_AT) {
  1516             JCExpression e = arrayCreatorRest(newpos, t);
  1517             if (typeArgs != null) {
  1518                 int pos = newpos;
  1519                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1520                     // note: this should always happen but we should
  1521                     // not rely on this as the parser is continuously
  1522                     // modified to improve error recovery.
  1523                     pos = typeArgs.head.pos;
  1525                 setErrorEndPos(S.prevEndPos());
  1526                 reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
  1527                 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
  1529             return e;
  1530         } else if (S.token() == LPAREN) {
  1531             JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t);
  1532             if (newClass.def != null) {
  1533                 assert newClass.def.mods.annotations.isEmpty();
  1534                 newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations);
  1536             return newClass;
  1537         } else {
  1538             reportSyntaxError(S.pos(), "expected2",
  1539                                LPAREN, LBRACKET);
  1540             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1541             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1545     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1546      */
  1547     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1548         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
  1549         if (S.token() == LT) {
  1550             checkGenerics();
  1551             t = typeArguments(t);
  1553         return classCreatorRest(newpos, encl, typeArgs, t);
  1556     /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
  1557      *                         | Expression "]" {[Annotations]  "[" Expression "]"} BracketsOpt )
  1558      */
  1559     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1561         List<JCTypeAnnotation> topAnnos = List.nil();
  1562         if (elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
  1563             JCAnnotatedType atype = (JCAnnotatedType) elemtype;
  1564             topAnnos = atype.annotations;
  1565             elemtype = atype.underlyingType;
  1568         List<JCTypeAnnotation> annos = typeAnnotationsOpt();
  1570         accept(LBRACKET);
  1572         if (S.token() == RBRACKET) {
  1573             accept(RBRACKET);
  1575             elemtype = bracketsOpt(elemtype, annos);
  1577             if (S.token() == LBRACE) {
  1578                 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
  1580                 na.annotations = topAnnos;
  1582                 return na;
  1583             } else {
  1584                 return syntaxError(S.pos(), "array.dimension.missing");
  1586         } else {
  1587             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1589             // maintain array dimension type annotations
  1590             ListBuffer<List<JCTypeAnnotation>> dimAnnotations = ListBuffer.lb();
  1591             dimAnnotations.append(annos);
  1593             dims.append(parseExpression());
  1594             accept(RBRACKET);
  1595             while (S.token() == LBRACKET
  1596                     || (S.token() == MONKEYS_AT)) {
  1597                 List<JCTypeAnnotation> maybeDimAnnos = typeAnnotationsOpt();
  1598                 int pos = S.pos();
  1599                 S.nextToken();
  1600                 if (S.token() == RBRACKET) {
  1601                     elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
  1602                 } else {
  1603                     if (S.token() == RBRACKET) { // no dimension
  1604                         elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
  1605                     } else {
  1606                         dimAnnotations.append(maybeDimAnnos);
  1607                         dims.append(parseExpression());
  1608                         accept(RBRACKET);
  1613             JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1614             na.annotations = topAnnos;
  1615             na.dimAnnotations = dimAnnotations.toList();
  1616             return na;
  1620     /** ClassCreatorRest = Arguments [ClassBody]
  1621      */
  1622     JCNewClass classCreatorRest(int newpos,
  1623                                   JCExpression encl,
  1624                                   List<JCExpression> typeArgs,
  1625                                   JCExpression t)
  1627         List<JCExpression> args = arguments();
  1628         JCClassDecl body = null;
  1629         if (S.token() == LBRACE) {
  1630             int pos = S.pos();
  1631             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1632             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1633             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1635         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1638     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1639      */
  1640     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1641         accept(LBRACE);
  1642         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1643         if (S.token() == COMMA) {
  1644             S.nextToken();
  1645         } else if (S.token() != RBRACE) {
  1646             elems.append(variableInitializer());
  1647             while (S.token() == COMMA) {
  1648                 S.nextToken();
  1649                 if (S.token() == RBRACE) break;
  1650                 elems.append(variableInitializer());
  1653         accept(RBRACE);
  1654         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1657     /** VariableInitializer = ArrayInitializer | Expression
  1658      */
  1659     public JCExpression variableInitializer() {
  1660         return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
  1663     /** ParExpression = "(" Expression ")"
  1664      */
  1665     JCExpression parExpression() {
  1666         accept(LPAREN);
  1667         JCExpression t = parseExpression();
  1668         accept(RPAREN);
  1669         return t;
  1672     /** Block = "{" BlockStatements "}"
  1673      */
  1674     JCBlock block(int pos, long flags) {
  1675         accept(LBRACE);
  1676         List<JCStatement> stats = blockStatements();
  1677         JCBlock t = F.at(pos).Block(flags, stats);
  1678         while (S.token() == CASE || S.token() == DEFAULT) {
  1679             syntaxError("orphaned", S.token());
  1680             switchBlockStatementGroups();
  1682         // the Block node has a field "endpos" for first char of last token, which is
  1683         // usually but not necessarily the last char of the last token.
  1684         t.endpos = S.pos();
  1685         accept(RBRACE);
  1686         return toP(t);
  1689     public JCBlock block() {
  1690         return block(S.pos(), 0);
  1693     /** BlockStatements = { BlockStatement }
  1694      *  BlockStatement  = LocalVariableDeclarationStatement
  1695      *                  | ClassOrInterfaceOrEnumDeclaration
  1696      *                  | [Ident ":"] Statement
  1697      *  LocalVariableDeclarationStatement
  1698      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1699      */
  1700     @SuppressWarnings("fallthrough")
  1701     List<JCStatement> blockStatements() {
  1702 //todo: skip to anchor on error(?)
  1703         int lastErrPos = -1;
  1704         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1705         while (true) {
  1706             int pos = S.pos();
  1707             switch (S.token()) {
  1708             case RBRACE: case CASE: case DEFAULT: case EOF:
  1709                 return stats.toList();
  1710             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1711             case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1712             case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1713                 stats.append(parseStatement());
  1714                 break;
  1715             case MONKEYS_AT:
  1716             case FINAL: {
  1717                 String dc = S.docComment();
  1718                 JCModifiers mods = modifiersOpt();
  1719                 if (S.token() == INTERFACE ||
  1720                     S.token() == CLASS ||
  1721                     allowEnums && S.token() == ENUM) {
  1722                     stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1723                 } else {
  1724                     JCExpression t = parseType();
  1725                     stats.appendList(variableDeclarators(mods, t,
  1726                                                          new ListBuffer<JCStatement>()));
  1727                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1728                     storeEnd(stats.elems.last(), S.endPos());
  1729                     accept(SEMI);
  1731                 break;
  1733             case ABSTRACT: case STRICTFP: {
  1734                 String dc = S.docComment();
  1735                 JCModifiers mods = modifiersOpt();
  1736                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1737                 break;
  1739             case INTERFACE:
  1740             case CLASS:
  1741                 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1742                                                                S.docComment()));
  1743                 break;
  1744             case ENUM:
  1745             case ASSERT:
  1746                 if (allowEnums && S.token() == ENUM) {
  1747                     log.error(S.pos(), "local.enum");
  1748                     stats.
  1749                         append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1750                                                                  S.docComment()));
  1751                     break;
  1752                 } else if (allowAsserts && S.token() == ASSERT) {
  1753                     stats.append(parseStatement());
  1754                     break;
  1756                 /* fall through to default */
  1757             default:
  1758                 Name name = S.name();
  1759                 JCExpression t = term(EXPR | TYPE);
  1760                 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
  1761                     S.nextToken();
  1762                     JCStatement stat = parseStatement();
  1763                     stats.append(F.at(pos).Labelled(name, stat));
  1764                 } else if ((lastmode & TYPE) != 0 &&
  1765                            (S.token() == IDENTIFIER ||
  1766                             S.token() == ASSERT ||
  1767                             S.token() == ENUM)) {
  1768                     pos = S.pos();
  1769                     JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1770                     F.at(pos);
  1771                     stats.appendList(variableDeclarators(mods, t,
  1772                                                          new ListBuffer<JCStatement>()));
  1773                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1774                     storeEnd(stats.elems.last(), S.endPos());
  1775                     accept(SEMI);
  1776                 } else {
  1777                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1778                     stats.append(to(F.at(pos).Exec(checkExprStat(t))));
  1779                     accept(SEMI);
  1783             // error recovery
  1784             if (S.pos() == lastErrPos)
  1785                 return stats.toList();
  1786             if (S.pos() <= errorEndPos) {
  1787                 skip(false, true, true, true);
  1788                 lastErrPos = S.pos();
  1791             // ensure no dangling /** @deprecated */ active
  1792             S.resetDeprecatedFlag();
  1796     /** Statement =
  1797      *       Block
  1798      *     | IF ParExpression Statement [ELSE Statement]
  1799      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1800      *     | FOR "(" FormalParameter : Expression ")" Statement
  1801      *     | WHILE ParExpression Statement
  1802      *     | DO Statement WHILE ParExpression ";"
  1803      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1804      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1805      *     | SYNCHRONIZED ParExpression Block
  1806      *     | RETURN [Expression] ";"
  1807      *     | THROW Expression ";"
  1808      *     | BREAK [Ident] ";"
  1809      *     | CONTINUE [Ident] ";"
  1810      *     | ASSERT Expression [ ":" Expression ] ";"
  1811      *     | ";"
  1812      *     | ExpressionStatement
  1813      *     | Ident ":" Statement
  1814      */
  1815     @SuppressWarnings("fallthrough")
  1816     public JCStatement parseStatement() {
  1817         int pos = S.pos();
  1818         switch (S.token()) {
  1819         case LBRACE:
  1820             return block();
  1821         case IF: {
  1822             S.nextToken();
  1823             JCExpression cond = parExpression();
  1824             JCStatement thenpart = parseStatement();
  1825             JCStatement elsepart = null;
  1826             if (S.token() == ELSE) {
  1827                 S.nextToken();
  1828                 elsepart = parseStatement();
  1830             return F.at(pos).If(cond, thenpart, elsepart);
  1832         case FOR: {
  1833             S.nextToken();
  1834             accept(LPAREN);
  1835             List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
  1836             if (inits.length() == 1 &&
  1837                 inits.head.getTag() == JCTree.VARDEF &&
  1838                 ((JCVariableDecl) inits.head).init == null &&
  1839                 S.token() == COLON) {
  1840                 checkForeach();
  1841                 JCVariableDecl var = (JCVariableDecl)inits.head;
  1842                 accept(COLON);
  1843                 JCExpression expr = parseExpression();
  1844                 accept(RPAREN);
  1845                 JCStatement body = parseStatement();
  1846                 return F.at(pos).ForeachLoop(var, expr, body);
  1847             } else {
  1848                 accept(SEMI);
  1849                 JCExpression cond = S.token() == SEMI ? null : parseExpression();
  1850                 accept(SEMI);
  1851                 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  1852                 accept(RPAREN);
  1853                 JCStatement body = parseStatement();
  1854                 return F.at(pos).ForLoop(inits, cond, steps, body);
  1857         case WHILE: {
  1858             S.nextToken();
  1859             JCExpression cond = parExpression();
  1860             JCStatement body = parseStatement();
  1861             return F.at(pos).WhileLoop(cond, body);
  1863         case DO: {
  1864             S.nextToken();
  1865             JCStatement body = parseStatement();
  1866             accept(WHILE);
  1867             JCExpression cond = parExpression();
  1868             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  1869             accept(SEMI);
  1870             return t;
  1872         case TRY: {
  1873             S.nextToken();
  1874             JCBlock body = block();
  1875             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  1876             JCBlock finalizer = null;
  1877             if (S.token() == CATCH || S.token() == FINALLY) {
  1878                 while (S.token() == CATCH) catchers.append(catchClause());
  1879                 if (S.token() == FINALLY) {
  1880                     S.nextToken();
  1881                     finalizer = block();
  1883             } else {
  1884                 log.error(pos, "try.without.catch.or.finally");
  1886             return F.at(pos).Try(body, catchers.toList(), finalizer);
  1888         case SWITCH: {
  1889             S.nextToken();
  1890             JCExpression selector = parExpression();
  1891             accept(LBRACE);
  1892             List<JCCase> cases = switchBlockStatementGroups();
  1893             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  1894             accept(RBRACE);
  1895             return t;
  1897         case SYNCHRONIZED: {
  1898             S.nextToken();
  1899             JCExpression lock = parExpression();
  1900             JCBlock body = block();
  1901             return F.at(pos).Synchronized(lock, body);
  1903         case RETURN: {
  1904             S.nextToken();
  1905             JCExpression result = S.token() == SEMI ? null : parseExpression();
  1906             JCReturn t = to(F.at(pos).Return(result));
  1907             accept(SEMI);
  1908             return t;
  1910         case THROW: {
  1911             S.nextToken();
  1912             JCExpression exc = parseExpression();
  1913             JCThrow t = to(F.at(pos).Throw(exc));
  1914             accept(SEMI);
  1915             return t;
  1917         case BREAK: {
  1918             S.nextToken();
  1919             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1920             JCBreak t = to(F.at(pos).Break(label));
  1921             accept(SEMI);
  1922             return t;
  1924         case CONTINUE: {
  1925             S.nextToken();
  1926             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1927             JCContinue t =  to(F.at(pos).Continue(label));
  1928             accept(SEMI);
  1929             return t;
  1931         case SEMI:
  1932             S.nextToken();
  1933             return toP(F.at(pos).Skip());
  1934         case ELSE:
  1935             return toP(F.Exec(syntaxError("else.without.if")));
  1936         case FINALLY:
  1937             return toP(F.Exec(syntaxError("finally.without.try")));
  1938         case CATCH:
  1939             return toP(F.Exec(syntaxError("catch.without.try")));
  1940         case ASSERT: {
  1941             if (allowAsserts && S.token() == ASSERT) {
  1942                 S.nextToken();
  1943                 JCExpression assertion = parseExpression();
  1944                 JCExpression message = null;
  1945                 if (S.token() == COLON) {
  1946                     S.nextToken();
  1947                     message = parseExpression();
  1949                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  1950                 accept(SEMI);
  1951                 return t;
  1953             /* else fall through to default case */
  1955         case ENUM:
  1956         default:
  1957             Name name = S.name();
  1958             JCExpression expr = parseExpression();
  1959             if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
  1960                 S.nextToken();
  1961                 JCStatement stat = parseStatement();
  1962                 return F.at(pos).Labelled(name, stat);
  1963             } else {
  1964                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1965                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  1966                 accept(SEMI);
  1967                 return stat;
  1972     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  1973      */
  1974     JCCatch catchClause() {
  1975         int pos = S.pos();
  1976         accept(CATCH);
  1977         accept(LPAREN);
  1978         JCVariableDecl formal =
  1979             variableDeclaratorId(optFinal(Flags.PARAMETER),
  1980                                  qualident());
  1981         accept(RPAREN);
  1982         JCBlock body = block();
  1983         return F.at(pos).Catch(formal, body);
  1986     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  1987      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  1988      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  1989      */
  1990     List<JCCase> switchBlockStatementGroups() {
  1991         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  1992         while (true) {
  1993             int pos = S.pos();
  1994             switch (S.token()) {
  1995             case CASE: {
  1996                 S.nextToken();
  1997                 JCExpression pat = parseExpression();
  1998                 accept(COLON);
  1999                 List<JCStatement> stats = blockStatements();
  2000                 JCCase c = F.at(pos).Case(pat, stats);
  2001                 if (stats.isEmpty())
  2002                     storeEnd(c, S.prevEndPos());
  2003                 cases.append(c);
  2004                 break;
  2006             case DEFAULT: {
  2007                 S.nextToken();
  2008                 accept(COLON);
  2009                 List<JCStatement> stats = blockStatements();
  2010                 JCCase c = F.at(pos).Case(null, stats);
  2011                 if (stats.isEmpty())
  2012                     storeEnd(c, S.prevEndPos());
  2013                 cases.append(c);
  2014                 break;
  2016             case RBRACE: case EOF:
  2017                 return cases.toList();
  2018             default:
  2019                 S.nextToken(); // to ensure progress
  2020                 syntaxError(pos, "expected3",
  2021                     CASE, DEFAULT, RBRACE);
  2026     /** MoreStatementExpressions = { COMMA StatementExpression }
  2027      */
  2028     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2029                                                                     JCExpression first,
  2030                                                                     T stats) {
  2031         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2032         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2033         while (S.token() == COMMA) {
  2034             S.nextToken();
  2035             pos = S.pos();
  2036             JCExpression t = parseExpression();
  2037             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2038             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2040         return stats;
  2043     /** ForInit = StatementExpression MoreStatementExpressions
  2044      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2045      */
  2046     List<JCStatement> forInit() {
  2047         ListBuffer<JCStatement> stats = lb();
  2048         int pos = S.pos();
  2049         if (S.token() == FINAL || S.token() == MONKEYS_AT) {
  2050             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2051         } else {
  2052             JCExpression t = term(EXPR | TYPE);
  2053             if ((lastmode & TYPE) != 0 &&
  2054                 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
  2055                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2056             else
  2057                 return moreStatementExpressions(pos, t, stats).toList();
  2061     /** ForUpdate = StatementExpression MoreStatementExpressions
  2062      */
  2063     List<JCExpressionStatement> forUpdate() {
  2064         return moreStatementExpressions(S.pos(),
  2065                                         parseExpression(),
  2066                                         new ListBuffer<JCExpressionStatement>()).toList();
  2069     enum AnnotationKind { DEFAULT_ANNO, TYPE_ANNO };
  2071     /** AnnotationsOpt = { '@' Annotation }
  2072      */
  2073     List<JCAnnotation> annotationsOpt(AnnotationKind kind) {
  2074         if (S.token() != MONKEYS_AT) return List.nil(); // optimization
  2075         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2076         int prevmode = mode;
  2077         while (S.token() == MONKEYS_AT) {
  2078             int pos = S.pos();
  2079             S.nextToken();
  2080             buf.append(annotation(pos, kind));
  2082         lastmode = mode;
  2083         mode = prevmode;
  2084         List<JCAnnotation> annotations = buf.toList();
  2086         if (debugJSR308 && kind == AnnotationKind.TYPE_ANNO)
  2087             System.out.println("TA: parsing " + annotations
  2088                     + " in " + log.currentSourceFile());
  2089         return annotations;
  2092     List<JCTypeAnnotation> typeAnnotationsOpt() {
  2093         List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.TYPE_ANNO);
  2094         return List.convert(JCTypeAnnotation.class, annotations);
  2097     /** ModifiersOpt = { Modifier }
  2098      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2099      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2100      *           | "@" Annotation
  2101      */
  2102     JCModifiers modifiersOpt() {
  2103         return modifiersOpt(null);
  2105     JCModifiers modifiersOpt(JCModifiers partial) {
  2106         long flags = (partial == null) ? 0 : partial.flags;
  2107         if (S.deprecatedFlag()) {
  2108             flags |= Flags.DEPRECATED;
  2109             S.resetDeprecatedFlag();
  2111         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2112         if (partial != null) annotations.appendList(partial.annotations);
  2113         int pos = S.pos();
  2114         int lastPos = Position.NOPOS;
  2115     loop:
  2116         while (true) {
  2117             long flag;
  2118             switch (S.token()) {
  2119             case PRIVATE     : flag = Flags.PRIVATE; break;
  2120             case PROTECTED   : flag = Flags.PROTECTED; break;
  2121             case PUBLIC      : flag = Flags.PUBLIC; break;
  2122             case STATIC      : flag = Flags.STATIC; break;
  2123             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2124             case FINAL       : flag = Flags.FINAL; break;
  2125             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2126             case NATIVE      : flag = Flags.NATIVE; break;
  2127             case VOLATILE    : flag = Flags.VOLATILE; break;
  2128             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2129             case STRICTFP    : flag = Flags.STRICTFP; break;
  2130             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2131             default: break loop;
  2133             if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
  2134             lastPos = S.pos();
  2135             S.nextToken();
  2136             if (flag == Flags.ANNOTATION) {
  2137                 checkAnnotations();
  2138                 if (S.token() != INTERFACE) {
  2139                 JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO);
  2140                 // if first modifier is an annotation, set pos to annotation's.
  2141                 if (flags == 0 && annotations.isEmpty())
  2142                     pos = ann.pos;
  2143                 annotations.append(ann);
  2144                 lastPos = ann.pos;
  2145                     flag = 0;
  2148             flags |= flag;
  2150         switch (S.token()) {
  2151         case ENUM: flags |= Flags.ENUM; break;
  2152         case INTERFACE: flags |= Flags.INTERFACE; break;
  2153         default: break;
  2156         /* A modifiers tree with no modifier tokens or annotations
  2157          * has no text position. */
  2158         if (flags == 0 && annotations.isEmpty())
  2159             pos = Position.NOPOS;
  2161         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2162         if (pos != Position.NOPOS)
  2163             storeEnd(mods, S.prevEndPos());
  2164         return mods;
  2167     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2168      * @param pos position of "@" token
  2169      */
  2170     JCAnnotation annotation(int pos, AnnotationKind kind) {
  2171         // accept(AT); // AT consumed by caller
  2172         checkAnnotations();
  2173         if (kind == AnnotationKind.TYPE_ANNO)
  2174             checkTypeAnnotations();
  2175         JCTree ident = qualident();
  2176         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2177         JCAnnotation ann;
  2178         if (kind == AnnotationKind.DEFAULT_ANNO)
  2179             ann = F.at(pos).Annotation(ident, fieldValues);
  2180         else
  2181             ann = F.at(pos).TypeAnnotation(ident, fieldValues);
  2182         storeEnd(ann, S.prevEndPos());
  2183         return ann;
  2186     List<JCExpression> annotationFieldValuesOpt() {
  2187         return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2190     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2191     List<JCExpression> annotationFieldValues() {
  2192         accept(LPAREN);
  2193         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2194         if (S.token() != RPAREN) {
  2195             buf.append(annotationFieldValue());
  2196             while (S.token() == COMMA) {
  2197                 S.nextToken();
  2198                 buf.append(annotationFieldValue());
  2201         accept(RPAREN);
  2202         return buf.toList();
  2205     /** AnnotationFieldValue    = AnnotationValue
  2206      *                          | Identifier "=" AnnotationValue
  2207      */
  2208     JCExpression annotationFieldValue() {
  2209         if (S.token() == IDENTIFIER) {
  2210             mode = EXPR;
  2211             JCExpression t1 = term1();
  2212             if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
  2213                 int pos = S.pos();
  2214                 accept(EQ);
  2215                 return toP(F.at(pos).Assign(t1, annotationValue()));
  2216             } else {
  2217                 return t1;
  2220         return annotationValue();
  2223     /* AnnotationValue          = ConditionalExpression
  2224      *                          | Annotation
  2225      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
  2226      */
  2227     JCExpression annotationValue() {
  2228         int pos;
  2229         switch (S.token()) {
  2230         case MONKEYS_AT:
  2231             pos = S.pos();
  2232             S.nextToken();
  2233             return annotation(pos, AnnotationKind.DEFAULT_ANNO);
  2234         case LBRACE:
  2235             pos = S.pos();
  2236             accept(LBRACE);
  2237             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2238             if (S.token() != RBRACE) {
  2239                 buf.append(annotationValue());
  2240                 while (S.token() == COMMA) {
  2241                     S.nextToken();
  2242                     if (S.token() == RPAREN) break;
  2243                     buf.append(annotationValue());
  2246             accept(RBRACE);
  2247             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2248         default:
  2249             mode = EXPR;
  2250             return term1();
  2254     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2255      */
  2256     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2257                                                                          JCExpression type,
  2258                                                                          T vdefs)
  2260         return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
  2263     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2264      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2266      *  @param reqInit  Is an initializer always required?
  2267      *  @param dc       The documentation comment for the variable declarations, or null.
  2268      */
  2269     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2270                                                                      JCModifiers mods,
  2271                                                                      JCExpression type,
  2272                                                                      Name name,
  2273                                                                      boolean reqInit,
  2274                                                                      String dc,
  2275                                                                      T vdefs)
  2277         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2278         while (S.token() == COMMA) {
  2279             // All but last of multiple declarators subsume a comma
  2280             storeEnd((JCTree)vdefs.elems.last(), S.endPos());
  2281             S.nextToken();
  2282             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2284         return vdefs;
  2287     /** VariableDeclarator = Ident VariableDeclaratorRest
  2288      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2289      */
  2290     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
  2291         return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
  2294     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2295      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2297      *  @param reqInit  Is an initializer always required?
  2298      *  @param dc       The documentation comment for the variable declarations, or null.
  2299      */
  2300     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2301                                   boolean reqInit, String dc) {
  2302         type = bracketsOpt(type);
  2303         JCExpression init = null;
  2304         if (S.token() == EQ) {
  2305             S.nextToken();
  2306             init = variableInitializer();
  2308         else if (reqInit) syntaxError(S.pos(), "expected", EQ);
  2309         JCVariableDecl result =
  2310             toP(F.at(pos).VarDef(mods, name, type, init));
  2311         attach(result, dc);
  2312         return result;
  2315     /** VariableDeclaratorId = Ident BracketsOpt
  2316      */
  2317     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2318         int pos = S.pos();
  2319         Name name = ident();
  2320         if ((mods.flags & Flags.VARARGS) == 0)
  2321             type = bracketsOpt(type);
  2322         return toP(F.at(pos).VarDef(mods, name, type, null));
  2325     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2326      */
  2327     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2328         int pos = S.pos();
  2329         JCExpression pid = null;
  2330         String dc = S.docComment();
  2331         JCModifiers mods = null;
  2332         List<JCAnnotation> packageAnnotations = List.nil();
  2333         if (S.token() == MONKEYS_AT)
  2334             mods = modifiersOpt();
  2336         if (S.token() == PACKAGE) {
  2337             if (mods != null) {
  2338                 checkNoMods(mods.flags);
  2339                 packageAnnotations = mods.annotations;
  2340                 mods = null;
  2342             S.nextToken();
  2343             pid = qualident();
  2344             accept(SEMI);
  2346         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2347         boolean checkForImports = true;
  2348         while (S.token() != EOF) {
  2349             if (S.pos() <= errorEndPos) {
  2350                 // error recovery
  2351                 skip(checkForImports, false, false, false);
  2352                 if (S.token() == EOF)
  2353                     break;
  2355             if (checkForImports && mods == null && S.token() == IMPORT) {
  2356                 defs.append(importDeclaration());
  2357             } else {
  2358                 JCTree def = typeDeclaration(mods);
  2359                 if (def instanceof JCExpressionStatement)
  2360                     def = ((JCExpressionStatement)def).expr;
  2361                 defs.append(def);
  2362                 if (def instanceof JCClassDecl)
  2363                     checkForImports = false;
  2364                 mods = null;
  2367         JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
  2368         attach(toplevel, dc);
  2369         if (defs.elems.isEmpty())
  2370             storeEnd(toplevel, S.prevEndPos());
  2371         if (keepDocComments)
  2372             toplevel.docComments = docComments;
  2373         if (keepLineMap)
  2374             toplevel.lineMap = S.getLineMap();
  2375         return toplevel;
  2378     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2379      */
  2380     JCTree importDeclaration() {
  2381         int pos = S.pos();
  2382         S.nextToken();
  2383         boolean importStatic = false;
  2384         if (S.token() == STATIC) {
  2385             checkStaticImports();
  2386             importStatic = true;
  2387             S.nextToken();
  2389         JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
  2390         do {
  2391             int pos1 = S.pos();
  2392             accept(DOT);
  2393             if (S.token() == STAR) {
  2394                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2395                 S.nextToken();
  2396                 break;
  2397             } else {
  2398                 pid = toP(F.at(pos1).Select(pid, ident()));
  2400         } while (S.token() == DOT);
  2401         accept(SEMI);
  2402         return toP(F.at(pos).Import(pid, importStatic));
  2405     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2406      *                  | ";"
  2407      */
  2408     JCTree typeDeclaration(JCModifiers mods) {
  2409         int pos = S.pos();
  2410         if (mods == null && S.token() == SEMI) {
  2411             S.nextToken();
  2412             return toP(F.at(pos).Skip());
  2413         } else {
  2414             String dc = S.docComment();
  2415             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
  2419     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2420      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2421      *  @param mods     Any modifiers starting the class or interface declaration
  2422      *  @param dc       The documentation comment for the class, or null.
  2423      */
  2424     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
  2425         if (S.token() == CLASS) {
  2426             return classDeclaration(mods, dc);
  2427         } else if (S.token() == INTERFACE) {
  2428             return interfaceDeclaration(mods, dc);
  2429         } else if (allowEnums) {
  2430             if (S.token() == ENUM) {
  2431                 return enumDeclaration(mods, dc);
  2432             } else {
  2433                 int pos = S.pos();
  2434                 List<JCTree> errs;
  2435                 if (S.token() == IDENTIFIER) {
  2436                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2437                     setErrorEndPos(S.pos());
  2438                 } else {
  2439                     errs = List.<JCTree>of(mods);
  2441                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2442                                               CLASS, INTERFACE, ENUM)));
  2444         } else {
  2445             if (S.token() == ENUM) {
  2446                 log.error(S.pos(), "enums.not.supported.in.source", source.name);
  2447                 allowEnums = true;
  2448                 return enumDeclaration(mods, dc);
  2450             int pos = S.pos();
  2451             List<JCTree> errs;
  2452             if (S.token() == IDENTIFIER) {
  2453                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2454                 setErrorEndPos(S.pos());
  2455             } else {
  2456                 errs = List.<JCTree>of(mods);
  2458             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2459                                           CLASS, INTERFACE)));
  2463     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2464      *                     [IMPLEMENTS TypeList] ClassBody
  2465      *  @param mods    The modifiers starting the class declaration
  2466      *  @param dc       The documentation comment for the class, or null.
  2467      */
  2468     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
  2469         int pos = S.pos();
  2470         accept(CLASS);
  2471         Name name = ident();
  2473         List<JCTypeParameter> typarams = typeParametersOpt();
  2475         JCTree extending = null;
  2476         if (S.token() == EXTENDS) {
  2477             S.nextToken();
  2478             extending = parseType();
  2480         List<JCExpression> implementing = List.nil();
  2481         if (S.token() == IMPLEMENTS) {
  2482             S.nextToken();
  2483             implementing = typeList();
  2485         List<JCTree> defs = classOrInterfaceBody(name, false);
  2486         JCClassDecl result = toP(F.at(pos).ClassDef(
  2487             mods, name, typarams, extending, implementing, defs));
  2488         attach(result, dc);
  2489         return result;
  2492     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2493      *                         [EXTENDS TypeList] InterfaceBody
  2494      *  @param mods    The modifiers starting the interface declaration
  2495      *  @param dc       The documentation comment for the interface, or null.
  2496      */
  2497     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
  2498         int pos = S.pos();
  2499         accept(INTERFACE);
  2500         Name name = ident();
  2502         List<JCTypeParameter> typarams = typeParametersOpt();
  2504         List<JCExpression> extending = List.nil();
  2505         if (S.token() == EXTENDS) {
  2506             S.nextToken();
  2507             extending = typeList();
  2509         List<JCTree> defs = classOrInterfaceBody(name, true);
  2510         JCClassDecl result = toP(F.at(pos).ClassDef(
  2511             mods, name, typarams, null, extending, defs));
  2512         attach(result, dc);
  2513         return result;
  2516     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2517      *  @param mods    The modifiers starting the enum declaration
  2518      *  @param dc       The documentation comment for the enum, or null.
  2519      */
  2520     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
  2521         int pos = S.pos();
  2522         accept(ENUM);
  2523         Name name = ident();
  2525         List<JCExpression> implementing = List.nil();
  2526         if (S.token() == IMPLEMENTS) {
  2527             S.nextToken();
  2528             implementing = typeList();
  2531         List<JCTree> defs = enumBody(name);
  2532         JCModifiers newMods =
  2533             F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
  2534         JCClassDecl result = toP(F.at(pos).
  2535             ClassDef(newMods, name, List.<JCTypeParameter>nil(),
  2536                 null, implementing, defs));
  2537         attach(result, dc);
  2538         return result;
  2541     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2542      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2543      */
  2544     List<JCTree> enumBody(Name enumName) {
  2545         accept(LBRACE);
  2546         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2547         if (S.token() == COMMA) {
  2548             S.nextToken();
  2549         } else if (S.token() != RBRACE && S.token() != SEMI) {
  2550             defs.append(enumeratorDeclaration(enumName));
  2551             while (S.token() == COMMA) {
  2552                 S.nextToken();
  2553                 if (S.token() == RBRACE || S.token() == SEMI) break;
  2554                 defs.append(enumeratorDeclaration(enumName));
  2556             if (S.token() != SEMI && S.token() != RBRACE) {
  2557                 defs.append(syntaxError(S.pos(), "expected3",
  2558                                 COMMA, RBRACE, SEMI));
  2559                 S.nextToken();
  2562         if (S.token() == SEMI) {
  2563             S.nextToken();
  2564             while (S.token() != RBRACE && S.token() != EOF) {
  2565                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2566                                                                 false));
  2567                 if (S.pos() <= errorEndPos) {
  2568                     // error recovery
  2569                    skip(false, true, true, false);
  2573         accept(RBRACE);
  2574         return defs.toList();
  2577     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2578      */
  2579     JCTree enumeratorDeclaration(Name enumName) {
  2580         String dc = S.docComment();
  2581         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2582         if (S.deprecatedFlag()) {
  2583             flags |= Flags.DEPRECATED;
  2584             S.resetDeprecatedFlag();
  2586         int pos = S.pos();
  2587         List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
  2588         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2589         List<JCExpression> typeArgs = typeArgumentsOpt();
  2590         int identPos = S.pos();
  2591         Name name = ident();
  2592         int createPos = S.pos();
  2593         List<JCExpression> args = (S.token() == LPAREN)
  2594             ? arguments() : List.<JCExpression>nil();
  2595         JCClassDecl body = null;
  2596         if (S.token() == LBRACE) {
  2597             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2598             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2599             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2601         if (args.isEmpty() && body == null)
  2602             createPos = Position.NOPOS;
  2603         JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
  2604         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2605         if (createPos != Position.NOPOS)
  2606             storeEnd(create, S.prevEndPos());
  2607         ident = F.at(Position.NOPOS).Ident(enumName);
  2608         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2609         attach(result, dc);
  2610         return result;
  2613     /** TypeList = Type {"," Type}
  2614      */
  2615     List<JCExpression> typeList() {
  2616         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2617         ts.append(parseType());
  2618         while (S.token() == COMMA) {
  2619             S.nextToken();
  2620             ts.append(parseType());
  2622         return ts.toList();
  2625     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2626      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2627      */
  2628     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2629         accept(LBRACE);
  2630         if (S.pos() <= errorEndPos) {
  2631             // error recovery
  2632             skip(false, true, false, false);
  2633             if (S.token() == LBRACE)
  2634                 S.nextToken();
  2636         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2637         while (S.token() != RBRACE && S.token() != EOF) {
  2638             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2639             if (S.pos() <= errorEndPos) {
  2640                // error recovery
  2641                skip(false, true, true, false);
  2644         accept(RBRACE);
  2645         return defs.toList();
  2648     /** ClassBodyDeclaration =
  2649      *      ";"
  2650      *    | [STATIC] Block
  2651      *    | ModifiersOpt
  2652      *      ( Type Ident
  2653      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2654      *      | VOID Ident MethodDeclaratorRest
  2655      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2656      *      | Ident ConstructorDeclaratorRest
  2657      *      | TypeParameters Ident ConstructorDeclaratorRest
  2658      *      | ClassOrInterfaceOrEnumDeclaration
  2659      *      )
  2660      *  InterfaceBodyDeclaration =
  2661      *      ";"
  2662      *    | ModifiersOpt Type Ident
  2663      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2664      */
  2665     List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2666         if (S.token() == SEMI) {
  2667             S.nextToken();
  2668             return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
  2669         } else {
  2670             String dc = S.docComment();
  2671             int pos = S.pos();
  2672             JCModifiers mods = modifiersOpt();
  2673             if (S.token() == CLASS ||
  2674                 S.token() == INTERFACE ||
  2675                 allowEnums && S.token() == ENUM) {
  2676                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2677             } else if (S.token() == LBRACE && !isInterface &&
  2678                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2679                        mods.annotations.isEmpty()) {
  2680                 return List.<JCTree>of(block(pos, mods.flags));
  2681             } else {
  2682                 pos = S.pos();
  2683                 List<JCTypeParameter> typarams = typeParametersOpt();
  2684                 // Hack alert:  if there are type arguments but no Modifiers, the start
  2685                 // position will be lost unless we set the Modifiers position.  There
  2686                 // should be an AST node for type parameters (BugId 5005090).
  2687                 if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
  2688                     mods.pos = pos;
  2691                 List<JCAnnotation> annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
  2693                 Token token = S.token();
  2694                 Name name = S.name();
  2695                 pos = S.pos();
  2696                 JCExpression type;
  2697                 boolean isVoid = S.token() == VOID;
  2698                 if (isVoid) {
  2699                     if (annosAfterParams.nonEmpty())
  2700                         illegal(annosAfterParams.head.pos);
  2701                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  2702                     S.nextToken();
  2703                 } else {
  2704                     mods.annotations = mods.annotations.appendList(annosAfterParams);
  2705                     // method returns types are un-annotated types
  2706                     type = unannotatedType();
  2708                 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
  2709                     if (isInterface || name != className)
  2710                         log.error(pos, "invalid.meth.decl.ret.type.req");
  2711                     return List.of(methodDeclaratorRest(
  2712                         pos, mods, null, names.init, typarams,
  2713                         isInterface, true, dc));
  2714                 } else {
  2715                     pos = S.pos();
  2716                     name = ident();
  2717                     if (S.token() == LPAREN) {
  2718                         return List.of(methodDeclaratorRest(
  2719                             pos, mods, type, name, typarams,
  2720                             isInterface, isVoid, dc));
  2721                     } else if (!isVoid && typarams.isEmpty()) {
  2722                         List<JCTree> defs =
  2723                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2724                                                     new ListBuffer<JCTree>()).toList();
  2725                         storeEnd(defs.last(), S.endPos());
  2726                         accept(SEMI);
  2727                         return defs;
  2728                     } else {
  2729                         pos = S.pos();
  2730                         List<JCTree> err = isVoid
  2731                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2732                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2733                             : null;
  2734                         return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
  2741     /** MethodDeclaratorRest =
  2742      *      FormalParameters BracketsOpt [Annotations] [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2743      *  VoidMethodDeclaratorRest =
  2744      *      FormalParameters [Annotations] [Throws TypeList] ( MethodBody | ";")
  2745      *  InterfaceMethodDeclaratorRest =
  2746      *      FormalParameters BracketsOpt [Annotations] [THROWS TypeList] ";"
  2747      *  VoidInterfaceMethodDeclaratorRest =
  2748      *      FormalParameters [Annotations] [THROWS TypeList] ";"
  2749      *  ConstructorDeclaratorRest =
  2750      *      "(" FormalParameterListOpt ")" [Annotations] [THROWS TypeList] MethodBody
  2751      */
  2752     JCTree methodDeclaratorRest(int pos,
  2753                               JCModifiers mods,
  2754                               JCExpression type,
  2755                               Name name,
  2756                               List<JCTypeParameter> typarams,
  2757                               boolean isInterface, boolean isVoid,
  2758                               String dc) {
  2759         List<JCVariableDecl> params = formalParameters();
  2761         List<JCTypeAnnotation> receiverAnnotations;
  2762         if (!isVoid) {
  2763             // need to distinguish between receiver anno and array anno
  2764             // look at typeAnnotationsPushedBack comment
  2765             this.permitTypeAnnotationsPushBack = true;
  2766             type = methodReturnArrayRest(type);
  2767             this.permitTypeAnnotationsPushBack = false;
  2768             if (typeAnnotationsPushedBack == null)
  2769                 receiverAnnotations = List.nil();
  2770             else
  2771                 receiverAnnotations = typeAnnotationsPushedBack;
  2772             typeAnnotationsPushedBack = null;
  2773         } else
  2774             receiverAnnotations = typeAnnotationsOpt();
  2776         List<JCExpression> thrown = List.nil();
  2777         if (S.token() == THROWS) {
  2778             S.nextToken();
  2779             thrown = qualidentList();
  2781         JCBlock body = null;
  2782         JCExpression defaultValue;
  2783         if (S.token() == LBRACE) {
  2784             body = block();
  2785             defaultValue = null;
  2786         } else {
  2787             if (S.token() == DEFAULT) {
  2788                 accept(DEFAULT);
  2789                 defaultValue = annotationValue();
  2790             } else {
  2791                 defaultValue = null;
  2793             accept(SEMI);
  2794             if (S.pos() <= errorEndPos) {
  2795                 // error recovery
  2796                 skip(false, true, false, false);
  2797                 if (S.token() == LBRACE) {
  2798                     body = block();
  2802         JCMethodDecl result =
  2803             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2804                                     params, receiverAnnotations, thrown,
  2805                                     body, defaultValue));
  2806         attach(result, dc);
  2807         return result;
  2810     /** Parses the array levels after the format parameters list, and append
  2811      * them to the return type, while preseving the order of type annotations
  2812      */
  2813     private JCExpression methodReturnArrayRest(JCExpression type) {
  2814         if (type.getTag() != JCTree.TYPEARRAY)
  2815             return bracketsOpt(type);
  2817         JCArrayTypeTree baseArray = (JCArrayTypeTree)type;
  2818         while (TreeInfo.typeIn(baseArray.elemtype) instanceof JCArrayTypeTree)
  2819             baseArray = (JCArrayTypeTree)TreeInfo.typeIn(baseArray.elemtype);
  2821         if (baseArray.elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
  2822             JCAnnotatedType at = (JCAnnotatedType)baseArray.elemtype;
  2823             at.underlyingType = bracketsOpt(at.underlyingType);
  2824         } else {
  2825             baseArray.elemtype = bracketsOpt(baseArray.elemtype);
  2828         return type;
  2831     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
  2832      */
  2833     List<JCExpression> qualidentList() {
  2834         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2836         List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
  2837         if (!typeAnnos.isEmpty())
  2838             ts.append(F.AnnotatedType(typeAnnos, qualident()));
  2839         else
  2840             ts.append(qualident());
  2841         while (S.token() == COMMA) {
  2842             S.nextToken();
  2844             typeAnnos = typeAnnotationsOpt();
  2845             if (!typeAnnos.isEmpty())
  2846                 ts.append(F.AnnotatedType(typeAnnos, qualident()));
  2847             else
  2848                 ts.append(qualident());
  2850         return ts.toList();
  2853     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  2854      */
  2855     List<JCTypeParameter> typeParametersOpt() {
  2856         if (S.token() == LT) {
  2857             checkGenerics();
  2858             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  2859             S.nextToken();
  2860             typarams.append(typeParameter());
  2861             while (S.token() == COMMA) {
  2862                 S.nextToken();
  2863                 typarams.append(typeParameter());
  2865             accept(GT);
  2866             return typarams.toList();
  2867         } else {
  2868             return List.nil();
  2872     /** TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
  2873      *  TypeParameterBound = EXTENDS Type {"&" Type}
  2874      *  TypeVariable = Ident
  2875      */
  2876     JCTypeParameter typeParameter() {
  2877         int pos = S.pos();
  2878         List<JCTypeAnnotation> annos = typeAnnotationsOpt();
  2879         Name name = ident();
  2880         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  2881         if (S.token() == EXTENDS) {
  2882             S.nextToken();
  2883             bounds.append(parseType());
  2884             while (S.token() == AMP) {
  2885                 S.nextToken();
  2886                 bounds.append(parseType());
  2889         return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
  2892     /** FormalParameters = "(" [ FormalParameterList ] ")"
  2893      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  2894      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  2895      */
  2896     List<JCVariableDecl> formalParameters() {
  2897         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  2898         JCVariableDecl lastParam = null;
  2899         accept(LPAREN);
  2900         if (S.token() != RPAREN) {
  2901             params.append(lastParam = formalParameter());
  2902             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
  2903                 S.nextToken();
  2904                 params.append(lastParam = formalParameter());
  2907         accept(RPAREN);
  2908         return params.toList();
  2911     JCModifiers optFinal(long flags) {
  2912         JCModifiers mods = modifiersOpt();
  2913         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  2914         mods.flags |= flags;
  2915         return mods;
  2918     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  2919      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  2920      */
  2921     JCVariableDecl formalParameter() {
  2922         JCModifiers mods = optFinal(Flags.PARAMETER);
  2923         // need to distinguish between vararg annos and array annos
  2924         // look at typeAnnotaitonsPushedBack comment
  2925         this.permitTypeAnnotationsPushBack = true;
  2926         JCExpression type = parseType();
  2927         this.permitTypeAnnotationsPushBack = false;
  2929         if (S.token() == ELLIPSIS) {
  2930             List<JCTypeAnnotation> varargsAnnos = typeAnnotationsPushedBack;
  2931             typeAnnotationsPushedBack = null;
  2932             checkVarargs();
  2933             mods.flags |= Flags.VARARGS;
  2934             // insert var arg type annotations
  2935             if (varargsAnnos != null && varargsAnnos.nonEmpty())
  2936                 type = F.at(S.pos()).AnnotatedType(varargsAnnos, type);
  2937             type = to(F.at(S.pos()).TypeArray(type));
  2939             S.nextToken();
  2940         } else {
  2941             // if not a var arg, then typeAnnotationsPushedBack should be null
  2942             if (typeAnnotationsPushedBack != null
  2943                     && !typeAnnotationsPushedBack.isEmpty()) {
  2944                 reportSyntaxError(typeAnnotationsPushedBack.head.pos,
  2945                         "illegal.start.of.type");
  2947             typeAnnotationsPushedBack = null;
  2949         return variableDeclaratorId(mods, type);
  2952 /* ---------- auxiliary methods -------------- */
  2954     /** Check that given tree is a legal expression statement.
  2955      */
  2956     protected JCExpression checkExprStat(JCExpression t) {
  2957         switch(t.getTag()) {
  2958         case JCTree.PREINC: case JCTree.PREDEC:
  2959         case JCTree.POSTINC: case JCTree.POSTDEC:
  2960         case JCTree.ASSIGN:
  2961         case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
  2962         case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
  2963         case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
  2964         case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
  2965         case JCTree.APPLY: case JCTree.NEWCLASS:
  2966         case JCTree.ERRONEOUS:
  2967             return t;
  2968         default:
  2969             log.error(t.pos, "not.stmt");
  2970             return F.at(t.pos).Erroneous(List.<JCTree>of(t));
  2974     /** Return precedence of operator represented by token,
  2975      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  2976      */
  2977     static int prec(Token token) {
  2978         int oc = optag(token);
  2979         return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
  2982     /** Return operation tag of binary operator represented by token,
  2983      *  -1 if token is not a binary operator.
  2984      */
  2985     static int optag(Token token) {
  2986         switch (token) {
  2987         case BARBAR:
  2988             return JCTree.OR;
  2989         case AMPAMP:
  2990             return JCTree.AND;
  2991         case BAR:
  2992             return JCTree.BITOR;
  2993         case BAREQ:
  2994             return JCTree.BITOR_ASG;
  2995         case CARET:
  2996             return JCTree.BITXOR;
  2997         case CARETEQ:
  2998             return JCTree.BITXOR_ASG;
  2999         case AMP:
  3000             return JCTree.BITAND;
  3001         case AMPEQ:
  3002             return JCTree.BITAND_ASG;
  3003         case EQEQ:
  3004             return JCTree.EQ;
  3005         case BANGEQ:
  3006             return JCTree.NE;
  3007         case LT:
  3008             return JCTree.LT;
  3009         case GT:
  3010             return JCTree.GT;
  3011         case LTEQ:
  3012             return JCTree.LE;
  3013         case GTEQ:
  3014             return JCTree.GE;
  3015         case LTLT:
  3016             return JCTree.SL;
  3017         case LTLTEQ:
  3018             return JCTree.SL_ASG;
  3019         case GTGT:
  3020             return JCTree.SR;
  3021         case GTGTEQ:
  3022             return JCTree.SR_ASG;
  3023         case GTGTGT:
  3024             return JCTree.USR;
  3025         case GTGTGTEQ:
  3026             return JCTree.USR_ASG;
  3027         case PLUS:
  3028             return JCTree.PLUS;
  3029         case PLUSEQ:
  3030             return JCTree.PLUS_ASG;
  3031         case SUB:
  3032             return JCTree.MINUS;
  3033         case SUBEQ:
  3034             return JCTree.MINUS_ASG;
  3035         case STAR:
  3036             return JCTree.MUL;
  3037         case STAREQ:
  3038             return JCTree.MUL_ASG;
  3039         case SLASH:
  3040             return JCTree.DIV;
  3041         case SLASHEQ:
  3042             return JCTree.DIV_ASG;
  3043         case PERCENT:
  3044             return JCTree.MOD;
  3045         case PERCENTEQ:
  3046             return JCTree.MOD_ASG;
  3047         case INSTANCEOF:
  3048             return JCTree.TYPETEST;
  3049         default:
  3050             return -1;
  3054     /** Return operation tag of unary operator represented by token,
  3055      *  -1 if token is not a binary operator.
  3056      */
  3057     static int unoptag(Token token) {
  3058         switch (token) {
  3059         case PLUS:
  3060             return JCTree.POS;
  3061         case SUB:
  3062             return JCTree.NEG;
  3063         case BANG:
  3064             return JCTree.NOT;
  3065         case TILDE:
  3066             return JCTree.COMPL;
  3067         case PLUSPLUS:
  3068             return JCTree.PREINC;
  3069         case SUBSUB:
  3070             return JCTree.PREDEC;
  3071         default:
  3072             return -1;
  3076     /** Return type tag of basic type represented by token,
  3077      *  -1 if token is not a basic type identifier.
  3078      */
  3079     static int typetag(Token token) {
  3080         switch (token) {
  3081         case BYTE:
  3082             return TypeTags.BYTE;
  3083         case CHAR:
  3084             return TypeTags.CHAR;
  3085         case SHORT:
  3086             return TypeTags.SHORT;
  3087         case INT:
  3088             return TypeTags.INT;
  3089         case LONG:
  3090             return TypeTags.LONG;
  3091         case FLOAT:
  3092             return TypeTags.FLOAT;
  3093         case DOUBLE:
  3094             return TypeTags.DOUBLE;
  3095         case BOOLEAN:
  3096             return TypeTags.BOOLEAN;
  3097         default:
  3098             return -1;
  3102     void checkGenerics() {
  3103         if (!allowGenerics) {
  3104             log.error(S.pos(), "generics.not.supported.in.source", source.name);
  3105             allowGenerics = true;
  3108     void checkVarargs() {
  3109         if (!allowVarargs) {
  3110             log.error(S.pos(), "varargs.not.supported.in.source", source.name);
  3111             allowVarargs = true;
  3114     void checkForeach() {
  3115         if (!allowForeach) {
  3116             log.error(S.pos(), "foreach.not.supported.in.source", source.name);
  3117             allowForeach = true;
  3120     void checkStaticImports() {
  3121         if (!allowStaticImport) {
  3122             log.error(S.pos(), "static.import.not.supported.in.source", source.name);
  3123             allowStaticImport = true;
  3126     void checkAnnotations() {
  3127         if (!allowAnnotations) {
  3128             log.error(S.pos(), "annotations.not.supported.in.source", source.name);
  3129             allowAnnotations = true;
  3132     void checkTypeAnnotations() {
  3133         if (!allowTypeAnnotations) {
  3134             log.error(S.pos(), "type.annotations.not.supported.in.source", source.name);
  3135             allowTypeAnnotations = true;

mercurial