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

Wed, 14 Apr 2010 12:31:55 +0100

author
mcimadamore
date
Wed, 14 Apr 2010 12:31:55 +0100
changeset 537
9d9d08922405
parent 536
396b117c1743
child 550
a6f2911a7c55
permissions
-rw-r--r--

6939620: Switch to 'complex' diamond inference scheme
Summary: Implement new inference scheme for diamond operator that takes into account type of actual arguments supplied to constructor
Reviewed-by: jjg, darcy

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

mercurial