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

Wed, 14 Apr 2010 12:23:29 +0100

author
mcimadamore
date
Wed, 14 Apr 2010 12:23:29 +0100
changeset 536
396b117c1743
parent 516
7f5db2e8b423
child 537
9d9d08922405
permissions
-rw-r--r--

6939618: Revert 'simple' diamond implementation
Summary: backout changeset for 6840638
Reviewed-by: jjg

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

mercurial