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

Mon, 26 Jul 2010 14:25:56 -0700

author
jjg
date
Mon, 26 Jul 2010 14:25:56 -0700
changeset 612
d1bd93028447
parent 609
13354e1abba7
child 613
b29160d1b3e0
permissions
-rw-r--r--

6957438: improve code for generating warning messages containing option names
Reviewed-by: mcimadamore

     1 /*
     2  * Copyright (c) 1999, 2009, Oracle and/or its affiliates. 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * 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 supported API.
    47  *  If 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.allowTWR = source.allowTryWithResources();
   135         this.allowDiamond = source.allowDiamond();
   136         this.allowMulticatch = source.allowMulticatch();
   137         this.allowTypeAnnotations = source.allowTypeAnnotations();
   138         this.keepDocComments = keepDocComments;
   139         if (keepDocComments)
   140             docComments = new HashMap<JCTree,String>();
   141         this.keepLineMap = keepLineMap;
   142         this.errorTree = F.Erroneous();
   143         this.debugJSR308 = fac.options.get("TA:parser") != null;
   144     }
   146     /** Switch: debug output for type-annotations operations
   147      */
   148     boolean debugJSR308;
   150     /** Switch: Should generics be recognized?
   151      */
   152     boolean allowGenerics;
   154     /** Switch: Should diamond operator be recognized?
   155      */
   156     boolean allowDiamond;
   158     /** Switch: Should multicatch clause be accepted?
   159      */
   160     boolean allowMulticatch;
   162     /** Switch: Should varargs be recognized?
   163      */
   164     boolean allowVarargs;
   166     /** Switch: should we recognize assert statements, or just give a warning?
   167      */
   168     boolean allowAsserts;
   170     /** Switch: should we recognize enums, or just give a warning?
   171      */
   172     boolean allowEnums;
   174     /** Switch: should we recognize foreach?
   175      */
   176     boolean allowForeach;
   178     /** Switch: should we recognize foreach?
   179      */
   180     boolean allowStaticImport;
   182     /** Switch: should we recognize annotations?
   183      */
   184     boolean allowAnnotations;
   186     /** Switch: should we recognize type annotations?
   187      */
   188     boolean allowTypeAnnotations;
   190     /** Switch: should we recognize automatic resource management?
   191      */
   192     boolean allowTWR;
   194     /** Switch: should we keep docComments?
   195      */
   196     boolean keepDocComments;
   198     /** Switch: should we keep line table?
   199      */
   200     boolean keepLineMap;
   202     /** When terms are parsed, the mode determines which is expected:
   203      *     mode = EXPR        : an expression
   204      *     mode = TYPE        : a type
   205      *     mode = NOPARAMS    : no parameters allowed for type
   206      *     mode = TYPEARG     : type argument
   207      */
   208     static final int EXPR = 0x1;
   209     static final int TYPE = 0x2;
   210     static final int NOPARAMS = 0x4;
   211     static final int TYPEARG = 0x8;
   212     static final int DIAMOND = 0x10;
   214     /** The current mode.
   215      */
   216     private int mode = 0;
   218     /** The mode of the term that was parsed last.
   219      */
   220     private int lastmode = 0;
   222 /* ---------- error recovery -------------- */
   224     private JCErroneous errorTree;
   226     /** Skip forward until a suitable stop token is found.
   227      */
   228     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   229          while (true) {
   230              switch (S.token()) {
   231                 case SEMI:
   232                     S.nextToken();
   233                     return;
   234                 case PUBLIC:
   235                 case FINAL:
   236                 case ABSTRACT:
   237                 case MONKEYS_AT:
   238                 case EOF:
   239                 case CLASS:
   240                 case INTERFACE:
   241                 case ENUM:
   242                     return;
   243                 case IMPORT:
   244                     if (stopAtImport)
   245                         return;
   246                     break;
   247                 case LBRACE:
   248                 case RBRACE:
   249                 case PRIVATE:
   250                 case PROTECTED:
   251                 case STATIC:
   252                 case TRANSIENT:
   253                 case NATIVE:
   254                 case VOLATILE:
   255                 case SYNCHRONIZED:
   256                 case STRICTFP:
   257                 case LT:
   258                 case BYTE:
   259                 case SHORT:
   260                 case CHAR:
   261                 case INT:
   262                 case LONG:
   263                 case FLOAT:
   264                 case DOUBLE:
   265                 case BOOLEAN:
   266                 case VOID:
   267                     if (stopAtMemberDecl)
   268                         return;
   269                     break;
   270                 case IDENTIFIER:
   271                    if (stopAtIdentifier)
   272                         return;
   273                     break;
   274                 case CASE:
   275                 case DEFAULT:
   276                 case IF:
   277                 case FOR:
   278                 case WHILE:
   279                 case DO:
   280                 case TRY:
   281                 case SWITCH:
   282                 case RETURN:
   283                 case THROW:
   284                 case BREAK:
   285                 case CONTINUE:
   286                 case ELSE:
   287                 case FINALLY:
   288                 case CATCH:
   289                     if (stopAtStatement)
   290                         return;
   291                     break;
   292             }
   293             S.nextToken();
   294         }
   295     }
   297     private JCErroneous syntaxError(int pos, String key, Token... args) {
   298         return syntaxError(pos, null, key, args);
   299     }
   301     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
   302         setErrorEndPos(pos);
   303         reportSyntaxError(pos, key, (Object[])args);
   304         return toP(F.at(pos).Erroneous(errs));
   305     }
   307     private int errorPos = Position.NOPOS;
   308     /**
   309      * Report a syntax error at given position using the given
   310      * argument unless one was already reported at the same position.
   311      */
   312     private void reportSyntaxError(int pos, String key, Object... args) {
   313         if (pos > S.errPos() || pos == Position.NOPOS) {
   314             if (S.token() == EOF)
   315                 log.error(pos, "premature.eof");
   316             else
   317                 log.error(pos, key, args);
   318         }
   319         S.errPos(pos);
   320         if (S.pos() == errorPos)
   321             S.nextToken(); // guarantee progress
   322         errorPos = S.pos();
   323     }
   326     /** Generate a syntax error at current position unless one was already
   327      *  reported at the same position.
   328      */
   329     private JCErroneous syntaxError(String key) {
   330         return syntaxError(S.pos(), key);
   331     }
   333     /** Generate a syntax error at current position unless one was
   334      *  already reported at the same position.
   335      */
   336     private JCErroneous syntaxError(String key, Token arg) {
   337         return syntaxError(S.pos(), key, arg);
   338     }
   340     /** If next input token matches given token, skip it, otherwise report
   341      *  an error.
   342      */
   343     public void accept(Token token) {
   344         if (S.token() == token) {
   345             S.nextToken();
   346         } else {
   347             setErrorEndPos(S.pos());
   348             reportSyntaxError(S.prevEndPos(), "expected", token);
   349         }
   350     }
   352     /** Report an illegal start of expression/type error at given position.
   353      */
   354     JCExpression illegal(int pos) {
   355         setErrorEndPos(S.pos());
   356         if ((mode & EXPR) != 0)
   357             return syntaxError(pos, "illegal.start.of.expr");
   358         else
   359             return syntaxError(pos, "illegal.start.of.type");
   361     }
   363     /** Report an illegal start of expression/type error at current position.
   364      */
   365     JCExpression illegal() {
   366         return illegal(S.pos());
   367     }
   369     /** Diagnose a modifier flag from the set, if any. */
   370     void checkNoMods(long mods) {
   371         if (mods != 0) {
   372             long lowestMod = mods & -mods;
   373             log.error(S.pos(), "mod.not.allowed.here",
   374                       Flags.asFlagSet(lowestMod));
   375         }
   376     }
   378 /* ---------- doc comments --------- */
   380     /** A hashtable to store all documentation comments
   381      *  indexed by the tree nodes they refer to.
   382      *  defined only if option flag keepDocComment is set.
   383      */
   384     Map<JCTree, String> docComments;
   386     /** Make an entry into docComments hashtable,
   387      *  provided flag keepDocComments is set and given doc comment is non-null.
   388      *  @param tree   The tree to be used as index in the hashtable
   389      *  @param dc     The doc comment to associate with the tree, or null.
   390      */
   391     void attach(JCTree tree, String dc) {
   392         if (keepDocComments && dc != null) {
   393 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   394             docComments.put(tree, dc);
   395         }
   396     }
   398 /* -------- source positions ------- */
   400     private int errorEndPos = -1;
   402     private void setErrorEndPos(int errPos) {
   403         if (errPos > errorEndPos)
   404             errorEndPos = errPos;
   405     }
   407     protected int getErrorEndPos() {
   408         return errorEndPos;
   409     }
   411     /**
   412      * Store ending position for a tree.
   413      * @param tree   The tree.
   414      * @param endpos The ending position to associate with the tree.
   415      */
   416     protected void storeEnd(JCTree tree, int endpos) {}
   418     /**
   419      * Store ending position for a tree.  The ending position should
   420      * be the ending position of the current token.
   421      * @param t The tree.
   422      */
   423     protected <T extends JCTree> T to(T t) { return t; }
   425     /**
   426      * Store ending position for a tree.  The ending position should
   427      * be greater of the ending position of the previous token and errorEndPos.
   428      * @param t The tree.
   429      */
   430     protected <T extends JCTree> T toP(T t) { return t; }
   432     /** Get the start position for a tree node.  The start position is
   433      * defined to be the position of the first character of the first
   434      * token of the node's source text.
   435      * @param tree  The tree node
   436      */
   437     public int getStartPos(JCTree tree) {
   438         return TreeInfo.getStartPos(tree);
   439     }
   441     /**
   442      * Get the end position for a tree node.  The end position is
   443      * defined to be the position of the last character of the last
   444      * token of the node's source text.  Returns Position.NOPOS if end
   445      * positions are not generated or the position is otherwise not
   446      * found.
   447      * @param tree  The tree node
   448      */
   449     public int getEndPos(JCTree tree) {
   450         return Position.NOPOS;
   451     }
   455 /* ---------- parsing -------------- */
   457     /**
   458      * Ident = IDENTIFIER
   459      */
   460     Name ident() {
   461         if (S.token() == IDENTIFIER) {
   462             Name name = S.name();
   463             S.nextToken();
   464             return name;
   465         } else if (S.token() == ASSERT) {
   466             if (allowAsserts) {
   467                 log.error(S.pos(), "assert.as.identifier");
   468                 S.nextToken();
   469                 return names.error;
   470             } else {
   471                 log.warning(S.pos(), "assert.as.identifier");
   472                 Name name = S.name();
   473                 S.nextToken();
   474                 return name;
   475             }
   476         } else if (S.token() == ENUM) {
   477             if (allowEnums) {
   478                 log.error(S.pos(), "enum.as.identifier");
   479                 S.nextToken();
   480                 return names.error;
   481             } else {
   482                 log.warning(S.pos(), "enum.as.identifier");
   483                 Name name = S.name();
   484                 S.nextToken();
   485                 return name;
   486             }
   487         } else {
   488             accept(IDENTIFIER);
   489             return names.error;
   490         }
   491 }
   493     /**
   494      * Qualident = Ident { DOT Ident }
   495      */
   496     public JCExpression qualident() {
   497         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
   498         while (S.token() == DOT) {
   499             int pos = S.pos();
   500             S.nextToken();
   501             t = toP(F.at(pos).Select(t, ident()));
   502         }
   503         return t;
   504     }
   506     /**
   507      * Literal =
   508      *     INTLITERAL
   509      *   | LONGLITERAL
   510      *   | FLOATLITERAL
   511      *   | DOUBLELITERAL
   512      *   | CHARLITERAL
   513      *   | STRINGLITERAL
   514      *   | TRUE
   515      *   | FALSE
   516      *   | NULL
   517      */
   518     JCExpression literal(Name prefix) {
   519         int pos = S.pos();
   520         JCExpression t = errorTree;
   521         switch (S.token()) {
   522         case INTLITERAL:
   523             try {
   524                 t = F.at(pos).Literal(
   525                     TypeTags.INT,
   526                     Convert.string2int(strval(prefix), S.radix()));
   527             } catch (NumberFormatException ex) {
   528                 log.error(S.pos(), "int.number.too.large", strval(prefix));
   529             }
   530             break;
   531         case LONGLITERAL:
   532             try {
   533                 t = F.at(pos).Literal(
   534                     TypeTags.LONG,
   535                     new Long(Convert.string2long(strval(prefix), S.radix())));
   536             } catch (NumberFormatException ex) {
   537                 log.error(S.pos(), "int.number.too.large", strval(prefix));
   538             }
   539             break;
   540         case FLOATLITERAL: {
   541             String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
   542             Float n;
   543             try {
   544                 n = Float.valueOf(proper);
   545             } catch (NumberFormatException ex) {
   546                 // error already repoted in scanner
   547                 n = Float.NaN;
   548             }
   549             if (n.floatValue() == 0.0f && !isZero(proper))
   550                 log.error(S.pos(), "fp.number.too.small");
   551             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   552                 log.error(S.pos(), "fp.number.too.large");
   553             else
   554                 t = F.at(pos).Literal(TypeTags.FLOAT, n);
   555             break;
   556         }
   557         case DOUBLELITERAL: {
   558             String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
   559             Double n;
   560             try {
   561                 n = Double.valueOf(proper);
   562             } catch (NumberFormatException ex) {
   563                 // error already reported in scanner
   564                 n = Double.NaN;
   565             }
   566             if (n.doubleValue() == 0.0d && !isZero(proper))
   567                 log.error(S.pos(), "fp.number.too.small");
   568             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   569                 log.error(S.pos(), "fp.number.too.large");
   570             else
   571                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
   572             break;
   573         }
   574         case CHARLITERAL:
   575             t = F.at(pos).Literal(
   576                 TypeTags.CHAR,
   577                 S.stringVal().charAt(0) + 0);
   578             break;
   579         case STRINGLITERAL:
   580             t = F.at(pos).Literal(
   581                 TypeTags.CLASS,
   582                 S.stringVal());
   583             break;
   584         case TRUE: case FALSE:
   585             t = F.at(pos).Literal(
   586                 TypeTags.BOOLEAN,
   587                 (S.token() == TRUE ? 1 : 0));
   588             break;
   589         case NULL:
   590             t = F.at(pos).Literal(
   591                 TypeTags.BOT,
   592                 null);
   593             break;
   594         default:
   595             assert false;
   596         }
   597         if (t == errorTree)
   598             t = F.at(pos).Erroneous();
   599         storeEnd(t, S.endPos());
   600         S.nextToken();
   601         return t;
   602     }
   603 //where
   604         boolean isZero(String s) {
   605             char[] cs = s.toCharArray();
   606             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   607             int i = ((base==16) ? 2 : 0);
   608             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   609             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   610         }
   612         String strval(Name prefix) {
   613             String s = S.stringVal();
   614             return prefix.isEmpty() ? s : prefix + s;
   615         }
   617     /** terms can be either expressions or types.
   618      */
   619     public JCExpression parseExpression() {
   620         return term(EXPR);
   621     }
   623     /**
   624      * parses (optional) type annotations followed by a type. If the
   625      * annotations are present before the type and are not consumed during array
   626      * parsing, this method returns a {@link JCAnnotatedType} consisting of
   627      * these annotations and the underlying type. Otherwise, it returns the
   628      * underlying type.
   629      *
   630      * <p>
   631      *
   632      * Note that this method sets {@code mode} to {@code TYPE} first, before
   633      * parsing annotations.
   634      */
   635     public JCExpression parseType() {
   636         List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
   637         return parseType(annotations);
   638     }
   640     public JCExpression parseType(List<JCTypeAnnotation> annotations) {
   641         JCExpression result = unannotatedType();
   643         if (!annotations.isEmpty())
   644             result = F.AnnotatedType(annotations, result);
   646         return result;
   647     }
   649     public JCExpression unannotatedType() {
   650         return term(TYPE);
   651     }
   653     JCExpression term(int newmode) {
   654         int prevmode = mode;
   655         mode = newmode;
   656         JCExpression t = term();
   657         lastmode = mode;
   658         mode = prevmode;
   659         return t;
   660     }
   662     /**
   663      *  Expression = Expression1 [ExpressionRest]
   664      *  ExpressionRest = [AssignmentOperator Expression1]
   665      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   666      *                       "&=" | "|=" | "^=" |
   667      *                       "%=" | "<<=" | ">>=" | ">>>="
   668      *  Type = Type1
   669      *  TypeNoParams = TypeNoParams1
   670      *  StatementExpression = Expression
   671      *  ConstantExpression = Expression
   672      */
   673     JCExpression term() {
   674         JCExpression t = term1();
   675         if ((mode & EXPR) != 0 &&
   676             S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
   677             return termRest(t);
   678         else
   679             return t;
   680     }
   682     JCExpression termRest(JCExpression t) {
   683         switch (S.token()) {
   684         case EQ: {
   685             int pos = S.pos();
   686             S.nextToken();
   687             mode = EXPR;
   688             JCExpression t1 = term();
   689             return toP(F.at(pos).Assign(t, t1));
   690         }
   691         case PLUSEQ:
   692         case SUBEQ:
   693         case STAREQ:
   694         case SLASHEQ:
   695         case PERCENTEQ:
   696         case AMPEQ:
   697         case BAREQ:
   698         case CARETEQ:
   699         case LTLTEQ:
   700         case GTGTEQ:
   701         case GTGTGTEQ:
   702             int pos = S.pos();
   703             Token token = S.token();
   704             S.nextToken();
   705             mode = EXPR;
   706             JCExpression t1 = term();
   707             return F.at(pos).Assignop(optag(token), t, t1);
   708         default:
   709             return t;
   710         }
   711     }
   713     /** Expression1   = Expression2 [Expression1Rest]
   714      *  Type1         = Type2
   715      *  TypeNoParams1 = TypeNoParams2
   716      */
   717     JCExpression term1() {
   718         JCExpression t = term2();
   719         if ((mode & EXPR) != 0 && S.token() == QUES) {
   720             mode = EXPR;
   721             return term1Rest(t);
   722         } else {
   723             return t;
   724         }
   725     }
   727     /** Expression1Rest = ["?" Expression ":" Expression1]
   728      */
   729     JCExpression term1Rest(JCExpression t) {
   730         if (S.token() == QUES) {
   731             int pos = S.pos();
   732             S.nextToken();
   733             JCExpression t1 = term();
   734             accept(COLON);
   735             JCExpression t2 = term1();
   736             return F.at(pos).Conditional(t, t1, t2);
   737         } else {
   738             return t;
   739         }
   740     }
   742     /** Expression2   = Expression3 [Expression2Rest]
   743      *  Type2         = Type3
   744      *  TypeNoParams2 = TypeNoParams3
   745      */
   746     JCExpression term2() {
   747         JCExpression t = term3();
   748         if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
   749             mode = EXPR;
   750             return term2Rest(t, TreeInfo.orPrec);
   751         } else {
   752             return t;
   753         }
   754     }
   756     /*  Expression2Rest = {infixop Expression3}
   757      *                  | Expression3 instanceof Type
   758      *  infixop         = "||"
   759      *                  | "&&"
   760      *                  | "|"
   761      *                  | "^"
   762      *                  | "&"
   763      *                  | "==" | "!="
   764      *                  | "<" | ">" | "<=" | ">="
   765      *                  | "<<" | ">>" | ">>>"
   766      *                  | "+" | "-"
   767      *                  | "*" | "/" | "%"
   768      */
   769     JCExpression term2Rest(JCExpression t, int minprec) {
   770         List<JCExpression[]> savedOd = odStackSupply.elems;
   771         JCExpression[] odStack = newOdStack();
   772         List<Token[]> savedOp = opStackSupply.elems;
   773         Token[] opStack = newOpStack();
   774         List<int[]> savedPos = posStackSupply.elems;
   775         int[] posStack = newPosStack();
   776         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   777         int top = 0;
   778         odStack[0] = t;
   779         int startPos = S.pos();
   780         Token topOp = ERROR;
   781         int topOpPos = Position.NOPOS;
   782         while (prec(S.token()) >= minprec) {
   783             posStack[top] = topOpPos;
   784             opStack[top] = topOp;
   785             top++;
   786             topOp = S.token();
   787             topOpPos = S.pos();
   788             S.nextToken();
   789             odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3();
   790             while (top > 0 && prec(topOp) >= prec(S.token())) {
   791                 odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1],
   792                                         odStack[top]);
   793                 top--;
   794                 topOp = opStack[top];
   795                 topOpPos = posStack[top];
   796             }
   797         }
   798         assert top == 0;
   799         t = odStack[0];
   801         if (t.getTag() == JCTree.PLUS) {
   802             StringBuffer buf = foldStrings(t);
   803             if (buf != null) {
   804                 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
   805             }
   806         }
   808         odStackSupply.elems = savedOd; // optimization
   809         opStackSupply.elems = savedOp; // optimization
   810         posStackSupply.elems = savedPos; // optimization
   811         return t;
   812     }
   813 //where
   814         /** Construct a binary or type test node.
   815          */
   816         private JCExpression makeOp(int pos,
   817                                     Token topOp,
   818                                     JCExpression od1,
   819                                     JCExpression od2)
   820         {
   821             if (topOp == INSTANCEOF) {
   822                 return F.at(pos).TypeTest(od1, od2);
   823             } else {
   824                 return F.at(pos).Binary(optag(topOp), od1, od2);
   825             }
   826         }
   827         /** If tree is a concatenation of string literals, replace it
   828          *  by a single literal representing the concatenated string.
   829          */
   830         protected StringBuffer foldStrings(JCTree tree) {
   831             List<String> buf = List.nil();
   832             while (true) {
   833                 if (tree.getTag() == JCTree.LITERAL) {
   834                     JCLiteral lit = (JCLiteral) tree;
   835                     if (lit.typetag == TypeTags.CLASS) {
   836                         StringBuffer sbuf =
   837                             new StringBuffer((String)lit.value);
   838                         while (buf.nonEmpty()) {
   839                             sbuf.append(buf.head);
   840                             buf = buf.tail;
   841                         }
   842                         return sbuf;
   843                     }
   844                 } else if (tree.getTag() == JCTree.PLUS) {
   845                     JCBinary op = (JCBinary)tree;
   846                     if (op.rhs.getTag() == JCTree.LITERAL) {
   847                         JCLiteral lit = (JCLiteral) op.rhs;
   848                         if (lit.typetag == TypeTags.CLASS) {
   849                             buf = buf.prepend((String) lit.value);
   850                             tree = op.lhs;
   851                             continue;
   852                         }
   853                     }
   854                 }
   855                 return null;
   856             }
   857         }
   859         /** optimization: To save allocating a new operand/operator stack
   860          *  for every binary operation, we use supplys.
   861          */
   862         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
   863         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
   864         ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
   866         private JCExpression[] newOdStack() {
   867             if (odStackSupply.elems == odStackSupply.last)
   868                 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
   869             JCExpression[] odStack = odStackSupply.elems.head;
   870             odStackSupply.elems = odStackSupply.elems.tail;
   871             return odStack;
   872         }
   874         private Token[] newOpStack() {
   875             if (opStackSupply.elems == opStackSupply.last)
   876                 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
   877             Token[] opStack = opStackSupply.elems.head;
   878             opStackSupply.elems = opStackSupply.elems.tail;
   879             return opStack;
   880         }
   882         private int[] newPosStack() {
   883             if (posStackSupply.elems == posStackSupply.last)
   884                 posStackSupply.append(new int[infixPrecedenceLevels + 1]);
   885             int[] posStack = posStackSupply.elems.head;
   886             posStackSupply.elems = posStackSupply.elems.tail;
   887             return posStack;
   888         }
   890     /** Expression3    = PrefixOp Expression3
   891      *                 | "(" Expr | TypeNoParams ")" Expression3
   892      *                 | Primary {Selector} {PostfixOp}
   893      *  Primary        = "(" Expression ")"
   894      *                 | Literal
   895      *                 | [TypeArguments] THIS [Arguments]
   896      *                 | [TypeArguments] SUPER SuperSuffix
   897      *                 | NEW [TypeArguments] Creator
   898      *                 | [Annotations] Ident { "." Ident }
   899      *                   [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   900      *                   | Arguments
   901      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   902      *                   ]
   903      *                 | BasicType BracketsOpt "." CLASS
   904      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   905      *  PostfixOp      = "++" | "--"
   906      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   907      *                 | BasicType
   908      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   909      *  Selector       = "." [TypeArguments] Ident [Arguments]
   910      *                 | "." THIS
   911      *                 | "." [TypeArguments] SUPER SuperSuffix
   912      *                 | "." NEW [TypeArguments] InnerCreator
   913      *                 | "[" Expression "]"
   914      *  TypeSelector   = "." Ident [TypeArguments]
   915      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   916      */
   917     protected JCExpression term3() {
   918         int pos = S.pos();
   919         JCExpression t;
   920         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   921         switch (S.token()) {
   922         case QUES:
   923             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   924                 mode = TYPE;
   925                 return typeArgument();
   926             } else
   927                 return illegal();
   928         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   929             if (typeArgs == null && (mode & EXPR) != 0) {
   930                 Token token = S.token();
   931                 S.nextToken();
   932                 mode = EXPR;
   933                 if (token == SUB &&
   934                     (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
   935                     S.radix() == 10) {
   936                     mode = EXPR;
   937                     t = literal(names.hyphen);
   938                 } else {
   939                     t = term3();
   940                     return F.at(pos).Unary(unoptag(token), t);
   941                 }
   942             } else return illegal();
   943             break;
   944         case LPAREN:
   945             if (typeArgs == null && (mode & EXPR) != 0) {
   946                 S.nextToken();
   947                 mode = EXPR | TYPE | NOPARAMS;
   948                 t = term3();
   949                 if ((mode & TYPE) != 0 && S.token() == LT) {
   950                     // Could be a cast to a parameterized type
   951                     int op = JCTree.LT;
   952                     int pos1 = S.pos();
   953                     S.nextToken();
   954                     mode &= (EXPR | TYPE);
   955                     mode |= TYPEARG;
   956                     JCExpression t1 = term3();
   957                     if ((mode & TYPE) != 0 &&
   958                         (S.token() == COMMA || S.token() == GT)) {
   959                         mode = TYPE;
   960                         ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   961                         args.append(t1);
   962                         while (S.token() == COMMA) {
   963                             S.nextToken();
   964                             args.append(typeArgument());
   965                         }
   966                         accept(GT);
   967                         t = toP(F.at(pos1).TypeApply(t, args.toList()));
   968                         checkGenerics();
   969                         while (S.token() == DOT) {
   970                             S.nextToken();
   971                             mode = TYPE;
   972                             t = toP(F.at(S.pos()).Select(t, ident()));
   973                             t = typeArgumentsOpt(t);
   974                         }
   975                         t = bracketsOpt(toP(t));
   976                     } else if ((mode & EXPR) != 0) {
   977                         mode = EXPR;
   978                         JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
   979                         t = F.at(pos1).Binary(op, t, e);
   980                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   981                     } else {
   982                         accept(GT);
   983                     }
   984                 }
   985                 else {
   986                     t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   987                 }
   988                 accept(RPAREN);
   989                 lastmode = mode;
   990                 mode = EXPR;
   991                 if ((lastmode & EXPR) == 0) {
   992                     JCExpression t1 = term3();
   993                     return F.at(pos).TypeCast(t, t1);
   994                 } else if ((lastmode & TYPE) != 0) {
   995                     switch (S.token()) {
   996                     /*case PLUSPLUS: case SUBSUB: */
   997                     case BANG: case TILDE:
   998                     case LPAREN: case THIS: case SUPER:
   999                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1000                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1001                     case TRUE: case FALSE: case NULL:
  1002                     case NEW: case IDENTIFIER: case ASSERT: case ENUM:
  1003                     case BYTE: case SHORT: case CHAR: case INT:
  1004                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1005                         JCExpression t1 = term3();
  1006                         return F.at(pos).TypeCast(t, t1);
  1009             } else return illegal();
  1010             t = toP(F.at(pos).Parens(t));
  1011             break;
  1012         case THIS:
  1013             if ((mode & EXPR) != 0) {
  1014                 mode = EXPR;
  1015                 t = to(F.at(pos).Ident(names._this));
  1016                 S.nextToken();
  1017                 if (typeArgs == null)
  1018                     t = argumentsOpt(null, t);
  1019                 else
  1020                     t = arguments(typeArgs, t);
  1021                 typeArgs = null;
  1022             } else return illegal();
  1023             break;
  1024         case SUPER:
  1025             if ((mode & EXPR) != 0) {
  1026                 mode = EXPR;
  1027                 t = to(F.at(pos).Ident(names._super));
  1028                 t = superSuffix(typeArgs, t);
  1029                 typeArgs = null;
  1030             } else return illegal();
  1031             break;
  1032         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1033         case CHARLITERAL: case STRINGLITERAL:
  1034         case TRUE: case FALSE: case NULL:
  1035             if (typeArgs == null && (mode & EXPR) != 0) {
  1036                 mode = EXPR;
  1037                 t = literal(names.empty);
  1038             } else return illegal();
  1039             break;
  1040         case NEW:
  1041             if (typeArgs != null) return illegal();
  1042             if ((mode & EXPR) != 0) {
  1043                 mode = EXPR;
  1044                 S.nextToken();
  1045                 if (S.token() == LT) typeArgs = typeArguments();
  1046                 t = creator(pos, typeArgs);
  1047                 typeArgs = null;
  1048             } else return illegal();
  1049             break;
  1050         case MONKEYS_AT:
  1052             // only annotated targetting class literals or cast types are valid
  1053             List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
  1054             if (typeAnnos.isEmpty()) {
  1055                 // else there would be no '@'
  1056                 throw new AssertionError("type annos is empty");
  1059             JCExpression expr = term3();
  1061             // Type annotations: If term3 just parsed a non-type, expect a
  1062             // class literal (and issue a syntax error if there is no class
  1063             // literal). Otherwise, create a JCAnnotatedType.
  1064             if ((mode & TYPE) == 0) {
  1065                 if (expr.getTag() != JCTree.SELECT)
  1066                     return illegal(typeAnnos.head.pos);
  1067                 JCFieldAccess sel = (JCFieldAccess)expr;
  1068                 if (sel.name != names._class)
  1069                     return illegal();
  1070                 else {
  1071                     sel.selected = F.AnnotatedType(typeAnnos, sel.selected);
  1072                     t = expr;
  1074             } else {
  1075                 // type annotation targeting a cast
  1076                 t = toP(F.at(S.pos()).AnnotatedType(typeAnnos, expr));
  1078             break;
  1079         case IDENTIFIER: case ASSERT: case ENUM:
  1080             if (typeArgs != null) return illegal();
  1081             t = toP(F.at(S.pos()).Ident(ident()));
  1082             loop: while (true) {
  1083                 pos = S.pos();
  1084                 final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
  1086                 // need to report an error later if LBRACKET is for array
  1087                 // index access rather than array creation level
  1088                 if (!annos.isEmpty() && S.token() != LBRACKET && S.token() != ELLIPSIS)
  1089                     return illegal(annos.head.pos);
  1090                 switch (S.token()) {
  1091                 case LBRACKET:
  1092                     S.nextToken();
  1094                     if (S.token() == RBRACKET) {
  1096                         S.nextToken();
  1098                         t = bracketsOpt(t, annos);
  1099                         t = toP(F.at(pos).TypeArray(t));
  1100                         t = bracketsSuffix(t);
  1101                     } else {
  1102                         if ((mode & EXPR) != 0) {
  1103                             mode = EXPR;
  1104                             JCExpression t1 = term();
  1105                             if (!annos.isEmpty()) t = illegal(annos.head.pos);
  1106                             t = to(F.at(pos).Indexed(t, t1));
  1108                         accept(RBRACKET);
  1110                     break loop;
  1111                 case LPAREN:
  1112                     if ((mode & EXPR) != 0) {
  1113                         mode = EXPR;
  1114                         t = arguments(typeArgs, t);
  1115                         typeArgs = null;
  1117                     break loop;
  1118                 case DOT:
  1119                     S.nextToken();
  1120                     int oldmode = mode;
  1121                     mode &= ~NOPARAMS;
  1122                     typeArgs = typeArgumentsOpt(EXPR);
  1123                     mode = oldmode;
  1124                     if ((mode & EXPR) != 0) {
  1125                         switch (S.token()) {
  1126                         case CLASS:
  1127                             if (typeArgs != null) return illegal();
  1128                             mode = EXPR;
  1129                             t = to(F.at(pos).Select(t, names._class));
  1130                             S.nextToken();
  1131                             break loop;
  1132                         case THIS:
  1133                             if (typeArgs != null) return illegal();
  1134                             mode = EXPR;
  1135                             t = to(F.at(pos).Select(t, names._this));
  1136                             S.nextToken();
  1137                             break loop;
  1138                         case SUPER:
  1139                             mode = EXPR;
  1140                             t = to(F.at(pos).Select(t, names._super));
  1141                             t = superSuffix(typeArgs, t);
  1142                             typeArgs = null;
  1143                             break loop;
  1144                         case NEW:
  1145                             if (typeArgs != null) return illegal();
  1146                             mode = EXPR;
  1147                             int pos1 = S.pos();
  1148                             S.nextToken();
  1149                             if (S.token() == LT) typeArgs = typeArguments();
  1150                             t = innerCreator(pos1, typeArgs, t);
  1151                             typeArgs = null;
  1152                             break loop;
  1155                     // typeArgs saved for next loop iteration.
  1156                     t = toP(F.at(pos).Select(t, ident()));
  1157                     break;
  1158                 case ELLIPSIS:
  1159                     if (this.permitTypeAnnotationsPushBack) {
  1160                         this.typeAnnotationsPushedBack = annos;
  1161                     } else if (annos.nonEmpty()) {
  1162                         // Don't return here -- error recovery attempt
  1163                         illegal(annos.head.pos);
  1165                     break loop;
  1166                 default:
  1167                     break loop;
  1170             if (typeArgs != null) illegal();
  1171             t = typeArgumentsOpt(t);
  1172             break;
  1173         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1174         case DOUBLE: case BOOLEAN:
  1175             if (typeArgs != null) illegal();
  1176             t = bracketsSuffix(bracketsOpt(basicType()));
  1177             break;
  1178         case VOID:
  1179             if (typeArgs != null) illegal();
  1180             if ((mode & EXPR) != 0) {
  1181                 S.nextToken();
  1182                 if (S.token() == DOT) {
  1183                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
  1184                     t = bracketsSuffix(ti);
  1185                 } else {
  1186                     return illegal(pos);
  1188             } else {
  1189                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1190                 // a void type (like other primitive types) to the next phase.
  1191                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1192                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
  1193                 S.nextToken();
  1194                 return ti;
  1195                 //return illegal();
  1197             break;
  1198         default:
  1199             return illegal();
  1201         if (typeArgs != null) illegal();
  1202         while (true) {
  1203             int pos1 = S.pos();
  1205             final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
  1207             if (S.token() == LBRACKET) {
  1208                 S.nextToken();
  1210                 if ((mode & TYPE) != 0) {
  1211                     int oldmode = mode;
  1212                     mode = TYPE;
  1213                     if (S.token() == RBRACKET) {
  1214                         S.nextToken();
  1215                         t = bracketsOpt(t, annos);
  1216                         t = toP(F.at(pos1).TypeArray(t));
  1217                         return t;
  1219                     mode = oldmode;
  1221                 if ((mode & EXPR) != 0) {
  1222                     mode = EXPR;
  1223                     JCExpression t1 = term();
  1224                     t = to(F.at(pos1).Indexed(t, t1));
  1226                 accept(RBRACKET);
  1227             } else if (S.token() == DOT) {
  1228                 S.nextToken();
  1229                 typeArgs = typeArgumentsOpt(EXPR);
  1230                 if (S.token() == SUPER && (mode & EXPR) != 0) {
  1231                     mode = EXPR;
  1232                     t = to(F.at(pos1).Select(t, names._super));
  1233                     S.nextToken();
  1234                     t = arguments(typeArgs, t);
  1235                     typeArgs = null;
  1236                 } else if (S.token() == NEW && (mode & EXPR) != 0) {
  1237                     if (typeArgs != null) return illegal();
  1238                     mode = EXPR;
  1239                     int pos2 = S.pos();
  1240                     S.nextToken();
  1241                     if (S.token() == LT) typeArgs = typeArguments();
  1242                     t = innerCreator(pos2, typeArgs, t);
  1243                     typeArgs = null;
  1244                 } else {
  1245                     t = toP(F.at(pos1).Select(t, ident()));
  1246                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1247                     typeArgs = null;
  1249             } else {
  1250                 if (!annos.isEmpty()) {
  1251                     if (permitTypeAnnotationsPushBack)
  1252                         typeAnnotationsPushedBack = annos;
  1253                     else
  1254                         return illegal(annos.head.pos);
  1256                 break;
  1259         while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
  1260             mode = EXPR;
  1261             t = to(F.at(S.pos()).Unary(
  1262                   S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
  1263             S.nextToken();
  1266         return toP(t);
  1269     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1270      */
  1271     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1272         S.nextToken();
  1273         if (S.token() == LPAREN || typeArgs != null) {
  1274             t = arguments(typeArgs, t);
  1275         } else {
  1276             int pos = S.pos();
  1277             accept(DOT);
  1278             typeArgs = (S.token() == LT) ? typeArguments() : null;
  1279             t = toP(F.at(pos).Select(t, ident()));
  1280             t = argumentsOpt(typeArgs, t);
  1282         return t;
  1285     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1286      */
  1287     JCPrimitiveTypeTree basicType() {
  1288         JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
  1289         S.nextToken();
  1290         return t;
  1293     /** ArgumentsOpt = [ Arguments ]
  1294      */
  1295     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1296         if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
  1297             mode = EXPR;
  1298             return arguments(typeArgs, t);
  1299         } else {
  1300             return t;
  1304     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1305      */
  1306     List<JCExpression> arguments() {
  1307         ListBuffer<JCExpression> args = lb();
  1308         if (S.token() == LPAREN) {
  1309             S.nextToken();
  1310             if (S.token() != RPAREN) {
  1311                 args.append(parseExpression());
  1312                 while (S.token() == COMMA) {
  1313                     S.nextToken();
  1314                     args.append(parseExpression());
  1317             accept(RPAREN);
  1318         } else {
  1319             syntaxError(S.pos(), "expected", LPAREN);
  1321         return args.toList();
  1324     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1325         int pos = S.pos();
  1326         List<JCExpression> args = arguments();
  1327         return toP(F.at(pos).Apply(typeArgs, t, args));
  1330     /**  TypeArgumentsOpt = [ TypeArguments ]
  1331      */
  1332     JCExpression typeArgumentsOpt(JCExpression t) {
  1333         if (S.token() == LT &&
  1334             (mode & TYPE) != 0 &&
  1335             (mode & NOPARAMS) == 0) {
  1336             mode = TYPE;
  1337             checkGenerics();
  1338             return typeArguments(t);
  1339         } else {
  1340             return t;
  1343     List<JCExpression> typeArgumentsOpt() {
  1344         return typeArgumentsOpt(TYPE);
  1347     List<JCExpression> typeArgumentsOpt(int useMode) {
  1348         if (S.token() == LT) {
  1349             checkGenerics();
  1350             if ((mode & useMode) == 0 ||
  1351                 (mode & NOPARAMS) != 0) {
  1352                 illegal();
  1354             mode = useMode;
  1355             return typeArguments();
  1357         return null;
  1360     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1361      */
  1362     List<JCExpression> typeArguments() {
  1363         ListBuffer<JCExpression> args = lb();
  1364         if (S.token() == LT) {
  1365             S.nextToken();
  1366             if (S.token() == GT && (mode & DIAMOND) != 0) {
  1367                 checkDiamond();
  1368                 S.nextToken();
  1369                 return List.nil();
  1371             args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1372             while (S.token() == COMMA) {
  1373                 S.nextToken();
  1374                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1376             switch (S.token()) {
  1377             case GTGTGTEQ:
  1378                 S.token(GTGTEQ);
  1379                 break;
  1380             case GTGTEQ:
  1381                 S.token(GTEQ);
  1382                 break;
  1383             case GTEQ:
  1384                 S.token(EQ);
  1385                 break;
  1386             case GTGTGT:
  1387                 S.token(GTGT);
  1388                 break;
  1389             case GTGT:
  1390                 S.token(GT);
  1391                 break;
  1392             default:
  1393                 accept(GT);
  1394                 break;
  1396         } else {
  1397             syntaxError(S.pos(), "expected", LT);
  1399         return args.toList();
  1402     /** TypeArgument = Type
  1403      *               | [Annotations] "?"
  1404      *               | [Annotations] "?" EXTENDS Type {"&" Type}
  1405      *               | [Annotations] "?" SUPER Type
  1406      */
  1407     JCExpression typeArgument() {
  1408         List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
  1409         if (S.token() != QUES) return parseType(annotations);
  1410         int pos = S.pos();
  1411         S.nextToken();
  1412         JCExpression result;
  1413         if (S.token() == EXTENDS) {
  1414             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1415             S.nextToken();
  1416             JCExpression bound = parseType();
  1417             result = F.at(pos).Wildcard(t, bound);
  1418         } else if (S.token() == SUPER) {
  1419             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1420             S.nextToken();
  1421             JCExpression bound = parseType();
  1422             result = F.at(pos).Wildcard(t, bound);
  1423         } else if (S.token() == IDENTIFIER) {
  1424             //error recovery
  1425             reportSyntaxError(S.prevEndPos(), "expected3",
  1426                     GT, EXTENDS, SUPER);
  1427             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1428             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1429             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
  1430             result = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1431         } else {
  1432             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1433             result = toP(F.at(pos).Wildcard(t, null));
  1435         if (!annotations.isEmpty())
  1436             result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
  1437         return result;
  1440     JCTypeApply typeArguments(JCExpression t) {
  1441         int pos = S.pos();
  1442         List<JCExpression> args = typeArguments();
  1443         return toP(F.at(pos).TypeApply(t, args));
  1446     /**
  1447      * BracketsOpt = { [Annotations] "[" "]" }
  1449      * <p>
  1451      * <code>annotations</code> is the list of annotations targeting
  1452      * the expression <code>t</code>.
  1453      */
  1454     private JCExpression bracketsOpt(JCExpression t,
  1455             List<JCTypeAnnotation> annotations) {
  1456         List<JCTypeAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
  1458         if (S.token() == LBRACKET) {
  1459             int pos = S.pos();
  1460             S.nextToken();
  1462             JCExpression orig = t;
  1463             t = bracketsOptCont(t, pos, nextLevelAnnotations);
  1464         } else if (!nextLevelAnnotations.isEmpty()) {
  1465             if (permitTypeAnnotationsPushBack) {
  1466                 this.typeAnnotationsPushedBack = nextLevelAnnotations;
  1467             } else
  1468                 return illegal(nextLevelAnnotations.head.pos);
  1471         int apos = S.pos();
  1472         if (!annotations.isEmpty())
  1473             t = F.at(apos).AnnotatedType(annotations, t);
  1474         return t;
  1477     /** BracketsOpt = {"[" TypeAnnotations "]"}
  1478      */
  1479     private JCExpression bracketsOpt(JCExpression t) {
  1480         return bracketsOpt(t, List.<JCTypeAnnotation>nil());
  1483     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos,
  1484             List<JCTypeAnnotation> annotations) {
  1485         accept(RBRACKET);
  1486         t = bracketsOpt(t, annotations);
  1487         return toP(F.at(pos).TypeArray(t));
  1490     /** BracketsSuffixExpr = "." CLASS
  1491      *  BracketsSuffixType =
  1492      */
  1493     JCExpression bracketsSuffix(JCExpression t) {
  1494         if ((mode & EXPR) != 0 && S.token() == DOT) {
  1495             mode = EXPR;
  1496             int pos = S.pos();
  1497             S.nextToken();
  1498             accept(CLASS);
  1499             if (S.pos() == errorEndPos) {
  1500                 // error recovery
  1501                 Name name = null;
  1502                 if (S.token() == IDENTIFIER) {
  1503                     name = S.name();
  1504                     S.nextToken();
  1505                 } else {
  1506                     name = names.error;
  1508                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1509             } else {
  1510                 t = toP(F.at(pos).Select(t, names._class));
  1512         } else if ((mode & TYPE) != 0) {
  1513             mode = TYPE;
  1514         } else {
  1515             syntaxError(S.pos(), "dot.class.expected");
  1517         return t;
  1520     /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1521      */
  1522     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1524         List<JCTypeAnnotation> newAnnotations = typeAnnotationsOpt();
  1526         switch (S.token()) {
  1527         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1528         case DOUBLE: case BOOLEAN:
  1529             if (typeArgs == null) {
  1530                 if (newAnnotations.isEmpty())
  1531                     return arrayCreatorRest(newpos, basicType());
  1532                 else
  1533                     return arrayCreatorRest(newpos, F.AnnotatedType(newAnnotations, basicType()));
  1535             break;
  1536         default:
  1538         JCExpression t = qualident();
  1539         // handle type annotations for non primitive arrays
  1540         if (!newAnnotations.isEmpty())
  1541             t = F.AnnotatedType(newAnnotations, t);
  1543         int oldmode = mode;
  1544         mode = TYPE | DIAMOND;
  1545         if (S.token() == LT) {
  1546             checkGenerics();
  1547             t = typeArguments(t);
  1549         while (S.token() == DOT) {
  1550             int pos = S.pos();
  1551             S.nextToken();
  1552             t = toP(F.at(pos).Select(t, ident()));
  1553             if (S.token() == LT) {
  1554                 checkGenerics();
  1555                 t = typeArguments(t);
  1558         mode = oldmode;
  1559         if (S.token() == LBRACKET || S.token() == MONKEYS_AT) {
  1560             JCExpression e = arrayCreatorRest(newpos, t);
  1561             if (typeArgs != null) {
  1562                 int pos = newpos;
  1563                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1564                     // note: this should always happen but we should
  1565                     // not rely on this as the parser is continuously
  1566                     // modified to improve error recovery.
  1567                     pos = typeArgs.head.pos;
  1569                 setErrorEndPos(S.prevEndPos());
  1570                 reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
  1571                 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
  1573             return e;
  1574         } else if (S.token() == LPAREN) {
  1575             JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t);
  1576             if (newClass.def != null) {
  1577                 assert newClass.def.mods.annotations.isEmpty();
  1578                 if (newAnnotations.nonEmpty()) {
  1579                     newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos);
  1580                     newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations);
  1583             return newClass;
  1584         } else {
  1585             reportSyntaxError(S.pos(), "expected2",
  1586                                LPAREN, LBRACKET);
  1587             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1588             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1592     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1593      */
  1594     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1595         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
  1596         if (S.token() == LT) {
  1597             int oldmode = mode;
  1598             mode |= DIAMOND;
  1599             checkGenerics();
  1600             t = typeArguments(t);
  1601             mode = oldmode;
  1603         return classCreatorRest(newpos, encl, typeArgs, t);
  1606     /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
  1607      *                         | Expression "]" {[Annotations]  "[" Expression "]"} BracketsOpt )
  1608      */
  1609     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1611         List<JCTypeAnnotation> topAnnos = List.nil();
  1612         if (elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
  1613             JCAnnotatedType atype = (JCAnnotatedType) elemtype;
  1614             topAnnos = atype.annotations;
  1615             elemtype = atype.underlyingType;
  1618         List<JCTypeAnnotation> annos = typeAnnotationsOpt();
  1620         accept(LBRACKET);
  1622         if (S.token() == RBRACKET) {
  1623             accept(RBRACKET);
  1625             elemtype = bracketsOpt(elemtype, annos);
  1627             if (S.token() == LBRACE) {
  1628                 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
  1630                 na.annotations = topAnnos;
  1632                 return na;
  1633             } else {
  1634                 return syntaxError(S.pos(), "array.dimension.missing");
  1636         } else {
  1637             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1639             // maintain array dimension type annotations
  1640             ListBuffer<List<JCTypeAnnotation>> dimAnnotations = ListBuffer.lb();
  1641             dimAnnotations.append(annos);
  1643             dims.append(parseExpression());
  1644             accept(RBRACKET);
  1645             while (S.token() == LBRACKET
  1646                     || (S.token() == MONKEYS_AT)) {
  1647                 List<JCTypeAnnotation> maybeDimAnnos = typeAnnotationsOpt();
  1648                 int pos = S.pos();
  1649                 S.nextToken();
  1650                 if (S.token() == RBRACKET) {
  1651                     elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
  1652                 } else {
  1653                     if (S.token() == RBRACKET) { // no dimension
  1654                         elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
  1655                     } else {
  1656                         dimAnnotations.append(maybeDimAnnos);
  1657                         dims.append(parseExpression());
  1658                         accept(RBRACKET);
  1663             JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1664             na.annotations = topAnnos;
  1665             na.dimAnnotations = dimAnnotations.toList();
  1666             return na;
  1670     /** ClassCreatorRest = Arguments [ClassBody]
  1671      */
  1672     JCNewClass classCreatorRest(int newpos,
  1673                                   JCExpression encl,
  1674                                   List<JCExpression> typeArgs,
  1675                                   JCExpression t)
  1677         List<JCExpression> args = arguments();
  1678         JCClassDecl body = null;
  1679         if (S.token() == LBRACE) {
  1680             int pos = S.pos();
  1681             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1682             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1683             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1685         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1688     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1689      */
  1690     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1691         accept(LBRACE);
  1692         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1693         if (S.token() == COMMA) {
  1694             S.nextToken();
  1695         } else if (S.token() != RBRACE) {
  1696             elems.append(variableInitializer());
  1697             while (S.token() == COMMA) {
  1698                 S.nextToken();
  1699                 if (S.token() == RBRACE) break;
  1700                 elems.append(variableInitializer());
  1703         accept(RBRACE);
  1704         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1707     /** VariableInitializer = ArrayInitializer | Expression
  1708      */
  1709     public JCExpression variableInitializer() {
  1710         return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
  1713     /** ParExpression = "(" Expression ")"
  1714      */
  1715     JCExpression parExpression() {
  1716         accept(LPAREN);
  1717         JCExpression t = parseExpression();
  1718         accept(RPAREN);
  1719         return t;
  1722     /** Block = "{" BlockStatements "}"
  1723      */
  1724     JCBlock block(int pos, long flags) {
  1725         accept(LBRACE);
  1726         List<JCStatement> stats = blockStatements();
  1727         JCBlock t = F.at(pos).Block(flags, stats);
  1728         while (S.token() == CASE || S.token() == DEFAULT) {
  1729             syntaxError("orphaned", S.token());
  1730             switchBlockStatementGroups();
  1732         // the Block node has a field "endpos" for first char of last token, which is
  1733         // usually but not necessarily the last char of the last token.
  1734         t.endpos = S.pos();
  1735         accept(RBRACE);
  1736         return toP(t);
  1739     public JCBlock block() {
  1740         return block(S.pos(), 0);
  1743     /** BlockStatements = { BlockStatement }
  1744      *  BlockStatement  = LocalVariableDeclarationStatement
  1745      *                  | ClassOrInterfaceOrEnumDeclaration
  1746      *                  | [Ident ":"] Statement
  1747      *  LocalVariableDeclarationStatement
  1748      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1749      */
  1750     @SuppressWarnings("fallthrough")
  1751     List<JCStatement> blockStatements() {
  1752 //todo: skip to anchor on error(?)
  1753         int lastErrPos = -1;
  1754         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1755         while (true) {
  1756             int pos = S.pos();
  1757             switch (S.token()) {
  1758             case RBRACE: case CASE: case DEFAULT: case EOF:
  1759                 return stats.toList();
  1760             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1761             case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1762             case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1763                 stats.append(parseStatement());
  1764                 break;
  1765             case MONKEYS_AT:
  1766             case FINAL: {
  1767                 String dc = S.docComment();
  1768                 JCModifiers mods = modifiersOpt();
  1769                 if (S.token() == INTERFACE ||
  1770                     S.token() == CLASS ||
  1771                     allowEnums && S.token() == ENUM) {
  1772                     stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1773                 } else {
  1774                     JCExpression t = parseType();
  1775                     stats.appendList(variableDeclarators(mods, t,
  1776                                                          new ListBuffer<JCStatement>()));
  1777                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1778                     storeEnd(stats.elems.last(), S.endPos());
  1779                     accept(SEMI);
  1781                 break;
  1783             case ABSTRACT: case STRICTFP: {
  1784                 String dc = S.docComment();
  1785                 JCModifiers mods = modifiersOpt();
  1786                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1787                 break;
  1789             case INTERFACE:
  1790             case CLASS:
  1791                 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1792                                                                S.docComment()));
  1793                 break;
  1794             case ENUM:
  1795             case ASSERT:
  1796                 if (allowEnums && S.token() == ENUM) {
  1797                     log.error(S.pos(), "local.enum");
  1798                     stats.
  1799                         append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1800                                                                  S.docComment()));
  1801                     break;
  1802                 } else if (allowAsserts && S.token() == ASSERT) {
  1803                     stats.append(parseStatement());
  1804                     break;
  1806                 /* fall through to default */
  1807             default:
  1808                 Name name = S.name();
  1809                 JCExpression t = term(EXPR | TYPE);
  1810                 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
  1811                     S.nextToken();
  1812                     JCStatement stat = parseStatement();
  1813                     stats.append(F.at(pos).Labelled(name, stat));
  1814                 } else if ((lastmode & TYPE) != 0 &&
  1815                            (S.token() == IDENTIFIER ||
  1816                             S.token() == ASSERT ||
  1817                             S.token() == ENUM)) {
  1818                     pos = S.pos();
  1819                     JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1820                     F.at(pos);
  1821                     stats.appendList(variableDeclarators(mods, t,
  1822                                                          new ListBuffer<JCStatement>()));
  1823                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1824                     storeEnd(stats.elems.last(), S.endPos());
  1825                     accept(SEMI);
  1826                 } else {
  1827                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1828                     stats.append(to(F.at(pos).Exec(checkExprStat(t))));
  1829                     accept(SEMI);
  1833             // error recovery
  1834             if (S.pos() == lastErrPos)
  1835                 return stats.toList();
  1836             if (S.pos() <= errorEndPos) {
  1837                 skip(false, true, true, true);
  1838                 lastErrPos = S.pos();
  1841             // ensure no dangling /** @deprecated */ active
  1842             S.resetDeprecatedFlag();
  1846     /** Statement =
  1847      *       Block
  1848      *     | IF ParExpression Statement [ELSE Statement]
  1849      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1850      *     | FOR "(" FormalParameter : Expression ")" Statement
  1851      *     | WHILE ParExpression Statement
  1852      *     | DO Statement WHILE ParExpression ";"
  1853      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1854      *     | TRY "(" ResourceSpecification ")" Block [Catches] [FinallyPart]
  1855      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1856      *     | SYNCHRONIZED ParExpression Block
  1857      *     | RETURN [Expression] ";"
  1858      *     | THROW Expression ";"
  1859      *     | BREAK [Ident] ";"
  1860      *     | CONTINUE [Ident] ";"
  1861      *     | ASSERT Expression [ ":" Expression ] ";"
  1862      *     | ";"
  1863      *     | ExpressionStatement
  1864      *     | Ident ":" Statement
  1865      */
  1866     @SuppressWarnings("fallthrough")
  1867     public JCStatement parseStatement() {
  1868         int pos = S.pos();
  1869         switch (S.token()) {
  1870         case LBRACE:
  1871             return block();
  1872         case IF: {
  1873             S.nextToken();
  1874             JCExpression cond = parExpression();
  1875             JCStatement thenpart = parseStatement();
  1876             JCStatement elsepart = null;
  1877             if (S.token() == ELSE) {
  1878                 S.nextToken();
  1879                 elsepart = parseStatement();
  1881             return F.at(pos).If(cond, thenpart, elsepart);
  1883         case FOR: {
  1884             S.nextToken();
  1885             accept(LPAREN);
  1886             List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
  1887             if (inits.length() == 1 &&
  1888                 inits.head.getTag() == JCTree.VARDEF &&
  1889                 ((JCVariableDecl) inits.head).init == null &&
  1890                 S.token() == COLON) {
  1891                 checkForeach();
  1892                 JCVariableDecl var = (JCVariableDecl)inits.head;
  1893                 accept(COLON);
  1894                 JCExpression expr = parseExpression();
  1895                 accept(RPAREN);
  1896                 JCStatement body = parseStatement();
  1897                 return F.at(pos).ForeachLoop(var, expr, body);
  1898             } else {
  1899                 accept(SEMI);
  1900                 JCExpression cond = S.token() == SEMI ? null : parseExpression();
  1901                 accept(SEMI);
  1902                 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  1903                 accept(RPAREN);
  1904                 JCStatement body = parseStatement();
  1905                 return F.at(pos).ForLoop(inits, cond, steps, body);
  1908         case WHILE: {
  1909             S.nextToken();
  1910             JCExpression cond = parExpression();
  1911             JCStatement body = parseStatement();
  1912             return F.at(pos).WhileLoop(cond, body);
  1914         case DO: {
  1915             S.nextToken();
  1916             JCStatement body = parseStatement();
  1917             accept(WHILE);
  1918             JCExpression cond = parExpression();
  1919             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  1920             accept(SEMI);
  1921             return t;
  1923         case TRY: {
  1924             S.nextToken();
  1925             List<JCTree> resources = List.<JCTree>nil();
  1926             if (S.token() == LPAREN) {
  1927                 checkAutomaticResourceManagement();
  1928                 S.nextToken();
  1929                 resources = resources();
  1930                 accept(RPAREN);
  1932             JCBlock body = block();
  1933             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  1934             JCBlock finalizer = null;
  1935             if (S.token() == CATCH || S.token() == FINALLY) {
  1936                 while (S.token() == CATCH) catchers.append(catchClause());
  1937                 if (S.token() == FINALLY) {
  1938                     S.nextToken();
  1939                     finalizer = block();
  1941             } else {
  1942                 if (allowTWR) {
  1943                     if (resources.isEmpty())
  1944                         log.error(pos, "try.without.catch.finally.or.resource.decls");
  1945                 } else
  1946                     log.error(pos, "try.without.catch.or.finally");
  1948             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  1950         case SWITCH: {
  1951             S.nextToken();
  1952             JCExpression selector = parExpression();
  1953             accept(LBRACE);
  1954             List<JCCase> cases = switchBlockStatementGroups();
  1955             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  1956             accept(RBRACE);
  1957             return t;
  1959         case SYNCHRONIZED: {
  1960             S.nextToken();
  1961             JCExpression lock = parExpression();
  1962             JCBlock body = block();
  1963             return F.at(pos).Synchronized(lock, body);
  1965         case RETURN: {
  1966             S.nextToken();
  1967             JCExpression result = S.token() == SEMI ? null : parseExpression();
  1968             JCReturn t = to(F.at(pos).Return(result));
  1969             accept(SEMI);
  1970             return t;
  1972         case THROW: {
  1973             S.nextToken();
  1974             JCExpression exc = parseExpression();
  1975             JCThrow t = to(F.at(pos).Throw(exc));
  1976             accept(SEMI);
  1977             return t;
  1979         case BREAK: {
  1980             S.nextToken();
  1981             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1982             JCBreak t = to(F.at(pos).Break(label));
  1983             accept(SEMI);
  1984             return t;
  1986         case CONTINUE: {
  1987             S.nextToken();
  1988             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1989             JCContinue t =  to(F.at(pos).Continue(label));
  1990             accept(SEMI);
  1991             return t;
  1993         case SEMI:
  1994             S.nextToken();
  1995             return toP(F.at(pos).Skip());
  1996         case ELSE:
  1997             return toP(F.Exec(syntaxError("else.without.if")));
  1998         case FINALLY:
  1999             return toP(F.Exec(syntaxError("finally.without.try")));
  2000         case CATCH:
  2001             return toP(F.Exec(syntaxError("catch.without.try")));
  2002         case ASSERT: {
  2003             if (allowAsserts && S.token() == ASSERT) {
  2004                 S.nextToken();
  2005                 JCExpression assertion = parseExpression();
  2006                 JCExpression message = null;
  2007                 if (S.token() == COLON) {
  2008                     S.nextToken();
  2009                     message = parseExpression();
  2011                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2012                 accept(SEMI);
  2013                 return t;
  2015             /* else fall through to default case */
  2017         case ENUM:
  2018         default:
  2019             Name name = S.name();
  2020             JCExpression expr = parseExpression();
  2021             if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
  2022                 S.nextToken();
  2023                 JCStatement stat = parseStatement();
  2024                 return F.at(pos).Labelled(name, stat);
  2025             } else {
  2026                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2027                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2028                 accept(SEMI);
  2029                 return stat;
  2034     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2035      */
  2036     JCCatch catchClause() {
  2037         int pos = S.pos();
  2038         accept(CATCH);
  2039         accept(LPAREN);
  2040         JCModifiers mods = optFinal(Flags.PARAMETER);
  2041         List<JCExpression> catchTypes = catchTypes();
  2042         JCExpression paramType = catchTypes.size() > 1 ?
  2043                 toP(F.at(catchTypes.head.getStartPosition()).TypeDisjoint(catchTypes)) :
  2044                 catchTypes.head;
  2045         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2046         accept(RPAREN);
  2047         JCBlock body = block();
  2048         return F.at(pos).Catch(formal, body);
  2051     List<JCExpression> catchTypes() {
  2052         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  2053         catchTypes.add(parseType());
  2054         while (S.token() == BAR) {
  2055             checkMulticatch();
  2056             S.nextToken();
  2057             catchTypes.add(qualident());
  2059         return catchTypes.toList();
  2062     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2063      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2064      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2065      */
  2066     List<JCCase> switchBlockStatementGroups() {
  2067         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2068         while (true) {
  2069             int pos = S.pos();
  2070             switch (S.token()) {
  2071             case CASE: {
  2072                 S.nextToken();
  2073                 JCExpression pat = parseExpression();
  2074                 accept(COLON);
  2075                 List<JCStatement> stats = blockStatements();
  2076                 JCCase c = F.at(pos).Case(pat, stats);
  2077                 if (stats.isEmpty())
  2078                     storeEnd(c, S.prevEndPos());
  2079                 cases.append(c);
  2080                 break;
  2082             case DEFAULT: {
  2083                 S.nextToken();
  2084                 accept(COLON);
  2085                 List<JCStatement> stats = blockStatements();
  2086                 JCCase c = F.at(pos).Case(null, stats);
  2087                 if (stats.isEmpty())
  2088                     storeEnd(c, S.prevEndPos());
  2089                 cases.append(c);
  2090                 break;
  2092             case RBRACE: case EOF:
  2093                 return cases.toList();
  2094             default:
  2095                 S.nextToken(); // to ensure progress
  2096                 syntaxError(pos, "expected3",
  2097                     CASE, DEFAULT, RBRACE);
  2102     /** MoreStatementExpressions = { COMMA StatementExpression }
  2103      */
  2104     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2105                                                                     JCExpression first,
  2106                                                                     T stats) {
  2107         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2108         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2109         while (S.token() == COMMA) {
  2110             S.nextToken();
  2111             pos = S.pos();
  2112             JCExpression t = parseExpression();
  2113             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2114             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2116         return stats;
  2119     /** ForInit = StatementExpression MoreStatementExpressions
  2120      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2121      */
  2122     List<JCStatement> forInit() {
  2123         ListBuffer<JCStatement> stats = lb();
  2124         int pos = S.pos();
  2125         if (S.token() == FINAL || S.token() == MONKEYS_AT) {
  2126             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2127         } else {
  2128             JCExpression t = term(EXPR | TYPE);
  2129             if ((lastmode & TYPE) != 0 &&
  2130                 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
  2131                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2132             else
  2133                 return moreStatementExpressions(pos, t, stats).toList();
  2137     /** ForUpdate = StatementExpression MoreStatementExpressions
  2138      */
  2139     List<JCExpressionStatement> forUpdate() {
  2140         return moreStatementExpressions(S.pos(),
  2141                                         parseExpression(),
  2142                                         new ListBuffer<JCExpressionStatement>()).toList();
  2145     enum AnnotationKind { DEFAULT_ANNO, TYPE_ANNO };
  2147     /** AnnotationsOpt = { '@' Annotation }
  2148      */
  2149     List<JCAnnotation> annotationsOpt(AnnotationKind kind) {
  2150         if (S.token() != MONKEYS_AT) return List.nil(); // optimization
  2151         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2152         int prevmode = mode;
  2153         while (S.token() == MONKEYS_AT) {
  2154             int pos = S.pos();
  2155             S.nextToken();
  2156             buf.append(annotation(pos, kind));
  2158         lastmode = mode;
  2159         mode = prevmode;
  2160         List<JCAnnotation> annotations = buf.toList();
  2162         if (debugJSR308 && kind == AnnotationKind.TYPE_ANNO)
  2163             System.out.println("TA: parsing " + annotations
  2164                     + " in " + log.currentSourceFile());
  2165         return annotations;
  2168     List<JCTypeAnnotation> typeAnnotationsOpt() {
  2169         List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.TYPE_ANNO);
  2170         return List.convert(JCTypeAnnotation.class, annotations);
  2173     /** ModifiersOpt = { Modifier }
  2174      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2175      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2176      *           | "@" Annotation
  2177      */
  2178     JCModifiers modifiersOpt() {
  2179         return modifiersOpt(null);
  2181     JCModifiers modifiersOpt(JCModifiers partial) {
  2182         long flags;
  2183         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2184         int pos;
  2185         if (partial == null) {
  2186             flags = 0;
  2187             pos = S.pos();
  2188         } else {
  2189             flags = partial.flags;
  2190             annotations.appendList(partial.annotations);
  2191             pos = partial.pos;
  2193         if (S.deprecatedFlag()) {
  2194             flags |= Flags.DEPRECATED;
  2195             S.resetDeprecatedFlag();
  2197         int lastPos = Position.NOPOS;
  2198     loop:
  2199         while (true) {
  2200             long flag;
  2201             switch (S.token()) {
  2202             case PRIVATE     : flag = Flags.PRIVATE; break;
  2203             case PROTECTED   : flag = Flags.PROTECTED; break;
  2204             case PUBLIC      : flag = Flags.PUBLIC; break;
  2205             case STATIC      : flag = Flags.STATIC; break;
  2206             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2207             case FINAL       : flag = Flags.FINAL; break;
  2208             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2209             case NATIVE      : flag = Flags.NATIVE; break;
  2210             case VOLATILE    : flag = Flags.VOLATILE; break;
  2211             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2212             case STRICTFP    : flag = Flags.STRICTFP; break;
  2213             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2214             default: break loop;
  2216             if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
  2217             lastPos = S.pos();
  2218             S.nextToken();
  2219             if (flag == Flags.ANNOTATION) {
  2220                 checkAnnotations();
  2221                 if (S.token() != INTERFACE) {
  2222                     JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO);
  2223                     // if first modifier is an annotation, set pos to annotation's.
  2224                     if (flags == 0 && annotations.isEmpty())
  2225                         pos = ann.pos;
  2226                     annotations.append(ann);
  2227                     lastPos = ann.pos;
  2228                     flag = 0;
  2231             flags |= flag;
  2233         switch (S.token()) {
  2234         case ENUM: flags |= Flags.ENUM; break;
  2235         case INTERFACE: flags |= Flags.INTERFACE; break;
  2236         default: break;
  2239         /* A modifiers tree with no modifier tokens or annotations
  2240          * has no text position. */
  2241         if ((flags & Flags.ModifierFlags) == 0 && annotations.isEmpty())
  2242             pos = Position.NOPOS;
  2244         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2245         if (pos != Position.NOPOS)
  2246             storeEnd(mods, S.prevEndPos());
  2247         return mods;
  2250     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2251      * @param pos position of "@" token
  2252      */
  2253     JCAnnotation annotation(int pos, AnnotationKind kind) {
  2254         // accept(AT); // AT consumed by caller
  2255         checkAnnotations();
  2256         if (kind == AnnotationKind.TYPE_ANNO)
  2257             checkTypeAnnotations();
  2258         JCTree ident = qualident();
  2259         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2260         JCAnnotation ann;
  2261         if (kind == AnnotationKind.DEFAULT_ANNO)
  2262             ann = F.at(pos).Annotation(ident, fieldValues);
  2263         else
  2264             ann = F.at(pos).TypeAnnotation(ident, fieldValues);
  2265         storeEnd(ann, S.prevEndPos());
  2266         return ann;
  2269     List<JCExpression> annotationFieldValuesOpt() {
  2270         return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2273     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2274     List<JCExpression> annotationFieldValues() {
  2275         accept(LPAREN);
  2276         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2277         if (S.token() != RPAREN) {
  2278             buf.append(annotationFieldValue());
  2279             while (S.token() == COMMA) {
  2280                 S.nextToken();
  2281                 buf.append(annotationFieldValue());
  2284         accept(RPAREN);
  2285         return buf.toList();
  2288     /** AnnotationFieldValue    = AnnotationValue
  2289      *                          | Identifier "=" AnnotationValue
  2290      */
  2291     JCExpression annotationFieldValue() {
  2292         if (S.token() == IDENTIFIER) {
  2293             mode = EXPR;
  2294             JCExpression t1 = term1();
  2295             if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
  2296                 int pos = S.pos();
  2297                 accept(EQ);
  2298                 JCExpression v = annotationValue();
  2299                 return toP(F.at(pos).Assign(t1, v));
  2300             } else {
  2301                 return t1;
  2304         return annotationValue();
  2307     /* AnnotationValue          = ConditionalExpression
  2308      *                          | Annotation
  2309      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2310      */
  2311     JCExpression annotationValue() {
  2312         int pos;
  2313         switch (S.token()) {
  2314         case MONKEYS_AT:
  2315             pos = S.pos();
  2316             S.nextToken();
  2317             return annotation(pos, AnnotationKind.DEFAULT_ANNO);
  2318         case LBRACE:
  2319             pos = S.pos();
  2320             accept(LBRACE);
  2321             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2322             if (S.token() != RBRACE) {
  2323                 buf.append(annotationValue());
  2324                 while (S.token() == COMMA) {
  2325                     S.nextToken();
  2326                     if (S.token() == RBRACE) break;
  2327                     buf.append(annotationValue());
  2330             accept(RBRACE);
  2331             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2332         default:
  2333             mode = EXPR;
  2334             return term1();
  2338     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2339      */
  2340     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2341                                                                          JCExpression type,
  2342                                                                          T vdefs)
  2344         return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
  2347     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2348      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2350      *  @param reqInit  Is an initializer always required?
  2351      *  @param dc       The documentation comment for the variable declarations, or null.
  2352      */
  2353     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2354                                                                      JCModifiers mods,
  2355                                                                      JCExpression type,
  2356                                                                      Name name,
  2357                                                                      boolean reqInit,
  2358                                                                      String dc,
  2359                                                                      T vdefs)
  2361         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2362         while (S.token() == COMMA) {
  2363             // All but last of multiple declarators subsume a comma
  2364             storeEnd((JCTree)vdefs.elems.last(), S.endPos());
  2365             S.nextToken();
  2366             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2368         return vdefs;
  2371     /** VariableDeclarator = Ident VariableDeclaratorRest
  2372      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2373      */
  2374     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
  2375         return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
  2378     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2379      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2381      *  @param reqInit  Is an initializer always required?
  2382      *  @param dc       The documentation comment for the variable declarations, or null.
  2383      */
  2384     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2385                                   boolean reqInit, String dc) {
  2386         type = bracketsOpt(type);
  2387         JCExpression init = null;
  2388         if (S.token() == EQ) {
  2389             S.nextToken();
  2390             init = variableInitializer();
  2392         else if (reqInit) syntaxError(S.pos(), "expected", EQ);
  2393         JCVariableDecl result =
  2394             toP(F.at(pos).VarDef(mods, name, type, init));
  2395         attach(result, dc);
  2396         return result;
  2399     /** VariableDeclaratorId = Ident BracketsOpt
  2400      */
  2401     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2402         int pos = S.pos();
  2403         Name name = ident();
  2404         if ((mods.flags & Flags.VARARGS) == 0)
  2405             type = bracketsOpt(type);
  2406         return toP(F.at(pos).VarDef(mods, name, type, null));
  2409     /** Resources = Resource { ";" Resources }
  2410      */
  2411     List<JCTree> resources() {
  2412         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2413         defs.append(resource());
  2414         while (S.token() == SEMI) {
  2415             // All but last of multiple declarators subsume a semicolon
  2416             storeEnd(defs.elems.last(), S.endPos());
  2417             S.nextToken();
  2418             defs.append(resource());
  2420         return defs.toList();
  2423     /** Resource =
  2424      *    VariableModifiers Type VariableDeclaratorId = Expression
  2425      *  | Expression
  2426      */
  2427     JCTree resource() {
  2428         int pos = S.pos();
  2429         if (S.token() == FINAL || S.token() == MONKEYS_AT) {
  2430             return variableDeclaratorRest(pos, optFinal(0), parseType(),
  2431                                           ident(), true, null);
  2432         } else {
  2433             JCExpression t = term(EXPR | TYPE);
  2434             if ((lastmode & TYPE) != 0 && S.token() == IDENTIFIER)
  2435                 return variableDeclaratorRest(pos, toP(F.at(pos).Modifiers(Flags.FINAL)), t,
  2436                                               ident(), true, null);
  2437             else
  2438                 return t;
  2442     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2443      */
  2444     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2445         int pos = S.pos();
  2446         JCExpression pid = null;
  2447         String dc = S.docComment();
  2448         JCModifiers mods = null;
  2449         List<JCAnnotation> packageAnnotations = List.nil();
  2450         if (S.token() == MONKEYS_AT)
  2451             mods = modifiersOpt();
  2453         if (S.token() == PACKAGE) {
  2454             if (mods != null) {
  2455                 checkNoMods(mods.flags);
  2456                 packageAnnotations = mods.annotations;
  2457                 mods = null;
  2459             S.nextToken();
  2460             pid = qualident();
  2461             accept(SEMI);
  2463         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2464         boolean checkForImports = true;
  2465         while (S.token() != EOF) {
  2466             if (S.pos() <= errorEndPos) {
  2467                 // error recovery
  2468                 skip(checkForImports, false, false, false);
  2469                 if (S.token() == EOF)
  2470                     break;
  2472             if (checkForImports && mods == null && S.token() == IMPORT) {
  2473                 defs.append(importDeclaration());
  2474             } else {
  2475                 JCTree def = typeDeclaration(mods);
  2476                 if (def instanceof JCExpressionStatement)
  2477                     def = ((JCExpressionStatement)def).expr;
  2478                 defs.append(def);
  2479                 if (def instanceof JCClassDecl)
  2480                     checkForImports = false;
  2481                 mods = null;
  2484         JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
  2485         attach(toplevel, dc);
  2486         if (defs.elems.isEmpty())
  2487             storeEnd(toplevel, S.prevEndPos());
  2488         if (keepDocComments)
  2489             toplevel.docComments = docComments;
  2490         if (keepLineMap)
  2491             toplevel.lineMap = S.getLineMap();
  2492         return toplevel;
  2495     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2496      */
  2497     JCTree importDeclaration() {
  2498         int pos = S.pos();
  2499         S.nextToken();
  2500         boolean importStatic = false;
  2501         if (S.token() == STATIC) {
  2502             checkStaticImports();
  2503             importStatic = true;
  2504             S.nextToken();
  2506         JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
  2507         do {
  2508             int pos1 = S.pos();
  2509             accept(DOT);
  2510             if (S.token() == STAR) {
  2511                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2512                 S.nextToken();
  2513                 break;
  2514             } else {
  2515                 pid = toP(F.at(pos1).Select(pid, ident()));
  2517         } while (S.token() == DOT);
  2518         accept(SEMI);
  2519         return toP(F.at(pos).Import(pid, importStatic));
  2522     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2523      *                  | ";"
  2524      */
  2525     JCTree typeDeclaration(JCModifiers mods) {
  2526         int pos = S.pos();
  2527         if (mods == null && S.token() == SEMI) {
  2528             S.nextToken();
  2529             return toP(F.at(pos).Skip());
  2530         } else {
  2531             String dc = S.docComment();
  2532             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
  2536     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2537      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2538      *  @param mods     Any modifiers starting the class or interface declaration
  2539      *  @param dc       The documentation comment for the class, or null.
  2540      */
  2541     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
  2542         if (S.token() == CLASS) {
  2543             return classDeclaration(mods, dc);
  2544         } else if (S.token() == INTERFACE) {
  2545             return interfaceDeclaration(mods, dc);
  2546         } else if (allowEnums) {
  2547             if (S.token() == ENUM) {
  2548                 return enumDeclaration(mods, dc);
  2549             } else {
  2550                 int pos = S.pos();
  2551                 List<JCTree> errs;
  2552                 if (S.token() == IDENTIFIER) {
  2553                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2554                     setErrorEndPos(S.pos());
  2555                 } else {
  2556                     errs = List.<JCTree>of(mods);
  2558                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2559                                               CLASS, INTERFACE, ENUM)));
  2561         } else {
  2562             if (S.token() == ENUM) {
  2563                 log.error(S.pos(), "enums.not.supported.in.source", source.name);
  2564                 allowEnums = true;
  2565                 return enumDeclaration(mods, dc);
  2567             int pos = S.pos();
  2568             List<JCTree> errs;
  2569             if (S.token() == IDENTIFIER) {
  2570                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2571                 setErrorEndPos(S.pos());
  2572             } else {
  2573                 errs = List.<JCTree>of(mods);
  2575             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2576                                           CLASS, INTERFACE)));
  2580     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2581      *                     [IMPLEMENTS TypeList] ClassBody
  2582      *  @param mods    The modifiers starting the class declaration
  2583      *  @param dc       The documentation comment for the class, or null.
  2584      */
  2585     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
  2586         int pos = S.pos();
  2587         accept(CLASS);
  2588         Name name = ident();
  2590         List<JCTypeParameter> typarams = typeParametersOpt();
  2592         JCTree extending = null;
  2593         if (S.token() == EXTENDS) {
  2594             S.nextToken();
  2595             extending = parseType();
  2597         List<JCExpression> implementing = List.nil();
  2598         if (S.token() == IMPLEMENTS) {
  2599             S.nextToken();
  2600             implementing = typeList();
  2602         List<JCTree> defs = classOrInterfaceBody(name, false);
  2603         JCClassDecl result = toP(F.at(pos).ClassDef(
  2604             mods, name, typarams, extending, implementing, defs));
  2605         attach(result, dc);
  2606         return result;
  2609     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2610      *                         [EXTENDS TypeList] InterfaceBody
  2611      *  @param mods    The modifiers starting the interface declaration
  2612      *  @param dc       The documentation comment for the interface, or null.
  2613      */
  2614     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
  2615         int pos = S.pos();
  2616         accept(INTERFACE);
  2617         Name name = ident();
  2619         List<JCTypeParameter> typarams = typeParametersOpt();
  2621         List<JCExpression> extending = List.nil();
  2622         if (S.token() == EXTENDS) {
  2623             S.nextToken();
  2624             extending = typeList();
  2626         List<JCTree> defs = classOrInterfaceBody(name, true);
  2627         JCClassDecl result = toP(F.at(pos).ClassDef(
  2628             mods, name, typarams, null, extending, defs));
  2629         attach(result, dc);
  2630         return result;
  2633     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2634      *  @param mods    The modifiers starting the enum declaration
  2635      *  @param dc       The documentation comment for the enum, or null.
  2636      */
  2637     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
  2638         int pos = S.pos();
  2639         accept(ENUM);
  2640         Name name = ident();
  2642         List<JCExpression> implementing = List.nil();
  2643         if (S.token() == IMPLEMENTS) {
  2644             S.nextToken();
  2645             implementing = typeList();
  2648         List<JCTree> defs = enumBody(name);
  2649         mods.flags |= Flags.ENUM;
  2650         JCClassDecl result = toP(F.at(pos).
  2651             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2652                 null, implementing, defs));
  2653         attach(result, dc);
  2654         return result;
  2657     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2658      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2659      */
  2660     List<JCTree> enumBody(Name enumName) {
  2661         accept(LBRACE);
  2662         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2663         if (S.token() == COMMA) {
  2664             S.nextToken();
  2665         } else if (S.token() != RBRACE && S.token() != SEMI) {
  2666             defs.append(enumeratorDeclaration(enumName));
  2667             while (S.token() == COMMA) {
  2668                 S.nextToken();
  2669                 if (S.token() == RBRACE || S.token() == SEMI) break;
  2670                 defs.append(enumeratorDeclaration(enumName));
  2672             if (S.token() != SEMI && S.token() != RBRACE) {
  2673                 defs.append(syntaxError(S.pos(), "expected3",
  2674                                 COMMA, RBRACE, SEMI));
  2675                 S.nextToken();
  2678         if (S.token() == SEMI) {
  2679             S.nextToken();
  2680             while (S.token() != RBRACE && S.token() != EOF) {
  2681                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2682                                                                 false));
  2683                 if (S.pos() <= errorEndPos) {
  2684                     // error recovery
  2685                    skip(false, true, true, false);
  2689         accept(RBRACE);
  2690         return defs.toList();
  2693     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2694      */
  2695     JCTree enumeratorDeclaration(Name enumName) {
  2696         String dc = S.docComment();
  2697         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2698         if (S.deprecatedFlag()) {
  2699             flags |= Flags.DEPRECATED;
  2700             S.resetDeprecatedFlag();
  2702         int pos = S.pos();
  2703         List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
  2704         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2705         List<JCExpression> typeArgs = typeArgumentsOpt();
  2706         int identPos = S.pos();
  2707         Name name = ident();
  2708         int createPos = S.pos();
  2709         List<JCExpression> args = (S.token() == LPAREN)
  2710             ? arguments() : List.<JCExpression>nil();
  2711         JCClassDecl body = null;
  2712         if (S.token() == LBRACE) {
  2713             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2714             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2715             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2717         if (args.isEmpty() && body == null)
  2718             createPos = identPos;
  2719         JCIdent ident = F.at(identPos).Ident(enumName);
  2720         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2721         if (createPos != identPos)
  2722             storeEnd(create, S.prevEndPos());
  2723         ident = F.at(identPos).Ident(enumName);
  2724         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2725         attach(result, dc);
  2726         return result;
  2729     /** TypeList = Type {"," Type}
  2730      */
  2731     List<JCExpression> typeList() {
  2732         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2733         ts.append(parseType());
  2734         while (S.token() == COMMA) {
  2735             S.nextToken();
  2736             ts.append(parseType());
  2738         return ts.toList();
  2741     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2742      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2743      */
  2744     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2745         accept(LBRACE);
  2746         if (S.pos() <= errorEndPos) {
  2747             // error recovery
  2748             skip(false, true, false, false);
  2749             if (S.token() == LBRACE)
  2750                 S.nextToken();
  2752         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2753         while (S.token() != RBRACE && S.token() != EOF) {
  2754             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2755             if (S.pos() <= errorEndPos) {
  2756                // error recovery
  2757                skip(false, true, true, false);
  2760         accept(RBRACE);
  2761         return defs.toList();
  2764     /** ClassBodyDeclaration =
  2765      *      ";"
  2766      *    | [STATIC] Block
  2767      *    | ModifiersOpt
  2768      *      ( Type Ident
  2769      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2770      *      | VOID Ident MethodDeclaratorRest
  2771      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2772      *      | Ident ConstructorDeclaratorRest
  2773      *      | TypeParameters Ident ConstructorDeclaratorRest
  2774      *      | ClassOrInterfaceOrEnumDeclaration
  2775      *      )
  2776      *  InterfaceBodyDeclaration =
  2777      *      ";"
  2778      *    | ModifiersOpt Type Ident
  2779      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2780      */
  2781     List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2782         if (S.token() == SEMI) {
  2783             S.nextToken();
  2784             return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
  2785         } else {
  2786             String dc = S.docComment();
  2787             int pos = S.pos();
  2788             JCModifiers mods = modifiersOpt();
  2789             if (S.token() == CLASS ||
  2790                 S.token() == INTERFACE ||
  2791                 allowEnums && S.token() == ENUM) {
  2792                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2793             } else if (S.token() == LBRACE && !isInterface &&
  2794                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2795                        mods.annotations.isEmpty()) {
  2796                 return List.<JCTree>of(block(pos, mods.flags));
  2797             } else {
  2798                 pos = S.pos();
  2799                 List<JCTypeParameter> typarams = typeParametersOpt();
  2800                 List<JCAnnotation> annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
  2802                 Name name = S.name();
  2803                 pos = S.pos();
  2804                 JCExpression type;
  2805                 boolean isVoid = S.token() == VOID;
  2806                 if (isVoid) {
  2807                     if (annosAfterParams.nonEmpty())
  2808                         illegal(annosAfterParams.head.pos);
  2809                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  2810                     S.nextToken();
  2811                 } else {
  2812                     if (annosAfterParams.nonEmpty()) {
  2813                         mods.annotations = mods.annotations.appendList(annosAfterParams);
  2814                         if (mods.pos == Position.NOPOS)
  2815                             mods.pos = mods.annotations.head.pos;
  2817                     // method returns types are un-annotated types
  2818                     type = unannotatedType();
  2820                 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
  2821                     if (isInterface || name != className)
  2822                         log.error(pos, "invalid.meth.decl.ret.type.req");
  2823                     return List.of(methodDeclaratorRest(
  2824                         pos, mods, null, names.init, typarams,
  2825                         isInterface, true, dc));
  2826                 } else {
  2827                     pos = S.pos();
  2828                     name = ident();
  2829                     if (S.token() == LPAREN) {
  2830                         return List.of(methodDeclaratorRest(
  2831                             pos, mods, type, name, typarams,
  2832                             isInterface, isVoid, dc));
  2833                     } else if (!isVoid && typarams.isEmpty()) {
  2834                         List<JCTree> defs =
  2835                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2836                                                     new ListBuffer<JCTree>()).toList();
  2837                         storeEnd(defs.last(), S.endPos());
  2838                         accept(SEMI);
  2839                         return defs;
  2840                     } else {
  2841                         pos = S.pos();
  2842                         List<JCTree> err = isVoid
  2843                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2844                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2845                             : null;
  2846                         return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
  2853     /** MethodDeclaratorRest =
  2854      *      FormalParameters BracketsOpt [Annotations] [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2855      *  VoidMethodDeclaratorRest =
  2856      *      FormalParameters [Annotations] [Throws TypeList] ( MethodBody | ";")
  2857      *  InterfaceMethodDeclaratorRest =
  2858      *      FormalParameters BracketsOpt [Annotations] [THROWS TypeList] ";"
  2859      *  VoidInterfaceMethodDeclaratorRest =
  2860      *      FormalParameters [Annotations] [THROWS TypeList] ";"
  2861      *  ConstructorDeclaratorRest =
  2862      *      "(" FormalParameterListOpt ")" [Annotations] [THROWS TypeList] MethodBody
  2863      */
  2864     JCTree methodDeclaratorRest(int pos,
  2865                               JCModifiers mods,
  2866                               JCExpression type,
  2867                               Name name,
  2868                               List<JCTypeParameter> typarams,
  2869                               boolean isInterface, boolean isVoid,
  2870                               String dc) {
  2871         List<JCVariableDecl> params = formalParameters();
  2873         List<JCTypeAnnotation> receiverAnnotations;
  2874         if (!isVoid) {
  2875             // need to distinguish between receiver anno and array anno
  2876             // look at typeAnnotationsPushedBack comment
  2877             this.permitTypeAnnotationsPushBack = true;
  2878             type = methodReturnArrayRest(type);
  2879             this.permitTypeAnnotationsPushBack = false;
  2880             if (typeAnnotationsPushedBack == null)
  2881                 receiverAnnotations = List.nil();
  2882             else
  2883                 receiverAnnotations = typeAnnotationsPushedBack;
  2884             typeAnnotationsPushedBack = null;
  2885         } else
  2886             receiverAnnotations = typeAnnotationsOpt();
  2888         List<JCExpression> thrown = List.nil();
  2889         if (S.token() == THROWS) {
  2890             S.nextToken();
  2891             thrown = qualidentList();
  2893         JCBlock body = null;
  2894         JCExpression defaultValue;
  2895         if (S.token() == LBRACE) {
  2896             body = block();
  2897             defaultValue = null;
  2898         } else {
  2899             if (S.token() == DEFAULT) {
  2900                 accept(DEFAULT);
  2901                 defaultValue = annotationValue();
  2902             } else {
  2903                 defaultValue = null;
  2905             accept(SEMI);
  2906             if (S.pos() <= errorEndPos) {
  2907                 // error recovery
  2908                 skip(false, true, false, false);
  2909                 if (S.token() == LBRACE) {
  2910                     body = block();
  2915         JCMethodDecl result =
  2916             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2917                                     params, receiverAnnotations, thrown,
  2918                                     body, defaultValue));
  2919         attach(result, dc);
  2920         return result;
  2923     /** Parses the array levels after the format parameters list, and append
  2924      * them to the return type, while preseving the order of type annotations
  2925      */
  2926     private JCExpression methodReturnArrayRest(JCExpression type) {
  2927         if (type.getTag() != JCTree.TYPEARRAY)
  2928             return bracketsOpt(type);
  2930         JCArrayTypeTree baseArray = (JCArrayTypeTree)type;
  2931         while (TreeInfo.typeIn(baseArray.elemtype) instanceof JCArrayTypeTree)
  2932             baseArray = (JCArrayTypeTree)TreeInfo.typeIn(baseArray.elemtype);
  2934         if (baseArray.elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
  2935             JCAnnotatedType at = (JCAnnotatedType)baseArray.elemtype;
  2936             at.underlyingType = bracketsOpt(at.underlyingType);
  2937         } else {
  2938             baseArray.elemtype = bracketsOpt(baseArray.elemtype);
  2941         return type;
  2944     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
  2945      */
  2946     List<JCExpression> qualidentList() {
  2947         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2949         List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
  2950         if (!typeAnnos.isEmpty())
  2951             ts.append(F.AnnotatedType(typeAnnos, qualident()));
  2952         else
  2953             ts.append(qualident());
  2954         while (S.token() == COMMA) {
  2955             S.nextToken();
  2957             typeAnnos = typeAnnotationsOpt();
  2958             if (!typeAnnos.isEmpty())
  2959                 ts.append(F.AnnotatedType(typeAnnos, qualident()));
  2960             else
  2961                 ts.append(qualident());
  2963         return ts.toList();
  2966     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  2967      */
  2968     List<JCTypeParameter> typeParametersOpt() {
  2969         if (S.token() == LT) {
  2970             checkGenerics();
  2971             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  2972             S.nextToken();
  2973             typarams.append(typeParameter());
  2974             while (S.token() == COMMA) {
  2975                 S.nextToken();
  2976                 typarams.append(typeParameter());
  2978             accept(GT);
  2979             return typarams.toList();
  2980         } else {
  2981             return List.nil();
  2985     /** TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
  2986      *  TypeParameterBound = EXTENDS Type {"&" Type}
  2987      *  TypeVariable = Ident
  2988      */
  2989     JCTypeParameter typeParameter() {
  2990         int pos = S.pos();
  2991         List<JCTypeAnnotation> annos = typeAnnotationsOpt();
  2992         Name name = ident();
  2993         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  2994         if (S.token() == EXTENDS) {
  2995             S.nextToken();
  2996             bounds.append(parseType());
  2997             while (S.token() == AMP) {
  2998                 S.nextToken();
  2999                 bounds.append(parseType());
  3002         return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
  3005     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3006      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3007      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3008      */
  3009     List<JCVariableDecl> formalParameters() {
  3010         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3011         JCVariableDecl lastParam = null;
  3012         accept(LPAREN);
  3013         if (S.token() != RPAREN) {
  3014             params.append(lastParam = formalParameter());
  3015             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
  3016                 S.nextToken();
  3017                 params.append(lastParam = formalParameter());
  3020         accept(RPAREN);
  3021         return params.toList();
  3024     JCModifiers optFinal(long flags) {
  3025         JCModifiers mods = modifiersOpt();
  3026         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3027         mods.flags |= flags;
  3028         return mods;
  3031     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3032      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3033      */
  3034     JCVariableDecl formalParameter() {
  3035         JCModifiers mods = optFinal(Flags.PARAMETER);
  3036         // need to distinguish between vararg annos and array annos
  3037         // look at typeAnnotaitonsPushedBack comment
  3038         this.permitTypeAnnotationsPushBack = true;
  3039         JCExpression type = parseType();
  3040         this.permitTypeAnnotationsPushBack = false;
  3042         if (S.token() == ELLIPSIS) {
  3043             List<JCTypeAnnotation> varargsAnnos = typeAnnotationsPushedBack;
  3044             typeAnnotationsPushedBack = null;
  3045             checkVarargs();
  3046             mods.flags |= Flags.VARARGS;
  3047             // insert var arg type annotations
  3048             if (varargsAnnos != null && varargsAnnos.nonEmpty())
  3049                 type = F.at(S.pos()).AnnotatedType(varargsAnnos, type);
  3050             type = to(F.at(S.pos()).TypeArray(type));
  3052             S.nextToken();
  3053         } else {
  3054             // if not a var arg, then typeAnnotationsPushedBack should be null
  3055             if (typeAnnotationsPushedBack != null
  3056                     && !typeAnnotationsPushedBack.isEmpty()) {
  3057                 reportSyntaxError(typeAnnotationsPushedBack.head.pos,
  3058                         "illegal.start.of.type");
  3060             typeAnnotationsPushedBack = null;
  3062         return variableDeclaratorId(mods, type);
  3065 /* ---------- auxiliary methods -------------- */
  3067     /** Check that given tree is a legal expression statement.
  3068      */
  3069     protected JCExpression checkExprStat(JCExpression t) {
  3070         switch(t.getTag()) {
  3071         case JCTree.PREINC: case JCTree.PREDEC:
  3072         case JCTree.POSTINC: case JCTree.POSTDEC:
  3073         case JCTree.ASSIGN:
  3074         case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
  3075         case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
  3076         case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
  3077         case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
  3078         case JCTree.APPLY: case JCTree.NEWCLASS:
  3079         case JCTree.ERRONEOUS:
  3080             return t;
  3081         default:
  3082             log.error(t.pos, "not.stmt");
  3083             return F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3087     /** Return precedence of operator represented by token,
  3088      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3089      */
  3090     static int prec(Token token) {
  3091         int oc = optag(token);
  3092         return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
  3095     /**
  3096      * Return the lesser of two positions, making allowance for either one
  3097      * being unset.
  3098      */
  3099     static int earlier(int pos1, int pos2) {
  3100         if (pos1 == Position.NOPOS)
  3101             return pos2;
  3102         if (pos2 == Position.NOPOS)
  3103             return pos1;
  3104         return (pos1 < pos2 ? pos1 : pos2);
  3107     /** Return operation tag of binary operator represented by token,
  3108      *  -1 if token is not a binary operator.
  3109      */
  3110     static int optag(Token token) {
  3111         switch (token) {
  3112         case BARBAR:
  3113             return JCTree.OR;
  3114         case AMPAMP:
  3115             return JCTree.AND;
  3116         case BAR:
  3117             return JCTree.BITOR;
  3118         case BAREQ:
  3119             return JCTree.BITOR_ASG;
  3120         case CARET:
  3121             return JCTree.BITXOR;
  3122         case CARETEQ:
  3123             return JCTree.BITXOR_ASG;
  3124         case AMP:
  3125             return JCTree.BITAND;
  3126         case AMPEQ:
  3127             return JCTree.BITAND_ASG;
  3128         case EQEQ:
  3129             return JCTree.EQ;
  3130         case BANGEQ:
  3131             return JCTree.NE;
  3132         case LT:
  3133             return JCTree.LT;
  3134         case GT:
  3135             return JCTree.GT;
  3136         case LTEQ:
  3137             return JCTree.LE;
  3138         case GTEQ:
  3139             return JCTree.GE;
  3140         case LTLT:
  3141             return JCTree.SL;
  3142         case LTLTEQ:
  3143             return JCTree.SL_ASG;
  3144         case GTGT:
  3145             return JCTree.SR;
  3146         case GTGTEQ:
  3147             return JCTree.SR_ASG;
  3148         case GTGTGT:
  3149             return JCTree.USR;
  3150         case GTGTGTEQ:
  3151             return JCTree.USR_ASG;
  3152         case PLUS:
  3153             return JCTree.PLUS;
  3154         case PLUSEQ:
  3155             return JCTree.PLUS_ASG;
  3156         case SUB:
  3157             return JCTree.MINUS;
  3158         case SUBEQ:
  3159             return JCTree.MINUS_ASG;
  3160         case STAR:
  3161             return JCTree.MUL;
  3162         case STAREQ:
  3163             return JCTree.MUL_ASG;
  3164         case SLASH:
  3165             return JCTree.DIV;
  3166         case SLASHEQ:
  3167             return JCTree.DIV_ASG;
  3168         case PERCENT:
  3169             return JCTree.MOD;
  3170         case PERCENTEQ:
  3171             return JCTree.MOD_ASG;
  3172         case INSTANCEOF:
  3173             return JCTree.TYPETEST;
  3174         default:
  3175             return -1;
  3179     /** Return operation tag of unary operator represented by token,
  3180      *  -1 if token is not a binary operator.
  3181      */
  3182     static int unoptag(Token token) {
  3183         switch (token) {
  3184         case PLUS:
  3185             return JCTree.POS;
  3186         case SUB:
  3187             return JCTree.NEG;
  3188         case BANG:
  3189             return JCTree.NOT;
  3190         case TILDE:
  3191             return JCTree.COMPL;
  3192         case PLUSPLUS:
  3193             return JCTree.PREINC;
  3194         case SUBSUB:
  3195             return JCTree.PREDEC;
  3196         default:
  3197             return -1;
  3201     /** Return type tag of basic type represented by token,
  3202      *  -1 if token is not a basic type identifier.
  3203      */
  3204     static int typetag(Token token) {
  3205         switch (token) {
  3206         case BYTE:
  3207             return TypeTags.BYTE;
  3208         case CHAR:
  3209             return TypeTags.CHAR;
  3210         case SHORT:
  3211             return TypeTags.SHORT;
  3212         case INT:
  3213             return TypeTags.INT;
  3214         case LONG:
  3215             return TypeTags.LONG;
  3216         case FLOAT:
  3217             return TypeTags.FLOAT;
  3218         case DOUBLE:
  3219             return TypeTags.DOUBLE;
  3220         case BOOLEAN:
  3221             return TypeTags.BOOLEAN;
  3222         default:
  3223             return -1;
  3227     void checkGenerics() {
  3228         if (!allowGenerics) {
  3229             log.error(S.pos(), "generics.not.supported.in.source", source.name);
  3230             allowGenerics = true;
  3233     void checkVarargs() {
  3234         if (!allowVarargs) {
  3235             log.error(S.pos(), "varargs.not.supported.in.source", source.name);
  3236             allowVarargs = true;
  3239     void checkForeach() {
  3240         if (!allowForeach) {
  3241             log.error(S.pos(), "foreach.not.supported.in.source", source.name);
  3242             allowForeach = true;
  3245     void checkStaticImports() {
  3246         if (!allowStaticImport) {
  3247             log.error(S.pos(), "static.import.not.supported.in.source", source.name);
  3248             allowStaticImport = true;
  3251     void checkAnnotations() {
  3252         if (!allowAnnotations) {
  3253             log.error(S.pos(), "annotations.not.supported.in.source", source.name);
  3254             allowAnnotations = true;
  3257     void checkTypeAnnotations() {
  3258         if (!allowTypeAnnotations) {
  3259             log.error(S.pos(), "type.annotations.not.supported.in.source", source.name);
  3260             allowTypeAnnotations = true;
  3263     void checkDiamond() {
  3264         if (!allowDiamond) {
  3265             log.error(S.pos(), "diamond.not.supported.in.source", source.name);
  3266             allowDiamond = true;
  3269     void checkMulticatch() {
  3270         if (!allowMulticatch) {
  3271             log.error(S.pos(), "multicatch.not.supported.in.source", source.name);
  3272             allowMulticatch = true;
  3275     void checkAutomaticResourceManagement() {
  3276         if (!allowTWR) {
  3277             log.error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name);
  3278             allowTWR = true;

mercurial