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

Thu, 06 Oct 2011 18:39:31 +0100

author
mcimadamore
date
Thu, 06 Oct 2011 18:39:31 +0100
changeset 1103
47147081d5b4
parent 1074
04f983e3e825
child 1113
d346ab55031b
permissions
-rw-r--r--

7090499: missing rawtypes warnings in anonymous inner class
Summary: javac does not detect raw types inside anonymous inner classes
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.javac.parser;
    28 import java.util.*;
    30 import com.sun.tools.javac.code.*;
    31 import com.sun.tools.javac.tree.*;
    32 import com.sun.tools.javac.tree.JCTree.*;
    33 import com.sun.tools.javac.util.*;
    34 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
    35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    36 import com.sun.tools.javac.util.List;
    38 import static com.sun.tools.javac.util.ListBuffer.lb;
    39 import static com.sun.tools.javac.parser.Token.*;
    41 /** The parser maps a token sequence into an abstract syntax
    42  *  tree. It operates by recursive descent, with code derived
    43  *  systematically from an LL(1) grammar. For efficiency reasons, an
    44  *  operator precedence scheme is used for parsing binary operation
    45  *  expressions.
    46  *
    47  *  <p><b>This is NOT part of any supported API.
    48  *  If you write code that depends on this, you do so at your own risk.
    49  *  This code and its internal interfaces are subject to change or
    50  *  deletion without notice.</b>
    51  */
    52 public class JavacParser implements Parser {
    54     /** The number of precedence levels of infix operators.
    55      */
    56     private static final int infixPrecedenceLevels = 10;
    58     /** The scanner used for lexical analysis.
    59      */
    60     protected Lexer S;
    62     /** The factory to be used for abstract syntax tree construction.
    63      */
    64     protected TreeMaker F;
    66     /** The log to be used for error diagnostics.
    67      */
    68     private Log log;
    70     /** The keyword table. */
    71     private Keywords keywords;
    73     /** The Source language setting. */
    74     private Source source;
    76     /** The name table. */
    77     private Names names;
    79     /** Construct a parser from a given scanner, tree factory and log.
    80      */
    81     protected JavacParser(ParserFactory fac,
    82                      Lexer S,
    83                      boolean keepDocComments,
    84                      boolean keepLineMap) {
    85         this.S = S;
    86         S.nextToken(); // prime the pump
    87         this.F = fac.F;
    88         this.log = fac.log;
    89         this.names = fac.names;
    90         this.keywords = fac.keywords;
    91         this.source = fac.source;
    92         this.allowGenerics = source.allowGenerics();
    93         this.allowVarargs = source.allowVarargs();
    94         this.allowAsserts = source.allowAsserts();
    95         this.allowEnums = source.allowEnums();
    96         this.allowForeach = source.allowForeach();
    97         this.allowStaticImport = source.allowStaticImport();
    98         this.allowAnnotations = source.allowAnnotations();
    99         this.allowTWR = source.allowTryWithResources();
   100         this.allowDiamond = source.allowDiamond();
   101         this.allowMulticatch = source.allowMulticatch();
   102         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
   103         this.keepDocComments = keepDocComments;
   104         docComments = keepDocComments ? new HashMap<JCTree,String>() : null;
   105         this.keepLineMap = keepLineMap;
   106         this.errorTree = F.Erroneous();
   107     }
   109     /** Switch: Should generics be recognized?
   110      */
   111     boolean allowGenerics;
   113     /** Switch: Should diamond operator be recognized?
   114      */
   115     boolean allowDiamond;
   117     /** Switch: Should multicatch clause be accepted?
   118      */
   119     boolean allowMulticatch;
   121     /** Switch: Should varargs be recognized?
   122      */
   123     boolean allowVarargs;
   125     /** Switch: should we recognize assert statements, or just give a warning?
   126      */
   127     boolean allowAsserts;
   129     /** Switch: should we recognize enums, or just give a warning?
   130      */
   131     boolean allowEnums;
   133     /** Switch: should we recognize foreach?
   134      */
   135     boolean allowForeach;
   137     /** Switch: should we recognize foreach?
   138      */
   139     boolean allowStaticImport;
   141     /** Switch: should we recognize annotations?
   142      */
   143     boolean allowAnnotations;
   145     /** Switch: should we recognize try-with-resources?
   146      */
   147     boolean allowTWR;
   149     /** Switch: should we fold strings?
   150      */
   151     boolean allowStringFolding;
   153     /** Switch: should we keep docComments?
   154      */
   155     boolean keepDocComments;
   157     /** Switch: should we keep line table?
   158      */
   159     boolean keepLineMap;
   161     /** When terms are parsed, the mode determines which is expected:
   162      *     mode = EXPR        : an expression
   163      *     mode = TYPE        : a type
   164      *     mode = NOPARAMS    : no parameters allowed for type
   165      *     mode = TYPEARG     : type argument
   166      */
   167     static final int EXPR = 0x1;
   168     static final int TYPE = 0x2;
   169     static final int NOPARAMS = 0x4;
   170     static final int TYPEARG = 0x8;
   171     static final int DIAMOND = 0x10;
   173     /** The current mode.
   174      */
   175     private int mode = 0;
   177     /** The mode of the term that was parsed last.
   178      */
   179     private int lastmode = 0;
   181 /* ---------- error recovery -------------- */
   183     private JCErroneous errorTree;
   185     /** Skip forward until a suitable stop token is found.
   186      */
   187     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   188          while (true) {
   189              switch (S.token()) {
   190                 case SEMI:
   191                     S.nextToken();
   192                     return;
   193                 case PUBLIC:
   194                 case FINAL:
   195                 case ABSTRACT:
   196                 case MONKEYS_AT:
   197                 case EOF:
   198                 case CLASS:
   199                 case INTERFACE:
   200                 case ENUM:
   201                     return;
   202                 case IMPORT:
   203                     if (stopAtImport)
   204                         return;
   205                     break;
   206                 case LBRACE:
   207                 case RBRACE:
   208                 case PRIVATE:
   209                 case PROTECTED:
   210                 case STATIC:
   211                 case TRANSIENT:
   212                 case NATIVE:
   213                 case VOLATILE:
   214                 case SYNCHRONIZED:
   215                 case STRICTFP:
   216                 case LT:
   217                 case BYTE:
   218                 case SHORT:
   219                 case CHAR:
   220                 case INT:
   221                 case LONG:
   222                 case FLOAT:
   223                 case DOUBLE:
   224                 case BOOLEAN:
   225                 case VOID:
   226                     if (stopAtMemberDecl)
   227                         return;
   228                     break;
   229                 case IDENTIFIER:
   230                    if (stopAtIdentifier)
   231                         return;
   232                     break;
   233                 case CASE:
   234                 case DEFAULT:
   235                 case IF:
   236                 case FOR:
   237                 case WHILE:
   238                 case DO:
   239                 case TRY:
   240                 case SWITCH:
   241                 case RETURN:
   242                 case THROW:
   243                 case BREAK:
   244                 case CONTINUE:
   245                 case ELSE:
   246                 case FINALLY:
   247                 case CATCH:
   248                     if (stopAtStatement)
   249                         return;
   250                     break;
   251             }
   252             S.nextToken();
   253         }
   254     }
   256     private JCErroneous syntaxError(int pos, String key, Token... args) {
   257         return syntaxError(pos, List.<JCTree>nil(), key, args);
   258     }
   260     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
   261         setErrorEndPos(pos);
   262         JCErroneous err = F.at(pos).Erroneous(errs);
   263         reportSyntaxError(err, key, (Object[])args);
   264         if (errs != null) {
   265             JCTree last = errs.last();
   266             if (last != null)
   267                 storeEnd(last, pos);
   268         }
   269         return toP(err);
   270     }
   272     private int errorPos = Position.NOPOS;
   274     /**
   275      * Report a syntax using the given the position parameter and arguments,
   276      * unless one was already reported at the same position.
   277      */
   278     private void reportSyntaxError(int pos, String key, Object... args) {
   279         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   280         reportSyntaxError(diag, key, args);
   281     }
   283     /**
   284      * Report a syntax error using the given DiagnosticPosition object and
   285      * arguments, unless one was already reported at the same position.
   286      */
   287     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   288         int pos = diagPos.getPreferredPosition();
   289         if (pos > S.errPos() || pos == Position.NOPOS) {
   290             if (S.token() == EOF) {
   291                 error(diagPos, "premature.eof");
   292             } else {
   293                 error(diagPos, key, args);
   294             }
   295         }
   296         S.errPos(pos);
   297         if (S.pos() == errorPos)
   298             S.nextToken(); // guarantee progress
   299         errorPos = S.pos();
   300     }
   303     /** Generate a syntax error at current position unless one was already
   304      *  reported at the same position.
   305      */
   306     private JCErroneous syntaxError(String key) {
   307         return syntaxError(S.pos(), key);
   308     }
   310     /** Generate a syntax error at current position unless one was
   311      *  already reported at the same position.
   312      */
   313     private JCErroneous syntaxError(String key, Token arg) {
   314         return syntaxError(S.pos(), key, arg);
   315     }
   317     /** If next input token matches given token, skip it, otherwise report
   318      *  an error.
   319      */
   320     public void accept(Token token) {
   321         if (S.token() == token) {
   322             S.nextToken();
   323         } else {
   324             setErrorEndPos(S.pos());
   325             reportSyntaxError(S.prevEndPos(), "expected", token);
   326         }
   327     }
   329     /** Report an illegal start of expression/type error at given position.
   330      */
   331     JCExpression illegal(int pos) {
   332         setErrorEndPos(pos);
   333         if ((mode & EXPR) != 0)
   334             return syntaxError(pos, "illegal.start.of.expr");
   335         else
   336             return syntaxError(pos, "illegal.start.of.type");
   338     }
   340     /** Report an illegal start of expression/type error at current position.
   341      */
   342     JCExpression illegal() {
   343         return illegal(S.pos());
   344     }
   346     /** Diagnose a modifier flag from the set, if any. */
   347     void checkNoMods(long mods) {
   348         if (mods != 0) {
   349             long lowestMod = mods & -mods;
   350             error(S.pos(), "mod.not.allowed.here",
   351                       Flags.asFlagSet(lowestMod));
   352         }
   353     }
   355 /* ---------- doc comments --------- */
   357     /** A hashtable to store all documentation comments
   358      *  indexed by the tree nodes they refer to.
   359      *  defined only if option flag keepDocComment is set.
   360      */
   361     private final Map<JCTree, String> docComments;
   363     /** Make an entry into docComments hashtable,
   364      *  provided flag keepDocComments is set and given doc comment is non-null.
   365      *  @param tree   The tree to be used as index in the hashtable
   366      *  @param dc     The doc comment to associate with the tree, or null.
   367      */
   368     void attach(JCTree tree, String dc) {
   369         if (keepDocComments && dc != null) {
   370 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   371             docComments.put(tree, dc);
   372         }
   373     }
   375 /* -------- source positions ------- */
   377     private int errorEndPos = -1;
   379     private void setErrorEndPos(int errPos) {
   380         if (errPos > errorEndPos)
   381             errorEndPos = errPos;
   382     }
   384     protected int getErrorEndPos() {
   385         return errorEndPos;
   386     }
   388     /**
   389      * Store ending position for a tree.
   390      * @param tree   The tree.
   391      * @param endpos The ending position to associate with the tree.
   392      */
   393     protected void storeEnd(JCTree tree, int endpos) {}
   395     /**
   396      * Store ending position for a tree.  The ending position should
   397      * be the ending position of the current token.
   398      * @param t The tree.
   399      */
   400     protected <T extends JCTree> T to(T t) { return t; }
   402     /**
   403      * Store ending position for a tree.  The ending position should
   404      * be greater of the ending position of the previous token and errorEndPos.
   405      * @param t The tree.
   406      */
   407     protected <T extends JCTree> T toP(T t) { return t; }
   409     /** Get the start position for a tree node.  The start position is
   410      * defined to be the position of the first character of the first
   411      * token of the node's source text.
   412      * @param tree  The tree node
   413      */
   414     public int getStartPos(JCTree tree) {
   415         return TreeInfo.getStartPos(tree);
   416     }
   418     /**
   419      * Get the end position for a tree node.  The end position is
   420      * defined to be the position of the last character of the last
   421      * token of the node's source text.  Returns Position.NOPOS if end
   422      * positions are not generated or the position is otherwise not
   423      * found.
   424      * @param tree  The tree node
   425      */
   426     public int getEndPos(JCTree tree) {
   427         return Position.NOPOS;
   428     }
   432 /* ---------- parsing -------------- */
   434     /**
   435      * Ident = IDENTIFIER
   436      */
   437     Name ident() {
   438         if (S.token() == IDENTIFIER) {
   439             Name name = S.name();
   440             S.nextToken();
   441             return name;
   442         } else if (S.token() == ASSERT) {
   443             if (allowAsserts) {
   444                 error(S.pos(), "assert.as.identifier");
   445                 S.nextToken();
   446                 return names.error;
   447             } else {
   448                 warning(S.pos(), "assert.as.identifier");
   449                 Name name = S.name();
   450                 S.nextToken();
   451                 return name;
   452             }
   453         } else if (S.token() == ENUM) {
   454             if (allowEnums) {
   455                 error(S.pos(), "enum.as.identifier");
   456                 S.nextToken();
   457                 return names.error;
   458             } else {
   459                 warning(S.pos(), "enum.as.identifier");
   460                 Name name = S.name();
   461                 S.nextToken();
   462                 return name;
   463             }
   464         } else {
   465             accept(IDENTIFIER);
   466             return names.error;
   467         }
   468 }
   470     /**
   471      * Qualident = Ident { DOT Ident }
   472      */
   473     public JCExpression qualident() {
   474         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
   475         while (S.token() == DOT) {
   476             int pos = S.pos();
   477             S.nextToken();
   478             t = toP(F.at(pos).Select(t, ident()));
   479         }
   480         return t;
   481     }
   483     JCExpression literal(Name prefix) {
   484         return literal(prefix, S.pos());
   485     }
   487     /**
   488      * Literal =
   489      *     INTLITERAL
   490      *   | LONGLITERAL
   491      *   | FLOATLITERAL
   492      *   | DOUBLELITERAL
   493      *   | CHARLITERAL
   494      *   | STRINGLITERAL
   495      *   | TRUE
   496      *   | FALSE
   497      *   | NULL
   498      */
   499     JCExpression literal(Name prefix, int pos) {
   500         JCExpression t = errorTree;
   501         switch (S.token()) {
   502         case INTLITERAL:
   503             try {
   504                 t = F.at(pos).Literal(
   505                     TypeTags.INT,
   506                     Convert.string2int(strval(prefix), S.radix()));
   507             } catch (NumberFormatException ex) {
   508                 error(S.pos(), "int.number.too.large", strval(prefix));
   509             }
   510             break;
   511         case LONGLITERAL:
   512             try {
   513                 t = F.at(pos).Literal(
   514                     TypeTags.LONG,
   515                     new Long(Convert.string2long(strval(prefix), S.radix())));
   516             } catch (NumberFormatException ex) {
   517                 error(S.pos(), "int.number.too.large", strval(prefix));
   518             }
   519             break;
   520         case FLOATLITERAL: {
   521             String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
   522             Float n;
   523             try {
   524                 n = Float.valueOf(proper);
   525             } catch (NumberFormatException ex) {
   526                 // error already reported in scanner
   527                 n = Float.NaN;
   528             }
   529             if (n.floatValue() == 0.0f && !isZero(proper))
   530                 error(S.pos(), "fp.number.too.small");
   531             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   532                 error(S.pos(), "fp.number.too.large");
   533             else
   534                 t = F.at(pos).Literal(TypeTags.FLOAT, n);
   535             break;
   536         }
   537         case DOUBLELITERAL: {
   538             String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
   539             Double n;
   540             try {
   541                 n = Double.valueOf(proper);
   542             } catch (NumberFormatException ex) {
   543                 // error already reported in scanner
   544                 n = Double.NaN;
   545             }
   546             if (n.doubleValue() == 0.0d && !isZero(proper))
   547                 error(S.pos(), "fp.number.too.small");
   548             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   549                 error(S.pos(), "fp.number.too.large");
   550             else
   551                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
   552             break;
   553         }
   554         case CHARLITERAL:
   555             t = F.at(pos).Literal(
   556                 TypeTags.CHAR,
   557                 S.stringVal().charAt(0) + 0);
   558             break;
   559         case STRINGLITERAL:
   560             t = F.at(pos).Literal(
   561                 TypeTags.CLASS,
   562                 S.stringVal());
   563             break;
   564         case TRUE: case FALSE:
   565             t = F.at(pos).Literal(
   566                 TypeTags.BOOLEAN,
   567                 (S.token() == TRUE ? 1 : 0));
   568             break;
   569         case NULL:
   570             t = F.at(pos).Literal(
   571                 TypeTags.BOT,
   572                 null);
   573             break;
   574         default:
   575             Assert.error();
   576         }
   577         if (t == errorTree)
   578             t = F.at(pos).Erroneous();
   579         storeEnd(t, S.endPos());
   580         S.nextToken();
   581         return t;
   582     }
   583 //where
   584         boolean isZero(String s) {
   585             char[] cs = s.toCharArray();
   586             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   587             int i = ((base==16) ? 2 : 0);
   588             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   589             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   590         }
   592         String strval(Name prefix) {
   593             String s = S.stringVal();
   594             return prefix.isEmpty() ? s : prefix + s;
   595         }
   597     /** terms can be either expressions or types.
   598      */
   599     public JCExpression parseExpression() {
   600         return term(EXPR);
   601     }
   603     public JCExpression parseType() {
   604         return term(TYPE);
   605     }
   607     JCExpression term(int newmode) {
   608         int prevmode = mode;
   609         mode = newmode;
   610         JCExpression t = term();
   611         lastmode = mode;
   612         mode = prevmode;
   613         return t;
   614     }
   616     /**
   617      *  Expression = Expression1 [ExpressionRest]
   618      *  ExpressionRest = [AssignmentOperator Expression1]
   619      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   620      *                       "&=" | "|=" | "^=" |
   621      *                       "%=" | "<<=" | ">>=" | ">>>="
   622      *  Type = Type1
   623      *  TypeNoParams = TypeNoParams1
   624      *  StatementExpression = Expression
   625      *  ConstantExpression = Expression
   626      */
   627     JCExpression term() {
   628         JCExpression t = term1();
   629         if ((mode & EXPR) != 0 &&
   630             S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
   631             return termRest(t);
   632         else
   633             return t;
   634     }
   636     JCExpression termRest(JCExpression t) {
   637         switch (S.token()) {
   638         case EQ: {
   639             int pos = S.pos();
   640             S.nextToken();
   641             mode = EXPR;
   642             JCExpression t1 = term();
   643             return toP(F.at(pos).Assign(t, t1));
   644         }
   645         case PLUSEQ:
   646         case SUBEQ:
   647         case STAREQ:
   648         case SLASHEQ:
   649         case PERCENTEQ:
   650         case AMPEQ:
   651         case BAREQ:
   652         case CARETEQ:
   653         case LTLTEQ:
   654         case GTGTEQ:
   655         case GTGTGTEQ:
   656             int pos = S.pos();
   657             Token token = S.token();
   658             S.nextToken();
   659             mode = EXPR;
   660             JCExpression t1 = term();
   661             return F.at(pos).Assignop(optag(token), t, t1);
   662         default:
   663             return t;
   664         }
   665     }
   667     /** Expression1   = Expression2 [Expression1Rest]
   668      *  Type1         = Type2
   669      *  TypeNoParams1 = TypeNoParams2
   670      */
   671     JCExpression term1() {
   672         JCExpression t = term2();
   673         if ((mode & EXPR) != 0 && S.token() == QUES) {
   674             mode = EXPR;
   675             return term1Rest(t);
   676         } else {
   677             return t;
   678         }
   679     }
   681     /** Expression1Rest = ["?" Expression ":" Expression1]
   682      */
   683     JCExpression term1Rest(JCExpression t) {
   684         if (S.token() == QUES) {
   685             int pos = S.pos();
   686             S.nextToken();
   687             JCExpression t1 = term();
   688             accept(COLON);
   689             JCExpression t2 = term1();
   690             return F.at(pos).Conditional(t, t1, t2);
   691         } else {
   692             return t;
   693         }
   694     }
   696     /** Expression2   = Expression3 [Expression2Rest]
   697      *  Type2         = Type3
   698      *  TypeNoParams2 = TypeNoParams3
   699      */
   700     JCExpression term2() {
   701         JCExpression t = term3();
   702         if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
   703             mode = EXPR;
   704             return term2Rest(t, TreeInfo.orPrec);
   705         } else {
   706             return t;
   707         }
   708     }
   710     /*  Expression2Rest = {infixop Expression3}
   711      *                  | Expression3 instanceof Type
   712      *  infixop         = "||"
   713      *                  | "&&"
   714      *                  | "|"
   715      *                  | "^"
   716      *                  | "&"
   717      *                  | "==" | "!="
   718      *                  | "<" | ">" | "<=" | ">="
   719      *                  | "<<" | ">>" | ">>>"
   720      *                  | "+" | "-"
   721      *                  | "*" | "/" | "%"
   722      */
   723     JCExpression term2Rest(JCExpression t, int minprec) {
   724         List<JCExpression[]> savedOd = odStackSupply.elems;
   725         JCExpression[] odStack = newOdStack();
   726         List<Token[]> savedOp = opStackSupply.elems;
   727         Token[] opStack = newOpStack();
   728         List<int[]> savedPos = posStackSupply.elems;
   729         int[] posStack = newPosStack();
   730         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   731         int top = 0;
   732         odStack[0] = t;
   733         int startPos = S.pos();
   734         Token topOp = ERROR;
   735         int topOpPos = Position.NOPOS;
   736         while (prec(S.token()) >= minprec) {
   737             posStack[top] = topOpPos;
   738             opStack[top] = topOp;
   739             top++;
   740             topOp = S.token();
   741             topOpPos = S.pos();
   742             S.nextToken();
   743             odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3();
   744             while (top > 0 && prec(topOp) >= prec(S.token())) {
   745                 odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1],
   746                                         odStack[top]);
   747                 top--;
   748                 topOp = opStack[top];
   749                 topOpPos = posStack[top];
   750             }
   751         }
   752         Assert.check(top == 0);
   753         t = odStack[0];
   755         if (t.getTag() == JCTree.PLUS) {
   756             StringBuffer buf = foldStrings(t);
   757             if (buf != null) {
   758                 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
   759             }
   760         }
   762         odStackSupply.elems = savedOd; // optimization
   763         opStackSupply.elems = savedOp; // optimization
   764         posStackSupply.elems = savedPos; // optimization
   765         return t;
   766     }
   767 //where
   768         /** Construct a binary or type test node.
   769          */
   770         private JCExpression makeOp(int pos,
   771                                     Token topOp,
   772                                     JCExpression od1,
   773                                     JCExpression od2)
   774         {
   775             if (topOp == INSTANCEOF) {
   776                 return F.at(pos).TypeTest(od1, od2);
   777             } else {
   778                 return F.at(pos).Binary(optag(topOp), od1, od2);
   779             }
   780         }
   781         /** If tree is a concatenation of string literals, replace it
   782          *  by a single literal representing the concatenated string.
   783          */
   784         protected StringBuffer foldStrings(JCTree tree) {
   785             if (!allowStringFolding)
   786                 return null;
   787             List<String> buf = List.nil();
   788             while (true) {
   789                 if (tree.getTag() == JCTree.LITERAL) {
   790                     JCLiteral lit = (JCLiteral) tree;
   791                     if (lit.typetag == TypeTags.CLASS) {
   792                         StringBuffer sbuf =
   793                             new StringBuffer((String)lit.value);
   794                         while (buf.nonEmpty()) {
   795                             sbuf.append(buf.head);
   796                             buf = buf.tail;
   797                         }
   798                         return sbuf;
   799                     }
   800                 } else if (tree.getTag() == JCTree.PLUS) {
   801                     JCBinary op = (JCBinary)tree;
   802                     if (op.rhs.getTag() == JCTree.LITERAL) {
   803                         JCLiteral lit = (JCLiteral) op.rhs;
   804                         if (lit.typetag == TypeTags.CLASS) {
   805                             buf = buf.prepend((String) lit.value);
   806                             tree = op.lhs;
   807                             continue;
   808                         }
   809                     }
   810                 }
   811                 return null;
   812             }
   813         }
   815         /** optimization: To save allocating a new operand/operator stack
   816          *  for every binary operation, we use supplys.
   817          */
   818         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
   819         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
   820         ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
   822         private JCExpression[] newOdStack() {
   823             if (odStackSupply.elems == odStackSupply.last)
   824                 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
   825             JCExpression[] odStack = odStackSupply.elems.head;
   826             odStackSupply.elems = odStackSupply.elems.tail;
   827             return odStack;
   828         }
   830         private Token[] newOpStack() {
   831             if (opStackSupply.elems == opStackSupply.last)
   832                 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
   833             Token[] opStack = opStackSupply.elems.head;
   834             opStackSupply.elems = opStackSupply.elems.tail;
   835             return opStack;
   836         }
   838         private int[] newPosStack() {
   839             if (posStackSupply.elems == posStackSupply.last)
   840                 posStackSupply.append(new int[infixPrecedenceLevels + 1]);
   841             int[] posStack = posStackSupply.elems.head;
   842             posStackSupply.elems = posStackSupply.elems.tail;
   843             return posStack;
   844         }
   846     /** Expression3    = PrefixOp Expression3
   847      *                 | "(" Expr | TypeNoParams ")" Expression3
   848      *                 | Primary {Selector} {PostfixOp}
   849      *  Primary        = "(" Expression ")"
   850      *                 | Literal
   851      *                 | [TypeArguments] THIS [Arguments]
   852      *                 | [TypeArguments] SUPER SuperSuffix
   853      *                 | NEW [TypeArguments] Creator
   854      *                 | Ident { "." Ident }
   855      *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   856      *                   | Arguments
   857      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   858      *                   ]
   859      *                 | BasicType BracketsOpt "." CLASS
   860      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   861      *  PostfixOp      = "++" | "--"
   862      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   863      *                 | BasicType
   864      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   865      *  Selector       = "." [TypeArguments] Ident [Arguments]
   866      *                 | "." THIS
   867      *                 | "." [TypeArguments] SUPER SuperSuffix
   868      *                 | "." NEW [TypeArguments] InnerCreator
   869      *                 | "[" Expression "]"
   870      *  TypeSelector   = "." Ident [TypeArguments]
   871      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   872      */
   873     protected JCExpression term3() {
   874         int pos = S.pos();
   875         JCExpression t;
   876         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   877         switch (S.token()) {
   878         case QUES:
   879             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   880                 mode = TYPE;
   881                 return typeArgument();
   882             } else
   883                 return illegal();
   884         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   885             if (typeArgs == null && (mode & EXPR) != 0) {
   886                 Token token = S.token();
   887                 S.nextToken();
   888                 mode = EXPR;
   889                 if (token == SUB &&
   890                     (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
   891                     S.radix() == 10) {
   892                     mode = EXPR;
   893                     t = literal(names.hyphen, pos);
   894                 } else {
   895                     t = term3();
   896                     return F.at(pos).Unary(unoptag(token), t);
   897                 }
   898             } else return illegal();
   899             break;
   900         case LPAREN:
   901             if (typeArgs == null && (mode & EXPR) != 0) {
   902                 S.nextToken();
   903                 mode = EXPR | TYPE | NOPARAMS;
   904                 t = term3();
   905                 if ((mode & TYPE) != 0 && S.token() == LT) {
   906                     // Could be a cast to a parameterized type
   907                     int op = JCTree.LT;
   908                     int pos1 = S.pos();
   909                     S.nextToken();
   910                     mode &= (EXPR | TYPE);
   911                     mode |= TYPEARG;
   912                     JCExpression t1 = term3();
   913                     if ((mode & TYPE) != 0 &&
   914                         (S.token() == COMMA || S.token() == GT)) {
   915                         mode = TYPE;
   916                         ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   917                         args.append(t1);
   918                         while (S.token() == COMMA) {
   919                             S.nextToken();
   920                             args.append(typeArgument());
   921                         }
   922                         accept(GT);
   923                         t = toP(F.at(pos1).TypeApply(t, args.toList()));
   924                         checkGenerics();
   925                         while (S.token() == DOT) {
   926                             S.nextToken();
   927                             mode = TYPE;
   928                             t = toP(F.at(S.pos()).Select(t, ident()));
   929                             t = typeArgumentsOpt(t);
   930                         }
   931                         t = bracketsOpt(toP(t));
   932                     } else if ((mode & EXPR) != 0) {
   933                         mode = EXPR;
   934                         JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
   935                         t = F.at(pos1).Binary(op, t, e);
   936                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   937                     } else {
   938                         accept(GT);
   939                     }
   940                 }
   941                 else {
   942                     t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   943                 }
   944                 accept(RPAREN);
   945                 lastmode = mode;
   946                 mode = EXPR;
   947                 if ((lastmode & EXPR) == 0) {
   948                     JCExpression t1 = term3();
   949                     return F.at(pos).TypeCast(t, t1);
   950                 } else if ((lastmode & TYPE) != 0) {
   951                     switch (S.token()) {
   952                     /*case PLUSPLUS: case SUBSUB: */
   953                     case BANG: case TILDE:
   954                     case LPAREN: case THIS: case SUPER:
   955                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
   956                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
   957                     case TRUE: case FALSE: case NULL:
   958                     case NEW: case IDENTIFIER: case ASSERT: case ENUM:
   959                     case BYTE: case SHORT: case CHAR: case INT:
   960                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
   961                         JCExpression t1 = term3();
   962                         return F.at(pos).TypeCast(t, t1);
   963                     }
   964                 }
   965             } else return illegal();
   966             t = toP(F.at(pos).Parens(t));
   967             break;
   968         case THIS:
   969             if ((mode & EXPR) != 0) {
   970                 mode = EXPR;
   971                 t = to(F.at(pos).Ident(names._this));
   972                 S.nextToken();
   973                 if (typeArgs == null)
   974                     t = argumentsOpt(null, t);
   975                 else
   976                     t = arguments(typeArgs, t);
   977                 typeArgs = null;
   978             } else return illegal();
   979             break;
   980         case SUPER:
   981             if ((mode & EXPR) != 0) {
   982                 mode = EXPR;
   983                 t = to(F.at(pos).Ident(names._super));
   984                 t = superSuffix(typeArgs, t);
   985                 typeArgs = null;
   986             } else return illegal();
   987             break;
   988         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
   989         case CHARLITERAL: case STRINGLITERAL:
   990         case TRUE: case FALSE: case NULL:
   991             if (typeArgs == null && (mode & EXPR) != 0) {
   992                 mode = EXPR;
   993                 t = literal(names.empty);
   994             } else return illegal();
   995             break;
   996         case NEW:
   997             if (typeArgs != null) return illegal();
   998             if ((mode & EXPR) != 0) {
   999                 mode = EXPR;
  1000                 S.nextToken();
  1001                 if (S.token() == LT) typeArgs = typeArguments(false);
  1002                 t = creator(pos, typeArgs);
  1003                 typeArgs = null;
  1004             } else return illegal();
  1005             break;
  1006         case IDENTIFIER: case ASSERT: case ENUM:
  1007             if (typeArgs != null) return illegal();
  1008             t = toP(F.at(S.pos()).Ident(ident()));
  1009             loop: while (true) {
  1010                 pos = S.pos();
  1011                 switch (S.token()) {
  1012                 case LBRACKET:
  1013                     S.nextToken();
  1014                     if (S.token() == RBRACKET) {
  1015                         S.nextToken();
  1016                         t = bracketsOpt(t);
  1017                         t = toP(F.at(pos).TypeArray(t));
  1018                         t = bracketsSuffix(t);
  1019                     } else {
  1020                         if ((mode & EXPR) != 0) {
  1021                             mode = EXPR;
  1022                             JCExpression t1 = term();
  1023                             t = to(F.at(pos).Indexed(t, t1));
  1025                         accept(RBRACKET);
  1027                     break loop;
  1028                 case LPAREN:
  1029                     if ((mode & EXPR) != 0) {
  1030                         mode = EXPR;
  1031                         t = arguments(typeArgs, t);
  1032                         typeArgs = null;
  1034                     break loop;
  1035                 case DOT:
  1036                     S.nextToken();
  1037                     int oldmode = mode;
  1038                     mode &= ~NOPARAMS;
  1039                     typeArgs = typeArgumentsOpt(EXPR);
  1040                     mode = oldmode;
  1041                     if ((mode & EXPR) != 0) {
  1042                         switch (S.token()) {
  1043                         case CLASS:
  1044                             if (typeArgs != null) return illegal();
  1045                             mode = EXPR;
  1046                             t = to(F.at(pos).Select(t, names._class));
  1047                             S.nextToken();
  1048                             break loop;
  1049                         case THIS:
  1050                             if (typeArgs != null) return illegal();
  1051                             mode = EXPR;
  1052                             t = to(F.at(pos).Select(t, names._this));
  1053                             S.nextToken();
  1054                             break loop;
  1055                         case SUPER:
  1056                             mode = EXPR;
  1057                             t = to(F.at(pos).Select(t, names._super));
  1058                             t = superSuffix(typeArgs, t);
  1059                             typeArgs = null;
  1060                             break loop;
  1061                         case NEW:
  1062                             if (typeArgs != null) return illegal();
  1063                             mode = EXPR;
  1064                             int pos1 = S.pos();
  1065                             S.nextToken();
  1066                             if (S.token() == LT) typeArgs = typeArguments(false);
  1067                             t = innerCreator(pos1, typeArgs, t);
  1068                             typeArgs = null;
  1069                             break loop;
  1072                     // typeArgs saved for next loop iteration.
  1073                     t = toP(F.at(pos).Select(t, ident()));
  1074                     break;
  1075                 default:
  1076                     break loop;
  1079             if (typeArgs != null) illegal();
  1080             t = typeArgumentsOpt(t);
  1081             break;
  1082         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1083         case DOUBLE: case BOOLEAN:
  1084             if (typeArgs != null) illegal();
  1085             t = bracketsSuffix(bracketsOpt(basicType()));
  1086             break;
  1087         case VOID:
  1088             if (typeArgs != null) illegal();
  1089             if ((mode & EXPR) != 0) {
  1090                 S.nextToken();
  1091                 if (S.token() == DOT) {
  1092                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
  1093                     t = bracketsSuffix(ti);
  1094                 } else {
  1095                     return illegal(pos);
  1097             } else {
  1098                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1099                 // a void type (like other primitive types) to the next phase.
  1100                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1101                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
  1102                 S.nextToken();
  1103                 return ti;
  1104                 //return illegal();
  1106             break;
  1107         default:
  1108             return illegal();
  1110         if (typeArgs != null) illegal();
  1111         while (true) {
  1112             int pos1 = S.pos();
  1113             if (S.token() == LBRACKET) {
  1114                 S.nextToken();
  1115                 if ((mode & TYPE) != 0) {
  1116                     int oldmode = mode;
  1117                     mode = TYPE;
  1118                     if (S.token() == RBRACKET) {
  1119                         S.nextToken();
  1120                         t = bracketsOpt(t);
  1121                         t = toP(F.at(pos1).TypeArray(t));
  1122                         return t;
  1124                     mode = oldmode;
  1126                 if ((mode & EXPR) != 0) {
  1127                     mode = EXPR;
  1128                     JCExpression t1 = term();
  1129                     t = to(F.at(pos1).Indexed(t, t1));
  1131                 accept(RBRACKET);
  1132             } else if (S.token() == DOT) {
  1133                 S.nextToken();
  1134                 typeArgs = typeArgumentsOpt(EXPR);
  1135                 if (S.token() == SUPER && (mode & EXPR) != 0) {
  1136                     mode = EXPR;
  1137                     t = to(F.at(pos1).Select(t, names._super));
  1138                     S.nextToken();
  1139                     t = arguments(typeArgs, t);
  1140                     typeArgs = null;
  1141                 } else if (S.token() == NEW && (mode & EXPR) != 0) {
  1142                     if (typeArgs != null) return illegal();
  1143                     mode = EXPR;
  1144                     int pos2 = S.pos();
  1145                     S.nextToken();
  1146                     if (S.token() == LT) typeArgs = typeArguments(false);
  1147                     t = innerCreator(pos2, typeArgs, t);
  1148                     typeArgs = null;
  1149                 } else {
  1150                     t = toP(F.at(pos1).Select(t, ident()));
  1151                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1152                     typeArgs = null;
  1154             } else {
  1155                 break;
  1158         while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
  1159             mode = EXPR;
  1160             t = to(F.at(S.pos()).Unary(
  1161                   S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
  1162             S.nextToken();
  1164         return toP(t);
  1167     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1168      */
  1169     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1170         S.nextToken();
  1171         if (S.token() == LPAREN || typeArgs != null) {
  1172             t = arguments(typeArgs, t);
  1173         } else {
  1174             int pos = S.pos();
  1175             accept(DOT);
  1176             typeArgs = (S.token() == LT) ? typeArguments(false) : null;
  1177             t = toP(F.at(pos).Select(t, ident()));
  1178             t = argumentsOpt(typeArgs, t);
  1180         return t;
  1183     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1184      */
  1185     JCPrimitiveTypeTree basicType() {
  1186         JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
  1187         S.nextToken();
  1188         return t;
  1191     /** ArgumentsOpt = [ Arguments ]
  1192      */
  1193     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1194         if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
  1195             mode = EXPR;
  1196             return arguments(typeArgs, t);
  1197         } else {
  1198             return t;
  1202     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1203      */
  1204     List<JCExpression> arguments() {
  1205         ListBuffer<JCExpression> args = lb();
  1206         if (S.token() == LPAREN) {
  1207             S.nextToken();
  1208             if (S.token() != RPAREN) {
  1209                 args.append(parseExpression());
  1210                 while (S.token() == COMMA) {
  1211                     S.nextToken();
  1212                     args.append(parseExpression());
  1215             accept(RPAREN);
  1216         } else {
  1217             syntaxError(S.pos(), "expected", LPAREN);
  1219         return args.toList();
  1222     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1223         int pos = S.pos();
  1224         List<JCExpression> args = arguments();
  1225         return toP(F.at(pos).Apply(typeArgs, t, args));
  1228     /**  TypeArgumentsOpt = [ TypeArguments ]
  1229      */
  1230     JCExpression typeArgumentsOpt(JCExpression t) {
  1231         if (S.token() == LT &&
  1232             (mode & TYPE) != 0 &&
  1233             (mode & NOPARAMS) == 0) {
  1234             mode = TYPE;
  1235             checkGenerics();
  1236             return typeArguments(t, false);
  1237         } else {
  1238             return t;
  1241     List<JCExpression> typeArgumentsOpt() {
  1242         return typeArgumentsOpt(TYPE);
  1245     List<JCExpression> typeArgumentsOpt(int useMode) {
  1246         if (S.token() == LT) {
  1247             checkGenerics();
  1248             if ((mode & useMode) == 0 ||
  1249                 (mode & NOPARAMS) != 0) {
  1250                 illegal();
  1252             mode = useMode;
  1253             return typeArguments(false);
  1255         return null;
  1258     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1259      */
  1260     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1261         if (S.token() == LT) {
  1262             S.nextToken();
  1263             if (S.token() == GT && diamondAllowed) {
  1264                 checkDiamond();
  1265                 mode |= DIAMOND;
  1266                 S.nextToken();
  1267                 return List.nil();
  1268             } else {
  1269                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1270                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1271                 while (S.token() == COMMA) {
  1272                     S.nextToken();
  1273                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1275                 switch (S.token()) {
  1276                 case GTGTGTEQ:
  1277                     S.token(GTGTEQ);
  1278                     break;
  1279                 case GTGTEQ:
  1280                     S.token(GTEQ);
  1281                     break;
  1282                 case GTEQ:
  1283                     S.token(EQ);
  1284                     break;
  1285                 case GTGTGT:
  1286                     S.token(GTGT);
  1287                     break;
  1288                 case GTGT:
  1289                     S.token(GT);
  1290                     break;
  1291                 case GT:
  1292                     S.nextToken();
  1293                     break;
  1294                 default:
  1295                     args.append(syntaxError(S.pos(), "expected", GT));
  1296                     break;
  1298                 return args.toList();
  1300         } else {
  1301             return List.<JCExpression>of(syntaxError(S.pos(), "expected", LT));
  1305     /** TypeArgument = Type
  1306      *               | "?"
  1307      *               | "?" EXTENDS Type {"&" Type}
  1308      *               | "?" SUPER Type
  1309      */
  1310     JCExpression typeArgument() {
  1311         if (S.token() != QUES) return parseType();
  1312         int pos = S.pos();
  1313         S.nextToken();
  1314         if (S.token() == EXTENDS) {
  1315             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1316             S.nextToken();
  1317             JCExpression bound = parseType();
  1318             return F.at(pos).Wildcard(t, bound);
  1319         } else if (S.token() == SUPER) {
  1320             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1321             S.nextToken();
  1322             JCExpression bound = parseType();
  1323             return F.at(pos).Wildcard(t, bound);
  1324         } else if (S.token() == IDENTIFIER) {
  1325             //error recovery
  1326             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1327             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1328             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
  1329             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1330             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1331             return err;
  1332         } else {
  1333             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1334             return toP(F.at(pos).Wildcard(t, null));
  1338     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1339         int pos = S.pos();
  1340         List<JCExpression> args = typeArguments(diamondAllowed);
  1341         return toP(F.at(pos).TypeApply(t, args));
  1344     /** BracketsOpt = {"[" "]"}
  1345      */
  1346     private JCExpression bracketsOpt(JCExpression t) {
  1347         if (S.token() == LBRACKET) {
  1348             int pos = S.pos();
  1349             S.nextToken();
  1350             t = bracketsOptCont(t, pos);
  1351             F.at(pos);
  1353         return t;
  1356     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1357         accept(RBRACKET);
  1358         t = bracketsOpt(t);
  1359         return toP(F.at(pos).TypeArray(t));
  1362     /** BracketsSuffixExpr = "." CLASS
  1363      *  BracketsSuffixType =
  1364      */
  1365     JCExpression bracketsSuffix(JCExpression t) {
  1366         if ((mode & EXPR) != 0 && S.token() == DOT) {
  1367             mode = EXPR;
  1368             int pos = S.pos();
  1369             S.nextToken();
  1370             accept(CLASS);
  1371             if (S.pos() == errorEndPos) {
  1372                 // error recovery
  1373                 Name name = null;
  1374                 if (S.token() == IDENTIFIER) {
  1375                     name = S.name();
  1376                     S.nextToken();
  1377                 } else {
  1378                     name = names.error;
  1380                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1381             } else {
  1382                 t = toP(F.at(pos).Select(t, names._class));
  1384         } else if ((mode & TYPE) != 0) {
  1385             mode = TYPE;
  1386         } else {
  1387             syntaxError(S.pos(), "dot.class.expected");
  1389         return t;
  1392     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1393      */
  1394     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1395         switch (S.token()) {
  1396         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1397         case DOUBLE: case BOOLEAN:
  1398             if (typeArgs == null)
  1399                 return arrayCreatorRest(newpos, basicType());
  1400             break;
  1401         default:
  1403         JCExpression t = qualident();
  1404         int oldmode = mode;
  1405         mode = TYPE;
  1406         boolean diamondFound = false;
  1407         int lastTypeargsPos = -1;
  1408         if (S.token() == LT) {
  1409             checkGenerics();
  1410             lastTypeargsPos = S.pos();
  1411             t = typeArguments(t, true);
  1412             diamondFound = (mode & DIAMOND) != 0;
  1414         while (S.token() == DOT) {
  1415             if (diamondFound) {
  1416                 //cannot select after a diamond
  1417                 illegal();
  1419             int pos = S.pos();
  1420             S.nextToken();
  1421             t = toP(F.at(pos).Select(t, ident()));
  1422             if (S.token() == LT) {
  1423                 lastTypeargsPos = S.pos();
  1424                 checkGenerics();
  1425                 t = typeArguments(t, true);
  1426                 diamondFound = (mode & DIAMOND) != 0;
  1429         mode = oldmode;
  1430         if (S.token() == LBRACKET) {
  1431             JCExpression e = arrayCreatorRest(newpos, t);
  1432             if (diamondFound) {
  1433                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  1434                 return toP(F.at(newpos).Erroneous(List.of(e)));
  1436             else if (typeArgs != null) {
  1437                 int pos = newpos;
  1438                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1439                     // note: this should always happen but we should
  1440                     // not rely on this as the parser is continuously
  1441                     // modified to improve error recovery.
  1442                     pos = typeArgs.head.pos;
  1444                 setErrorEndPos(S.prevEndPos());
  1445                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  1446                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  1447                 return toP(err);
  1449             return e;
  1450         } else if (S.token() == LPAREN) {
  1451             return classCreatorRest(newpos, null, typeArgs, t);
  1452         } else {
  1453             setErrorEndPos(S.pos());
  1454             reportSyntaxError(S.pos(), "expected2", LPAREN, LBRACKET);
  1455             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1456             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1460     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1461      */
  1462     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1463         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
  1464         if (S.token() == LT) {
  1465             int oldmode = mode;
  1466             checkGenerics();
  1467             t = typeArguments(t, true);
  1468             mode = oldmode;
  1470         return classCreatorRest(newpos, encl, typeArgs, t);
  1473     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1474      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1475      */
  1476     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1477         accept(LBRACKET);
  1478         if (S.token() == RBRACKET) {
  1479             accept(RBRACKET);
  1480             elemtype = bracketsOpt(elemtype);
  1481             if (S.token() == LBRACE) {
  1482                 return arrayInitializer(newpos, elemtype);
  1483             } else {
  1484                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  1485                 return syntaxError(S.pos(), List.<JCTree>of(t), "array.dimension.missing");
  1487         } else {
  1488             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1489             dims.append(parseExpression());
  1490             accept(RBRACKET);
  1491             while (S.token() == LBRACKET) {
  1492                 int pos = S.pos();
  1493                 S.nextToken();
  1494                 if (S.token() == RBRACKET) {
  1495                     elemtype = bracketsOptCont(elemtype, pos);
  1496                 } else {
  1497                     dims.append(parseExpression());
  1498                     accept(RBRACKET);
  1501             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1505     /** ClassCreatorRest = Arguments [ClassBody]
  1506      */
  1507     JCNewClass classCreatorRest(int newpos,
  1508                                   JCExpression encl,
  1509                                   List<JCExpression> typeArgs,
  1510                                   JCExpression t)
  1512         List<JCExpression> args = arguments();
  1513         JCClassDecl body = null;
  1514         if (S.token() == LBRACE) {
  1515             int pos = S.pos();
  1516             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1517             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1518             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1520         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1523     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1524      */
  1525     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1526         accept(LBRACE);
  1527         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1528         if (S.token() == COMMA) {
  1529             S.nextToken();
  1530         } else if (S.token() != RBRACE) {
  1531             elems.append(variableInitializer());
  1532             while (S.token() == COMMA) {
  1533                 S.nextToken();
  1534                 if (S.token() == RBRACE) break;
  1535                 elems.append(variableInitializer());
  1538         accept(RBRACE);
  1539         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1542     /** VariableInitializer = ArrayInitializer | Expression
  1543      */
  1544     public JCExpression variableInitializer() {
  1545         return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
  1548     /** ParExpression = "(" Expression ")"
  1549      */
  1550     JCExpression parExpression() {
  1551         accept(LPAREN);
  1552         JCExpression t = parseExpression();
  1553         accept(RPAREN);
  1554         return t;
  1557     /** Block = "{" BlockStatements "}"
  1558      */
  1559     JCBlock block(int pos, long flags) {
  1560         accept(LBRACE);
  1561         List<JCStatement> stats = blockStatements();
  1562         JCBlock t = F.at(pos).Block(flags, stats);
  1563         while (S.token() == CASE || S.token() == DEFAULT) {
  1564             syntaxError("orphaned", S.token());
  1565             switchBlockStatementGroups();
  1567         // the Block node has a field "endpos" for first char of last token, which is
  1568         // usually but not necessarily the last char of the last token.
  1569         t.endpos = S.pos();
  1570         accept(RBRACE);
  1571         return toP(t);
  1574     public JCBlock block() {
  1575         return block(S.pos(), 0);
  1578     /** BlockStatements = { BlockStatement }
  1579      *  BlockStatement  = LocalVariableDeclarationStatement
  1580      *                  | ClassOrInterfaceOrEnumDeclaration
  1581      *                  | [Ident ":"] Statement
  1582      *  LocalVariableDeclarationStatement
  1583      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1584      */
  1585     @SuppressWarnings("fallthrough")
  1586     List<JCStatement> blockStatements() {
  1587 //todo: skip to anchor on error(?)
  1588         int lastErrPos = -1;
  1589         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1590         while (true) {
  1591             int pos = S.pos();
  1592             switch (S.token()) {
  1593             case RBRACE: case CASE: case DEFAULT: case EOF:
  1594                 return stats.toList();
  1595             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1596             case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1597             case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1598                 stats.append(parseStatement());
  1599                 break;
  1600             case MONKEYS_AT:
  1601             case FINAL: {
  1602                 String dc = S.docComment();
  1603                 JCModifiers mods = modifiersOpt();
  1604                 if (S.token() == INTERFACE ||
  1605                     S.token() == CLASS ||
  1606                     allowEnums && S.token() == ENUM) {
  1607                     stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1608                 } else {
  1609                     JCExpression t = parseType();
  1610                     stats.appendList(variableDeclarators(mods, t,
  1611                                                          new ListBuffer<JCStatement>()));
  1612                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1613                     storeEnd(stats.elems.last(), S.endPos());
  1614                     accept(SEMI);
  1616                 break;
  1618             case ABSTRACT: case STRICTFP: {
  1619                 String dc = S.docComment();
  1620                 JCModifiers mods = modifiersOpt();
  1621                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1622                 break;
  1624             case INTERFACE:
  1625             case CLASS:
  1626                 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1627                                                                S.docComment()));
  1628                 break;
  1629             case ENUM:
  1630             case ASSERT:
  1631                 if (allowEnums && S.token() == ENUM) {
  1632                     error(S.pos(), "local.enum");
  1633                     stats.
  1634                         append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1635                                                                  S.docComment()));
  1636                     break;
  1637                 } else if (allowAsserts && S.token() == ASSERT) {
  1638                     stats.append(parseStatement());
  1639                     break;
  1641                 /* fall through to default */
  1642             default:
  1643                 Name name = S.name();
  1644                 JCExpression t = term(EXPR | TYPE);
  1645                 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
  1646                     S.nextToken();
  1647                     JCStatement stat = parseStatement();
  1648                     stats.append(F.at(pos).Labelled(name, stat));
  1649                 } else if ((lastmode & TYPE) != 0 &&
  1650                            (S.token() == IDENTIFIER ||
  1651                             S.token() == ASSERT ||
  1652                             S.token() == ENUM)) {
  1653                     pos = S.pos();
  1654                     JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1655                     F.at(pos);
  1656                     stats.appendList(variableDeclarators(mods, t,
  1657                                                          new ListBuffer<JCStatement>()));
  1658                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1659                     storeEnd(stats.elems.last(), S.endPos());
  1660                     accept(SEMI);
  1661                 } else {
  1662                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1663                     stats.append(to(F.at(pos).Exec(checkExprStat(t))));
  1664                     accept(SEMI);
  1668             // error recovery
  1669             if (S.pos() == lastErrPos)
  1670                 return stats.toList();
  1671             if (S.pos() <= errorEndPos) {
  1672                 skip(false, true, true, true);
  1673                 lastErrPos = S.pos();
  1676             // ensure no dangling /** @deprecated */ active
  1677             S.resetDeprecatedFlag();
  1681     /** Statement =
  1682      *       Block
  1683      *     | IF ParExpression Statement [ELSE Statement]
  1684      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1685      *     | FOR "(" FormalParameter : Expression ")" Statement
  1686      *     | WHILE ParExpression Statement
  1687      *     | DO Statement WHILE ParExpression ";"
  1688      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1689      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  1690      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1691      *     | SYNCHRONIZED ParExpression Block
  1692      *     | RETURN [Expression] ";"
  1693      *     | THROW Expression ";"
  1694      *     | BREAK [Ident] ";"
  1695      *     | CONTINUE [Ident] ";"
  1696      *     | ASSERT Expression [ ":" Expression ] ";"
  1697      *     | ";"
  1698      *     | ExpressionStatement
  1699      *     | Ident ":" Statement
  1700      */
  1701     @SuppressWarnings("fallthrough")
  1702     public JCStatement parseStatement() {
  1703         int pos = S.pos();
  1704         switch (S.token()) {
  1705         case LBRACE:
  1706             return block();
  1707         case IF: {
  1708             S.nextToken();
  1709             JCExpression cond = parExpression();
  1710             JCStatement thenpart = parseStatement();
  1711             JCStatement elsepart = null;
  1712             if (S.token() == ELSE) {
  1713                 S.nextToken();
  1714                 elsepart = parseStatement();
  1716             return F.at(pos).If(cond, thenpart, elsepart);
  1718         case FOR: {
  1719             S.nextToken();
  1720             accept(LPAREN);
  1721             List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
  1722             if (inits.length() == 1 &&
  1723                 inits.head.getTag() == JCTree.VARDEF &&
  1724                 ((JCVariableDecl) inits.head).init == null &&
  1725                 S.token() == COLON) {
  1726                 checkForeach();
  1727                 JCVariableDecl var = (JCVariableDecl)inits.head;
  1728                 accept(COLON);
  1729                 JCExpression expr = parseExpression();
  1730                 accept(RPAREN);
  1731                 JCStatement body = parseStatement();
  1732                 return F.at(pos).ForeachLoop(var, expr, body);
  1733             } else {
  1734                 accept(SEMI);
  1735                 JCExpression cond = S.token() == SEMI ? null : parseExpression();
  1736                 accept(SEMI);
  1737                 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  1738                 accept(RPAREN);
  1739                 JCStatement body = parseStatement();
  1740                 return F.at(pos).ForLoop(inits, cond, steps, body);
  1743         case WHILE: {
  1744             S.nextToken();
  1745             JCExpression cond = parExpression();
  1746             JCStatement body = parseStatement();
  1747             return F.at(pos).WhileLoop(cond, body);
  1749         case DO: {
  1750             S.nextToken();
  1751             JCStatement body = parseStatement();
  1752             accept(WHILE);
  1753             JCExpression cond = parExpression();
  1754             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  1755             accept(SEMI);
  1756             return t;
  1758         case TRY: {
  1759             S.nextToken();
  1760             List<JCTree> resources = List.<JCTree>nil();
  1761             if (S.token() == LPAREN) {
  1762                 checkTryWithResources();
  1763                 S.nextToken();
  1764                 resources = resources();
  1765                 accept(RPAREN);
  1767             JCBlock body = block();
  1768             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  1769             JCBlock finalizer = null;
  1770             if (S.token() == CATCH || S.token() == FINALLY) {
  1771                 while (S.token() == CATCH) catchers.append(catchClause());
  1772                 if (S.token() == FINALLY) {
  1773                     S.nextToken();
  1774                     finalizer = block();
  1776             } else {
  1777                 if (allowTWR) {
  1778                     if (resources.isEmpty())
  1779                         error(pos, "try.without.catch.finally.or.resource.decls");
  1780                 } else
  1781                     error(pos, "try.without.catch.or.finally");
  1783             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  1785         case SWITCH: {
  1786             S.nextToken();
  1787             JCExpression selector = parExpression();
  1788             accept(LBRACE);
  1789             List<JCCase> cases = switchBlockStatementGroups();
  1790             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  1791             accept(RBRACE);
  1792             return t;
  1794         case SYNCHRONIZED: {
  1795             S.nextToken();
  1796             JCExpression lock = parExpression();
  1797             JCBlock body = block();
  1798             return F.at(pos).Synchronized(lock, body);
  1800         case RETURN: {
  1801             S.nextToken();
  1802             JCExpression result = S.token() == SEMI ? null : parseExpression();
  1803             JCReturn t = to(F.at(pos).Return(result));
  1804             accept(SEMI);
  1805             return t;
  1807         case THROW: {
  1808             S.nextToken();
  1809             JCExpression exc = parseExpression();
  1810             JCThrow t = to(F.at(pos).Throw(exc));
  1811             accept(SEMI);
  1812             return t;
  1814         case BREAK: {
  1815             S.nextToken();
  1816             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1817             JCBreak t = to(F.at(pos).Break(label));
  1818             accept(SEMI);
  1819             return t;
  1821         case CONTINUE: {
  1822             S.nextToken();
  1823             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1824             JCContinue t =  to(F.at(pos).Continue(label));
  1825             accept(SEMI);
  1826             return t;
  1828         case SEMI:
  1829             S.nextToken();
  1830             return toP(F.at(pos).Skip());
  1831         case ELSE:
  1832             return toP(F.Exec(syntaxError("else.without.if")));
  1833         case FINALLY:
  1834             return toP(F.Exec(syntaxError("finally.without.try")));
  1835         case CATCH:
  1836             return toP(F.Exec(syntaxError("catch.without.try")));
  1837         case ASSERT: {
  1838             if (allowAsserts && S.token() == ASSERT) {
  1839                 S.nextToken();
  1840                 JCExpression assertion = parseExpression();
  1841                 JCExpression message = null;
  1842                 if (S.token() == COLON) {
  1843                     S.nextToken();
  1844                     message = parseExpression();
  1846                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  1847                 accept(SEMI);
  1848                 return t;
  1850             /* else fall through to default case */
  1852         case ENUM:
  1853         default:
  1854             Name name = S.name();
  1855             JCExpression expr = parseExpression();
  1856             if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
  1857                 S.nextToken();
  1858                 JCStatement stat = parseStatement();
  1859                 return F.at(pos).Labelled(name, stat);
  1860             } else {
  1861                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1862                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  1863                 accept(SEMI);
  1864                 return stat;
  1869     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  1870      */
  1871     protected JCCatch catchClause() {
  1872         int pos = S.pos();
  1873         accept(CATCH);
  1874         accept(LPAREN);
  1875         JCModifiers mods = optFinal(Flags.PARAMETER);
  1876         List<JCExpression> catchTypes = catchTypes();
  1877         JCExpression paramType = catchTypes.size() > 1 ?
  1878                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  1879                 catchTypes.head;
  1880         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  1881         accept(RPAREN);
  1882         JCBlock body = block();
  1883         return F.at(pos).Catch(formal, body);
  1886     List<JCExpression> catchTypes() {
  1887         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  1888         catchTypes.add(parseType());
  1889         while (S.token() == BAR) {
  1890             checkMulticatch();
  1891             S.nextToken();
  1892             catchTypes.add(qualident());
  1894         return catchTypes.toList();
  1897     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  1898      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  1899      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  1900      */
  1901     List<JCCase> switchBlockStatementGroups() {
  1902         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  1903         while (true) {
  1904             int pos = S.pos();
  1905             switch (S.token()) {
  1906             case CASE: {
  1907                 S.nextToken();
  1908                 JCExpression pat = parseExpression();
  1909                 accept(COLON);
  1910                 List<JCStatement> stats = blockStatements();
  1911                 JCCase c = F.at(pos).Case(pat, stats);
  1912                 if (stats.isEmpty())
  1913                     storeEnd(c, S.prevEndPos());
  1914                 cases.append(c);
  1915                 break;
  1917             case DEFAULT: {
  1918                 S.nextToken();
  1919                 accept(COLON);
  1920                 List<JCStatement> stats = blockStatements();
  1921                 JCCase c = F.at(pos).Case(null, stats);
  1922                 if (stats.isEmpty())
  1923                     storeEnd(c, S.prevEndPos());
  1924                 cases.append(c);
  1925                 break;
  1927             case RBRACE: case EOF:
  1928                 return cases.toList();
  1929             default:
  1930                 S.nextToken(); // to ensure progress
  1931                 syntaxError(pos, "expected3",
  1932                     CASE, DEFAULT, RBRACE);
  1937     /** MoreStatementExpressions = { COMMA StatementExpression }
  1938      */
  1939     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  1940                                                                     JCExpression first,
  1941                                                                     T stats) {
  1942         // This Exec is a "StatementExpression"; it subsumes no terminating token
  1943         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  1944         while (S.token() == COMMA) {
  1945             S.nextToken();
  1946             pos = S.pos();
  1947             JCExpression t = parseExpression();
  1948             // This Exec is a "StatementExpression"; it subsumes no terminating token
  1949             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  1951         return stats;
  1954     /** ForInit = StatementExpression MoreStatementExpressions
  1955      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  1956      */
  1957     List<JCStatement> forInit() {
  1958         ListBuffer<JCStatement> stats = lb();
  1959         int pos = S.pos();
  1960         if (S.token() == FINAL || S.token() == MONKEYS_AT) {
  1961             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  1962         } else {
  1963             JCExpression t = term(EXPR | TYPE);
  1964             if ((lastmode & TYPE) != 0 &&
  1965                 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
  1966                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  1967             else
  1968                 return moreStatementExpressions(pos, t, stats).toList();
  1972     /** ForUpdate = StatementExpression MoreStatementExpressions
  1973      */
  1974     List<JCExpressionStatement> forUpdate() {
  1975         return moreStatementExpressions(S.pos(),
  1976                                         parseExpression(),
  1977                                         new ListBuffer<JCExpressionStatement>()).toList();
  1980     /** AnnotationsOpt = { '@' Annotation }
  1981      */
  1982     List<JCAnnotation> annotationsOpt() {
  1983         if (S.token() != MONKEYS_AT) return List.nil(); // optimization
  1984         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  1985         while (S.token() == MONKEYS_AT) {
  1986             int pos = S.pos();
  1987             S.nextToken();
  1988             buf.append(annotation(pos));
  1990         return buf.toList();
  1993     /** ModifiersOpt = { Modifier }
  1994      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  1995      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  1996      *           | "@" Annotation
  1997      */
  1998     JCModifiers modifiersOpt() {
  1999         return modifiersOpt(null);
  2001     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2002         long flags;
  2003         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2004         int pos;
  2005         if (partial == null) {
  2006             flags = 0;
  2007             pos = S.pos();
  2008         } else {
  2009             flags = partial.flags;
  2010             annotations.appendList(partial.annotations);
  2011             pos = partial.pos;
  2013         if (S.deprecatedFlag()) {
  2014             flags |= Flags.DEPRECATED;
  2015             S.resetDeprecatedFlag();
  2017         int lastPos = Position.NOPOS;
  2018     loop:
  2019         while (true) {
  2020             long flag;
  2021             switch (S.token()) {
  2022             case PRIVATE     : flag = Flags.PRIVATE; break;
  2023             case PROTECTED   : flag = Flags.PROTECTED; break;
  2024             case PUBLIC      : flag = Flags.PUBLIC; break;
  2025             case STATIC      : flag = Flags.STATIC; break;
  2026             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2027             case FINAL       : flag = Flags.FINAL; break;
  2028             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2029             case NATIVE      : flag = Flags.NATIVE; break;
  2030             case VOLATILE    : flag = Flags.VOLATILE; break;
  2031             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2032             case STRICTFP    : flag = Flags.STRICTFP; break;
  2033             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2034             case ERROR       : flag = 0; S.nextToken(); break;
  2035             default: break loop;
  2037             if ((flags & flag) != 0) error(S.pos(), "repeated.modifier");
  2038             lastPos = S.pos();
  2039             S.nextToken();
  2040             if (flag == Flags.ANNOTATION) {
  2041                 checkAnnotations();
  2042                 if (S.token() != INTERFACE) {
  2043                     JCAnnotation ann = annotation(lastPos);
  2044                     // if first modifier is an annotation, set pos to annotation's.
  2045                     if (flags == 0 && annotations.isEmpty())
  2046                         pos = ann.pos;
  2047                     annotations.append(ann);
  2048                     lastPos = ann.pos;
  2049                     flag = 0;
  2052             flags |= flag;
  2054         switch (S.token()) {
  2055         case ENUM: flags |= Flags.ENUM; break;
  2056         case INTERFACE: flags |= Flags.INTERFACE; break;
  2057         default: break;
  2060         /* A modifiers tree with no modifier tokens or annotations
  2061          * has no text position. */
  2062         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2063             pos = Position.NOPOS;
  2065         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2066         if (pos != Position.NOPOS)
  2067             storeEnd(mods, S.prevEndPos());
  2068         return mods;
  2071     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2072      * @param pos position of "@" token
  2073      */
  2074     JCAnnotation annotation(int pos) {
  2075         // accept(AT); // AT consumed by caller
  2076         checkAnnotations();
  2077         JCTree ident = qualident();
  2078         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2079         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  2080         storeEnd(ann, S.prevEndPos());
  2081         return ann;
  2084     List<JCExpression> annotationFieldValuesOpt() {
  2085         return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2088     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2089     List<JCExpression> annotationFieldValues() {
  2090         accept(LPAREN);
  2091         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2092         if (S.token() != RPAREN) {
  2093             buf.append(annotationFieldValue());
  2094             while (S.token() == COMMA) {
  2095                 S.nextToken();
  2096                 buf.append(annotationFieldValue());
  2099         accept(RPAREN);
  2100         return buf.toList();
  2103     /** AnnotationFieldValue    = AnnotationValue
  2104      *                          | Identifier "=" AnnotationValue
  2105      */
  2106     JCExpression annotationFieldValue() {
  2107         if (S.token() == IDENTIFIER) {
  2108             mode = EXPR;
  2109             JCExpression t1 = term1();
  2110             if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
  2111                 int pos = S.pos();
  2112                 accept(EQ);
  2113                 JCExpression v = annotationValue();
  2114                 return toP(F.at(pos).Assign(t1, v));
  2115             } else {
  2116                 return t1;
  2119         return annotationValue();
  2122     /* AnnotationValue          = ConditionalExpression
  2123      *                          | Annotation
  2124      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2125      */
  2126     JCExpression annotationValue() {
  2127         int pos;
  2128         switch (S.token()) {
  2129         case MONKEYS_AT:
  2130             pos = S.pos();
  2131             S.nextToken();
  2132             return annotation(pos);
  2133         case LBRACE:
  2134             pos = S.pos();
  2135             accept(LBRACE);
  2136             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2137             if (S.token() != RBRACE) {
  2138                 buf.append(annotationValue());
  2139                 while (S.token() == COMMA) {
  2140                     S.nextToken();
  2141                     if (S.token() == RBRACE) break;
  2142                     buf.append(annotationValue());
  2145             accept(RBRACE);
  2146             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2147         default:
  2148             mode = EXPR;
  2149             return term1();
  2153     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2154      */
  2155     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2156                                                                          JCExpression type,
  2157                                                                          T vdefs)
  2159         return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
  2162     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2163      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2165      *  @param reqInit  Is an initializer always required?
  2166      *  @param dc       The documentation comment for the variable declarations, or null.
  2167      */
  2168     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2169                                                                      JCModifiers mods,
  2170                                                                      JCExpression type,
  2171                                                                      Name name,
  2172                                                                      boolean reqInit,
  2173                                                                      String dc,
  2174                                                                      T vdefs)
  2176         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2177         while (S.token() == COMMA) {
  2178             // All but last of multiple declarators subsume a comma
  2179             storeEnd((JCTree)vdefs.elems.last(), S.endPos());
  2180             S.nextToken();
  2181             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2183         return vdefs;
  2186     /** VariableDeclarator = Ident VariableDeclaratorRest
  2187      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2188      */
  2189     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
  2190         return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
  2193     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2194      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2196      *  @param reqInit  Is an initializer always required?
  2197      *  @param dc       The documentation comment for the variable declarations, or null.
  2198      */
  2199     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2200                                   boolean reqInit, String dc) {
  2201         type = bracketsOpt(type);
  2202         JCExpression init = null;
  2203         if (S.token() == EQ) {
  2204             S.nextToken();
  2205             init = variableInitializer();
  2207         else if (reqInit) syntaxError(S.pos(), "expected", EQ);
  2208         JCVariableDecl result =
  2209             toP(F.at(pos).VarDef(mods, name, type, init));
  2210         attach(result, dc);
  2211         return result;
  2214     /** VariableDeclaratorId = Ident BracketsOpt
  2215      */
  2216     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2217         int pos = S.pos();
  2218         Name name = ident();
  2219         if ((mods.flags & Flags.VARARGS) != 0 &&
  2220                 S.token() == LBRACKET) {
  2221             log.error(S.pos(), "varargs.and.old.array.syntax");
  2223         type = bracketsOpt(type);
  2224         return toP(F.at(pos).VarDef(mods, name, type, null));
  2227     /** Resources = Resource { ";" Resources }
  2228      */
  2229     List<JCTree> resources() {
  2230         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2231         defs.append(resource());
  2232         while (S.token() == SEMI) {
  2233             // All but last of multiple declarators must subsume a semicolon
  2234             storeEnd(defs.elems.last(), S.endPos());
  2235             int semiColonPos = S.pos();
  2236             S.nextToken();
  2237             if (S.token() == RPAREN) { // Optional trailing semicolon
  2238                                        // after last resource
  2239                 break;
  2241             defs.append(resource());
  2243         return defs.toList();
  2246     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  2247      */
  2248     protected JCTree resource() {
  2249         JCModifiers optFinal = optFinal(Flags.FINAL);
  2250         JCExpression type = parseType();
  2251         int pos = S.pos();
  2252         Name ident = ident();
  2253         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  2256     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2257      */
  2258     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2259         int pos = S.pos();
  2260         JCExpression pid = null;
  2261         String dc = S.docComment();
  2262         JCModifiers mods = null;
  2263         List<JCAnnotation> packageAnnotations = List.nil();
  2264         if (S.token() == MONKEYS_AT)
  2265             mods = modifiersOpt();
  2267         if (S.token() == PACKAGE) {
  2268             if (mods != null) {
  2269                 checkNoMods(mods.flags);
  2270                 packageAnnotations = mods.annotations;
  2271                 mods = null;
  2273             S.nextToken();
  2274             pid = qualident();
  2275             accept(SEMI);
  2277         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2278         boolean checkForImports = true;
  2279         while (S.token() != EOF) {
  2280             if (S.pos() <= errorEndPos) {
  2281                 // error recovery
  2282                 skip(checkForImports, false, false, false);
  2283                 if (S.token() == EOF)
  2284                     break;
  2286             if (checkForImports && mods == null && S.token() == IMPORT) {
  2287                 defs.append(importDeclaration());
  2288             } else {
  2289                 JCTree def = typeDeclaration(mods);
  2290                 if (keepDocComments && dc != null && docComments.get(def) == dc) {
  2291                     // If the first type declaration has consumed the first doc
  2292                     // comment, then don't use it for the top level comment as well.
  2293                     dc = null;
  2295                 if (def instanceof JCExpressionStatement)
  2296                     def = ((JCExpressionStatement)def).expr;
  2297                 defs.append(def);
  2298                 if (def instanceof JCClassDecl)
  2299                     checkForImports = false;
  2300                 mods = null;
  2303         JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
  2304         attach(toplevel, dc);
  2305         if (defs.elems.isEmpty())
  2306             storeEnd(toplevel, S.prevEndPos());
  2307         if (keepDocComments)
  2308             toplevel.docComments = docComments;
  2309         if (keepLineMap)
  2310             toplevel.lineMap = S.getLineMap();
  2311         return toplevel;
  2314     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2315      */
  2316     JCTree importDeclaration() {
  2317         int pos = S.pos();
  2318         S.nextToken();
  2319         boolean importStatic = false;
  2320         if (S.token() == STATIC) {
  2321             checkStaticImports();
  2322             importStatic = true;
  2323             S.nextToken();
  2325         JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
  2326         do {
  2327             int pos1 = S.pos();
  2328             accept(DOT);
  2329             if (S.token() == STAR) {
  2330                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2331                 S.nextToken();
  2332                 break;
  2333             } else {
  2334                 pid = toP(F.at(pos1).Select(pid, ident()));
  2336         } while (S.token() == DOT);
  2337         accept(SEMI);
  2338         return toP(F.at(pos).Import(pid, importStatic));
  2341     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2342      *                  | ";"
  2343      */
  2344     JCTree typeDeclaration(JCModifiers mods) {
  2345         int pos = S.pos();
  2346         if (mods == null && S.token() == SEMI) {
  2347             S.nextToken();
  2348             return toP(F.at(pos).Skip());
  2349         } else {
  2350             String dc = S.docComment();
  2351             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
  2355     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2356      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2357      *  @param mods     Any modifiers starting the class or interface declaration
  2358      *  @param dc       The documentation comment for the class, or null.
  2359      */
  2360     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
  2361         if (S.token() == CLASS) {
  2362             return classDeclaration(mods, dc);
  2363         } else if (S.token() == INTERFACE) {
  2364             return interfaceDeclaration(mods, dc);
  2365         } else if (allowEnums) {
  2366             if (S.token() == ENUM) {
  2367                 return enumDeclaration(mods, dc);
  2368             } else {
  2369                 int pos = S.pos();
  2370                 List<JCTree> errs;
  2371                 if (S.token() == IDENTIFIER) {
  2372                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2373                     setErrorEndPos(S.pos());
  2374                 } else {
  2375                     errs = List.<JCTree>of(mods);
  2377                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2378                                               CLASS, INTERFACE, ENUM)));
  2380         } else {
  2381             if (S.token() == ENUM) {
  2382                 error(S.pos(), "enums.not.supported.in.source", source.name);
  2383                 allowEnums = true;
  2384                 return enumDeclaration(mods, dc);
  2386             int pos = S.pos();
  2387             List<JCTree> errs;
  2388             if (S.token() == IDENTIFIER) {
  2389                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2390                 setErrorEndPos(S.pos());
  2391             } else {
  2392                 errs = List.<JCTree>of(mods);
  2394             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2395                                           CLASS, INTERFACE)));
  2399     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2400      *                     [IMPLEMENTS TypeList] ClassBody
  2401      *  @param mods    The modifiers starting the class declaration
  2402      *  @param dc       The documentation comment for the class, or null.
  2403      */
  2404     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
  2405         int pos = S.pos();
  2406         accept(CLASS);
  2407         Name name = ident();
  2409         List<JCTypeParameter> typarams = typeParametersOpt();
  2411         JCExpression extending = null;
  2412         if (S.token() == EXTENDS) {
  2413             S.nextToken();
  2414             extending = parseType();
  2416         List<JCExpression> implementing = List.nil();
  2417         if (S.token() == IMPLEMENTS) {
  2418             S.nextToken();
  2419             implementing = typeList();
  2421         List<JCTree> defs = classOrInterfaceBody(name, false);
  2422         JCClassDecl result = toP(F.at(pos).ClassDef(
  2423             mods, name, typarams, extending, implementing, defs));
  2424         attach(result, dc);
  2425         return result;
  2428     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2429      *                         [EXTENDS TypeList] InterfaceBody
  2430      *  @param mods    The modifiers starting the interface declaration
  2431      *  @param dc       The documentation comment for the interface, or null.
  2432      */
  2433     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
  2434         int pos = S.pos();
  2435         accept(INTERFACE);
  2436         Name name = ident();
  2438         List<JCTypeParameter> typarams = typeParametersOpt();
  2440         List<JCExpression> extending = List.nil();
  2441         if (S.token() == EXTENDS) {
  2442             S.nextToken();
  2443             extending = typeList();
  2445         List<JCTree> defs = classOrInterfaceBody(name, true);
  2446         JCClassDecl result = toP(F.at(pos).ClassDef(
  2447             mods, name, typarams, null, extending, defs));
  2448         attach(result, dc);
  2449         return result;
  2452     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2453      *  @param mods    The modifiers starting the enum declaration
  2454      *  @param dc       The documentation comment for the enum, or null.
  2455      */
  2456     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
  2457         int pos = S.pos();
  2458         accept(ENUM);
  2459         Name name = ident();
  2461         List<JCExpression> implementing = List.nil();
  2462         if (S.token() == IMPLEMENTS) {
  2463             S.nextToken();
  2464             implementing = typeList();
  2467         List<JCTree> defs = enumBody(name);
  2468         mods.flags |= Flags.ENUM;
  2469         JCClassDecl result = toP(F.at(pos).
  2470             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2471                 null, implementing, defs));
  2472         attach(result, dc);
  2473         return result;
  2476     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2477      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2478      */
  2479     List<JCTree> enumBody(Name enumName) {
  2480         accept(LBRACE);
  2481         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2482         if (S.token() == COMMA) {
  2483             S.nextToken();
  2484         } else if (S.token() != RBRACE && S.token() != SEMI) {
  2485             defs.append(enumeratorDeclaration(enumName));
  2486             while (S.token() == COMMA) {
  2487                 S.nextToken();
  2488                 if (S.token() == RBRACE || S.token() == SEMI) break;
  2489                 defs.append(enumeratorDeclaration(enumName));
  2491             if (S.token() != SEMI && S.token() != RBRACE) {
  2492                 defs.append(syntaxError(S.pos(), "expected3",
  2493                                 COMMA, RBRACE, SEMI));
  2494                 S.nextToken();
  2497         if (S.token() == SEMI) {
  2498             S.nextToken();
  2499             while (S.token() != RBRACE && S.token() != EOF) {
  2500                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2501                                                                 false));
  2502                 if (S.pos() <= errorEndPos) {
  2503                     // error recovery
  2504                    skip(false, true, true, false);
  2508         accept(RBRACE);
  2509         return defs.toList();
  2512     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2513      */
  2514     JCTree enumeratorDeclaration(Name enumName) {
  2515         String dc = S.docComment();
  2516         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2517         if (S.deprecatedFlag()) {
  2518             flags |= Flags.DEPRECATED;
  2519             S.resetDeprecatedFlag();
  2521         int pos = S.pos();
  2522         List<JCAnnotation> annotations = annotationsOpt();
  2523         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2524         List<JCExpression> typeArgs = typeArgumentsOpt();
  2525         int identPos = S.pos();
  2526         Name name = ident();
  2527         int createPos = S.pos();
  2528         List<JCExpression> args = (S.token() == LPAREN)
  2529             ? arguments() : List.<JCExpression>nil();
  2530         JCClassDecl body = null;
  2531         if (S.token() == LBRACE) {
  2532             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2533             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2534             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2536         if (args.isEmpty() && body == null)
  2537             createPos = identPos;
  2538         JCIdent ident = F.at(identPos).Ident(enumName);
  2539         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2540         if (createPos != identPos)
  2541             storeEnd(create, S.prevEndPos());
  2542         ident = F.at(identPos).Ident(enumName);
  2543         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2544         attach(result, dc);
  2545         return result;
  2548     /** TypeList = Type {"," Type}
  2549      */
  2550     List<JCExpression> typeList() {
  2551         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2552         ts.append(parseType());
  2553         while (S.token() == COMMA) {
  2554             S.nextToken();
  2555             ts.append(parseType());
  2557         return ts.toList();
  2560     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2561      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2562      */
  2563     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2564         accept(LBRACE);
  2565         if (S.pos() <= errorEndPos) {
  2566             // error recovery
  2567             skip(false, true, false, false);
  2568             if (S.token() == LBRACE)
  2569                 S.nextToken();
  2571         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2572         while (S.token() != RBRACE && S.token() != EOF) {
  2573             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2574             if (S.pos() <= errorEndPos) {
  2575                // error recovery
  2576                skip(false, true, true, false);
  2579         accept(RBRACE);
  2580         return defs.toList();
  2583     /** ClassBodyDeclaration =
  2584      *      ";"
  2585      *    | [STATIC] Block
  2586      *    | ModifiersOpt
  2587      *      ( Type Ident
  2588      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2589      *      | VOID Ident MethodDeclaratorRest
  2590      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2591      *      | Ident ConstructorDeclaratorRest
  2592      *      | TypeParameters Ident ConstructorDeclaratorRest
  2593      *      | ClassOrInterfaceOrEnumDeclaration
  2594      *      )
  2595      *  InterfaceBodyDeclaration =
  2596      *      ";"
  2597      *    | ModifiersOpt Type Ident
  2598      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2599      */
  2600     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2601         if (S.token() == SEMI) {
  2602             S.nextToken();
  2603             return List.<JCTree>nil();
  2604         } else {
  2605             String dc = S.docComment();
  2606             int pos = S.pos();
  2607             JCModifiers mods = modifiersOpt();
  2608             if (S.token() == CLASS ||
  2609                 S.token() == INTERFACE ||
  2610                 allowEnums && S.token() == ENUM) {
  2611                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2612             } else if (S.token() == LBRACE && !isInterface &&
  2613                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2614                        mods.annotations.isEmpty()) {
  2615                 return List.<JCTree>of(block(pos, mods.flags));
  2616             } else {
  2617                 pos = S.pos();
  2618                 List<JCTypeParameter> typarams = typeParametersOpt();
  2619                 // if there are type parameters but no modifiers, save the start
  2620                 // position of the method in the modifiers.
  2621                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  2622                     mods.pos = pos;
  2623                     storeEnd(mods, pos);
  2625                 Name name = S.name();
  2626                 pos = S.pos();
  2627                 JCExpression type;
  2628                 boolean isVoid = S.token() == VOID;
  2629                 if (isVoid) {
  2630                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  2631                     S.nextToken();
  2632                 } else {
  2633                     type = parseType();
  2635                 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
  2636                     if (isInterface || name != className)
  2637                         error(pos, "invalid.meth.decl.ret.type.req");
  2638                     return List.of(methodDeclaratorRest(
  2639                         pos, mods, null, names.init, typarams,
  2640                         isInterface, true, dc));
  2641                 } else {
  2642                     pos = S.pos();
  2643                     name = ident();
  2644                     if (S.token() == LPAREN) {
  2645                         return List.of(methodDeclaratorRest(
  2646                             pos, mods, type, name, typarams,
  2647                             isInterface, isVoid, dc));
  2648                     } else if (!isVoid && typarams.isEmpty()) {
  2649                         List<JCTree> defs =
  2650                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2651                                                     new ListBuffer<JCTree>()).toList();
  2652                         storeEnd(defs.last(), S.endPos());
  2653                         accept(SEMI);
  2654                         return defs;
  2655                     } else {
  2656                         pos = S.pos();
  2657                         List<JCTree> err = isVoid
  2658                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2659                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2660                             : null;
  2661                         return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
  2668     /** MethodDeclaratorRest =
  2669      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2670      *  VoidMethodDeclaratorRest =
  2671      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  2672      *  InterfaceMethodDeclaratorRest =
  2673      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  2674      *  VoidInterfaceMethodDeclaratorRest =
  2675      *      FormalParameters [THROWS TypeList] ";"
  2676      *  ConstructorDeclaratorRest =
  2677      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  2678      */
  2679     JCTree methodDeclaratorRest(int pos,
  2680                               JCModifiers mods,
  2681                               JCExpression type,
  2682                               Name name,
  2683                               List<JCTypeParameter> typarams,
  2684                               boolean isInterface, boolean isVoid,
  2685                               String dc) {
  2686         List<JCVariableDecl> params = formalParameters();
  2687         if (!isVoid) type = bracketsOpt(type);
  2688         List<JCExpression> thrown = List.nil();
  2689         if (S.token() == THROWS) {
  2690             S.nextToken();
  2691             thrown = qualidentList();
  2693         JCBlock body = null;
  2694         JCExpression defaultValue;
  2695         if (S.token() == LBRACE) {
  2696             body = block();
  2697             defaultValue = null;
  2698         } else {
  2699             if (S.token() == DEFAULT) {
  2700                 accept(DEFAULT);
  2701                 defaultValue = annotationValue();
  2702             } else {
  2703                 defaultValue = null;
  2705             accept(SEMI);
  2706             if (S.pos() <= errorEndPos) {
  2707                 // error recovery
  2708                 skip(false, true, false, false);
  2709                 if (S.token() == LBRACE) {
  2710                     body = block();
  2715         JCMethodDecl result =
  2716             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2717                                     params, thrown,
  2718                                     body, defaultValue));
  2719         attach(result, dc);
  2720         return result;
  2723     /** QualidentList = Qualident {"," Qualident}
  2724      */
  2725     List<JCExpression> qualidentList() {
  2726         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2727         ts.append(qualident());
  2728         while (S.token() == COMMA) {
  2729             S.nextToken();
  2730             ts.append(qualident());
  2732         return ts.toList();
  2735     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  2736      */
  2737     List<JCTypeParameter> typeParametersOpt() {
  2738         if (S.token() == LT) {
  2739             checkGenerics();
  2740             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  2741             S.nextToken();
  2742             typarams.append(typeParameter());
  2743             while (S.token() == COMMA) {
  2744                 S.nextToken();
  2745                 typarams.append(typeParameter());
  2747             accept(GT);
  2748             return typarams.toList();
  2749         } else {
  2750             return List.nil();
  2754     /** TypeParameter = TypeVariable [TypeParameterBound]
  2755      *  TypeParameterBound = EXTENDS Type {"&" Type}
  2756      *  TypeVariable = Ident
  2757      */
  2758     JCTypeParameter typeParameter() {
  2759         int pos = S.pos();
  2760         Name name = ident();
  2761         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  2762         if (S.token() == EXTENDS) {
  2763             S.nextToken();
  2764             bounds.append(parseType());
  2765             while (S.token() == AMP) {
  2766                 S.nextToken();
  2767                 bounds.append(parseType());
  2770         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  2773     /** FormalParameters = "(" [ FormalParameterList ] ")"
  2774      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  2775      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  2776      */
  2777     List<JCVariableDecl> formalParameters() {
  2778         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  2779         JCVariableDecl lastParam = null;
  2780         accept(LPAREN);
  2781         if (S.token() != RPAREN) {
  2782             params.append(lastParam = formalParameter());
  2783             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
  2784                 S.nextToken();
  2785                 params.append(lastParam = formalParameter());
  2788         accept(RPAREN);
  2789         return params.toList();
  2792     JCModifiers optFinal(long flags) {
  2793         JCModifiers mods = modifiersOpt();
  2794         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  2795         mods.flags |= flags;
  2796         return mods;
  2799     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  2800      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  2801      */
  2802     protected JCVariableDecl formalParameter() {
  2803         JCModifiers mods = optFinal(Flags.PARAMETER);
  2804         JCExpression type = parseType();
  2805         if (S.token() == ELLIPSIS) {
  2806             checkVarargs();
  2807             mods.flags |= Flags.VARARGS;
  2808             type = to(F.at(S.pos()).TypeArray(type));
  2809             S.nextToken();
  2811         return variableDeclaratorId(mods, type);
  2814 /* ---------- auxiliary methods -------------- */
  2816     void error(int pos, String key, Object ... args) {
  2817         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  2820     void error(DiagnosticPosition pos, String key, Object ... args) {
  2821         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  2824     void warning(int pos, String key, Object ... args) {
  2825         log.warning(pos, key, args);
  2828     /** Check that given tree is a legal expression statement.
  2829      */
  2830     protected JCExpression checkExprStat(JCExpression t) {
  2831         switch(t.getTag()) {
  2832         case JCTree.PREINC: case JCTree.PREDEC:
  2833         case JCTree.POSTINC: case JCTree.POSTDEC:
  2834         case JCTree.ASSIGN:
  2835         case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
  2836         case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
  2837         case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
  2838         case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
  2839         case JCTree.APPLY: case JCTree.NEWCLASS:
  2840         case JCTree.ERRONEOUS:
  2841             return t;
  2842         default:
  2843             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  2844             error(ret, "not.stmt");
  2845             return ret;
  2849     /** Return precedence of operator represented by token,
  2850      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  2851      */
  2852     static int prec(Token token) {
  2853         int oc = optag(token);
  2854         return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
  2857     /**
  2858      * Return the lesser of two positions, making allowance for either one
  2859      * being unset.
  2860      */
  2861     static int earlier(int pos1, int pos2) {
  2862         if (pos1 == Position.NOPOS)
  2863             return pos2;
  2864         if (pos2 == Position.NOPOS)
  2865             return pos1;
  2866         return (pos1 < pos2 ? pos1 : pos2);
  2869     /** Return operation tag of binary operator represented by token,
  2870      *  -1 if token is not a binary operator.
  2871      */
  2872     static int optag(Token token) {
  2873         switch (token) {
  2874         case BARBAR:
  2875             return JCTree.OR;
  2876         case AMPAMP:
  2877             return JCTree.AND;
  2878         case BAR:
  2879             return JCTree.BITOR;
  2880         case BAREQ:
  2881             return JCTree.BITOR_ASG;
  2882         case CARET:
  2883             return JCTree.BITXOR;
  2884         case CARETEQ:
  2885             return JCTree.BITXOR_ASG;
  2886         case AMP:
  2887             return JCTree.BITAND;
  2888         case AMPEQ:
  2889             return JCTree.BITAND_ASG;
  2890         case EQEQ:
  2891             return JCTree.EQ;
  2892         case BANGEQ:
  2893             return JCTree.NE;
  2894         case LT:
  2895             return JCTree.LT;
  2896         case GT:
  2897             return JCTree.GT;
  2898         case LTEQ:
  2899             return JCTree.LE;
  2900         case GTEQ:
  2901             return JCTree.GE;
  2902         case LTLT:
  2903             return JCTree.SL;
  2904         case LTLTEQ:
  2905             return JCTree.SL_ASG;
  2906         case GTGT:
  2907             return JCTree.SR;
  2908         case GTGTEQ:
  2909             return JCTree.SR_ASG;
  2910         case GTGTGT:
  2911             return JCTree.USR;
  2912         case GTGTGTEQ:
  2913             return JCTree.USR_ASG;
  2914         case PLUS:
  2915             return JCTree.PLUS;
  2916         case PLUSEQ:
  2917             return JCTree.PLUS_ASG;
  2918         case SUB:
  2919             return JCTree.MINUS;
  2920         case SUBEQ:
  2921             return JCTree.MINUS_ASG;
  2922         case STAR:
  2923             return JCTree.MUL;
  2924         case STAREQ:
  2925             return JCTree.MUL_ASG;
  2926         case SLASH:
  2927             return JCTree.DIV;
  2928         case SLASHEQ:
  2929             return JCTree.DIV_ASG;
  2930         case PERCENT:
  2931             return JCTree.MOD;
  2932         case PERCENTEQ:
  2933             return JCTree.MOD_ASG;
  2934         case INSTANCEOF:
  2935             return JCTree.TYPETEST;
  2936         default:
  2937             return -1;
  2941     /** Return operation tag of unary operator represented by token,
  2942      *  -1 if token is not a binary operator.
  2943      */
  2944     static int unoptag(Token token) {
  2945         switch (token) {
  2946         case PLUS:
  2947             return JCTree.POS;
  2948         case SUB:
  2949             return JCTree.NEG;
  2950         case BANG:
  2951             return JCTree.NOT;
  2952         case TILDE:
  2953             return JCTree.COMPL;
  2954         case PLUSPLUS:
  2955             return JCTree.PREINC;
  2956         case SUBSUB:
  2957             return JCTree.PREDEC;
  2958         default:
  2959             return -1;
  2963     /** Return type tag of basic type represented by token,
  2964      *  -1 if token is not a basic type identifier.
  2965      */
  2966     static int typetag(Token token) {
  2967         switch (token) {
  2968         case BYTE:
  2969             return TypeTags.BYTE;
  2970         case CHAR:
  2971             return TypeTags.CHAR;
  2972         case SHORT:
  2973             return TypeTags.SHORT;
  2974         case INT:
  2975             return TypeTags.INT;
  2976         case LONG:
  2977             return TypeTags.LONG;
  2978         case FLOAT:
  2979             return TypeTags.FLOAT;
  2980         case DOUBLE:
  2981             return TypeTags.DOUBLE;
  2982         case BOOLEAN:
  2983             return TypeTags.BOOLEAN;
  2984         default:
  2985             return -1;
  2989     void checkGenerics() {
  2990         if (!allowGenerics) {
  2991             error(S.pos(), "generics.not.supported.in.source", source.name);
  2992             allowGenerics = true;
  2995     void checkVarargs() {
  2996         if (!allowVarargs) {
  2997             error(S.pos(), "varargs.not.supported.in.source", source.name);
  2998             allowVarargs = true;
  3001     void checkForeach() {
  3002         if (!allowForeach) {
  3003             error(S.pos(), "foreach.not.supported.in.source", source.name);
  3004             allowForeach = true;
  3007     void checkStaticImports() {
  3008         if (!allowStaticImport) {
  3009             error(S.pos(), "static.import.not.supported.in.source", source.name);
  3010             allowStaticImport = true;
  3013     void checkAnnotations() {
  3014         if (!allowAnnotations) {
  3015             error(S.pos(), "annotations.not.supported.in.source", source.name);
  3016             allowAnnotations = true;
  3019     void checkDiamond() {
  3020         if (!allowDiamond) {
  3021             error(S.pos(), "diamond.not.supported.in.source", source.name);
  3022             allowDiamond = true;
  3025     void checkMulticatch() {
  3026         if (!allowMulticatch) {
  3027             error(S.pos(), "multicatch.not.supported.in.source", source.name);
  3028             allowMulticatch = true;
  3031     void checkTryWithResources() {
  3032         if (!allowTWR) {
  3033             error(S.pos(), "try.with.resources.not.supported.in.source", source.name);
  3034             allowTWR = true;

mercurial