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

Tue, 08 Nov 2011 11:51:05 -0800

author
jjg
date
Tue, 08 Nov 2011 11:51:05 -0800
changeset 1127
ca49d50318dc
parent 1125
56830d5cb5bb
child 1138
7375d4979bd3
permissions
-rw-r--r--

6921494: provide way to print javac tree tag values
Reviewed-by: jjg, mcimadamore
Contributed-by: vicenterz@yahoo.es

     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.parser.Tokens.*;
    32 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
    33 import com.sun.tools.javac.tree.*;
    34 import com.sun.tools.javac.tree.JCTree.*;
    35 import com.sun.tools.javac.util.*;
    36 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
    37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    38 import com.sun.tools.javac.util.List;
    40 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
    41 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
    42 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
    43 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
    44 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
    45 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
    46 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
    47 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
    48 import static com.sun.tools.javac.util.ListBuffer.lb;
    49 import static com.sun.tools.javac.tree.JCTree.Tag.*;
    51 /** The parser maps a token sequence into an abstract syntax
    52  *  tree. It operates by recursive descent, with code derived
    53  *  systematically from an LL(1) grammar. For efficiency reasons, an
    54  *  operator precedence scheme is used for parsing binary operation
    55  *  expressions.
    56  *
    57  *  <p><b>This is NOT part of any supported API.
    58  *  If you write code that depends on this, you do so at your own risk.
    59  *  This code and its internal interfaces are subject to change or
    60  *  deletion without notice.</b>
    61  */
    62 public class JavacParser implements Parser {
    64     /** The number of precedence levels of infix operators.
    65      */
    66     private static final int infixPrecedenceLevels = 10;
    68     /** The scanner used for lexical analysis.
    69      */
    70     protected Lexer S;
    72     /** The factory to be used for abstract syntax tree construction.
    73      */
    74     protected TreeMaker F;
    76     /** The log to be used for error diagnostics.
    77      */
    78     private Log log;
    80     /** The Source language setting. */
    81     private Source source;
    83     /** The name table. */
    84     private Names names;
    86     /** Construct a parser from a given scanner, tree factory and log.
    87      */
    88     protected JavacParser(ParserFactory fac,
    89                      Lexer S,
    90                      boolean keepDocComments,
    91                      boolean keepLineMap) {
    92         this.S = S;
    93         nextToken(); // prime the pump
    94         this.F = fac.F;
    95         this.log = fac.log;
    96         this.names = fac.names;
    97         this.source = fac.source;
    98         this.allowGenerics = source.allowGenerics();
    99         this.allowVarargs = source.allowVarargs();
   100         this.allowAsserts = source.allowAsserts();
   101         this.allowEnums = source.allowEnums();
   102         this.allowForeach = source.allowForeach();
   103         this.allowStaticImport = source.allowStaticImport();
   104         this.allowAnnotations = source.allowAnnotations();
   105         this.allowTWR = source.allowTryWithResources();
   106         this.allowDiamond = source.allowDiamond();
   107         this.allowMulticatch = source.allowMulticatch();
   108         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
   109         this.keepDocComments = keepDocComments;
   110         docComments = keepDocComments ? new HashMap<JCTree,String>() : null;
   111         this.keepLineMap = keepLineMap;
   112         this.errorTree = F.Erroneous();
   113     }
   115     /** Switch: Should generics be recognized?
   116      */
   117     boolean allowGenerics;
   119     /** Switch: Should diamond operator be recognized?
   120      */
   121     boolean allowDiamond;
   123     /** Switch: Should multicatch clause be accepted?
   124      */
   125     boolean allowMulticatch;
   127     /** Switch: Should varargs be recognized?
   128      */
   129     boolean allowVarargs;
   131     /** Switch: should we recognize assert statements, or just give a warning?
   132      */
   133     boolean allowAsserts;
   135     /** Switch: should we recognize enums, or just give a warning?
   136      */
   137     boolean allowEnums;
   139     /** Switch: should we recognize foreach?
   140      */
   141     boolean allowForeach;
   143     /** Switch: should we recognize foreach?
   144      */
   145     boolean allowStaticImport;
   147     /** Switch: should we recognize annotations?
   148      */
   149     boolean allowAnnotations;
   151     /** Switch: should we recognize try-with-resources?
   152      */
   153     boolean allowTWR;
   155     /** Switch: should we fold strings?
   156      */
   157     boolean allowStringFolding;
   159     /** Switch: should we keep docComments?
   160      */
   161     boolean keepDocComments;
   163     /** Switch: should we keep line table?
   164      */
   165     boolean keepLineMap;
   167     /** When terms are parsed, the mode determines which is expected:
   168      *     mode = EXPR        : an expression
   169      *     mode = TYPE        : a type
   170      *     mode = NOPARAMS    : no parameters allowed for type
   171      *     mode = TYPEARG     : type argument
   172      */
   173     static final int EXPR = 0x1;
   174     static final int TYPE = 0x2;
   175     static final int NOPARAMS = 0x4;
   176     static final int TYPEARG = 0x8;
   177     static final int DIAMOND = 0x10;
   179     /** The current mode.
   180      */
   181     private int mode = 0;
   183     /** The mode of the term that was parsed last.
   184      */
   185     private int lastmode = 0;
   187     /* ---------- token management -------------- */
   189     protected Token token;
   191     protected void nextToken() {
   192         S.nextToken();
   193         token = S.token();
   194     }
   196     /* ---------- error recovery -------------- */
   198     private JCErroneous errorTree;
   200     /** Skip forward until a suitable stop token is found.
   201      */
   202     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   203          while (true) {
   204              switch (token.kind) {
   205                 case SEMI:
   206                     nextToken();
   207                     return;
   208                 case PUBLIC:
   209                 case FINAL:
   210                 case ABSTRACT:
   211                 case MONKEYS_AT:
   212                 case EOF:
   213                 case CLASS:
   214                 case INTERFACE:
   215                 case ENUM:
   216                     return;
   217                 case IMPORT:
   218                     if (stopAtImport)
   219                         return;
   220                     break;
   221                 case LBRACE:
   222                 case RBRACE:
   223                 case PRIVATE:
   224                 case PROTECTED:
   225                 case STATIC:
   226                 case TRANSIENT:
   227                 case NATIVE:
   228                 case VOLATILE:
   229                 case SYNCHRONIZED:
   230                 case STRICTFP:
   231                 case LT:
   232                 case BYTE:
   233                 case SHORT:
   234                 case CHAR:
   235                 case INT:
   236                 case LONG:
   237                 case FLOAT:
   238                 case DOUBLE:
   239                 case BOOLEAN:
   240                 case VOID:
   241                     if (stopAtMemberDecl)
   242                         return;
   243                     break;
   244                 case IDENTIFIER:
   245                    if (stopAtIdentifier)
   246                         return;
   247                     break;
   248                 case CASE:
   249                 case DEFAULT:
   250                 case IF:
   251                 case FOR:
   252                 case WHILE:
   253                 case DO:
   254                 case TRY:
   255                 case SWITCH:
   256                 case RETURN:
   257                 case THROW:
   258                 case BREAK:
   259                 case CONTINUE:
   260                 case ELSE:
   261                 case FINALLY:
   262                 case CATCH:
   263                     if (stopAtStatement)
   264                         return;
   265                     break;
   266             }
   267             nextToken();
   268         }
   269     }
   271     private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
   272         return syntaxError(pos, List.<JCTree>nil(), key, args);
   273     }
   275     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
   276         setErrorEndPos(pos);
   277         JCErroneous err = F.at(pos).Erroneous(errs);
   278         reportSyntaxError(err, key, (Object[])args);
   279         if (errs != null) {
   280             JCTree last = errs.last();
   281             if (last != null)
   282                 storeEnd(last, pos);
   283         }
   284         return toP(err);
   285     }
   287     private int errorPos = Position.NOPOS;
   289     /**
   290      * Report a syntax using the given the position parameter and arguments,
   291      * unless one was already reported at the same position.
   292      */
   293     private void reportSyntaxError(int pos, String key, Object... args) {
   294         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   295         reportSyntaxError(diag, key, args);
   296     }
   298     /**
   299      * Report a syntax error using the given DiagnosticPosition object and
   300      * arguments, unless one was already reported at the same position.
   301      */
   302     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   303         int pos = diagPos.getPreferredPosition();
   304         if (pos > S.errPos() || pos == Position.NOPOS) {
   305             if (token.kind == EOF) {
   306                 error(diagPos, "premature.eof");
   307             } else {
   308                 error(diagPos, key, args);
   309             }
   310         }
   311         S.errPos(pos);
   312         if (token.pos == errorPos)
   313             nextToken(); // guarantee progress
   314         errorPos = token.pos;
   315     }
   318     /** Generate a syntax error at current position unless one was already
   319      *  reported at the same position.
   320      */
   321     private JCErroneous syntaxError(String key) {
   322         return syntaxError(token.pos, key);
   323     }
   325     /** Generate a syntax error at current position unless one was
   326      *  already reported at the same position.
   327      */
   328     private JCErroneous syntaxError(String key, TokenKind arg) {
   329         return syntaxError(token.pos, key, arg);
   330     }
   332     /** If next input token matches given token, skip it, otherwise report
   333      *  an error.
   334      */
   335     public void accept(TokenKind tk) {
   336         if (token.kind == tk) {
   337             nextToken();
   338         } else {
   339             setErrorEndPos(token.pos);
   340             reportSyntaxError(S.prevToken().endPos, "expected", tk);
   341         }
   342     }
   344     /** Report an illegal start of expression/type error at given position.
   345      */
   346     JCExpression illegal(int pos) {
   347         setErrorEndPos(pos);
   348         if ((mode & EXPR) != 0)
   349             return syntaxError(pos, "illegal.start.of.expr");
   350         else
   351             return syntaxError(pos, "illegal.start.of.type");
   353     }
   355     /** Report an illegal start of expression/type error at current position.
   356      */
   357     JCExpression illegal() {
   358         return illegal(token.pos);
   359     }
   361     /** Diagnose a modifier flag from the set, if any. */
   362     void checkNoMods(long mods) {
   363         if (mods != 0) {
   364             long lowestMod = mods & -mods;
   365             error(token.pos, "mod.not.allowed.here",
   366                       Flags.asFlagSet(lowestMod));
   367         }
   368     }
   370 /* ---------- doc comments --------- */
   372     /** A hashtable to store all documentation comments
   373      *  indexed by the tree nodes they refer to.
   374      *  defined only if option flag keepDocComment is set.
   375      */
   376     private final Map<JCTree, String> docComments;
   378     /** Make an entry into docComments hashtable,
   379      *  provided flag keepDocComments is set and given doc comment is non-null.
   380      *  @param tree   The tree to be used as index in the hashtable
   381      *  @param dc     The doc comment to associate with the tree, or null.
   382      */
   383     void attach(JCTree tree, String dc) {
   384         if (keepDocComments && dc != null) {
   385 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   386             docComments.put(tree, dc);
   387         }
   388     }
   390 /* -------- source positions ------- */
   392     private int errorEndPos = -1;
   394     private void setErrorEndPos(int errPos) {
   395         if (errPos > errorEndPos)
   396             errorEndPos = errPos;
   397     }
   399     protected int getErrorEndPos() {
   400         return errorEndPos;
   401     }
   403     /**
   404      * Store ending position for a tree.
   405      * @param tree   The tree.
   406      * @param endpos The ending position to associate with the tree.
   407      */
   408     protected void storeEnd(JCTree tree, int endpos) {}
   410     /**
   411      * Store ending position for a tree.  The ending position should
   412      * be the ending position of the current token.
   413      * @param t The tree.
   414      */
   415     protected <T extends JCTree> T to(T t) { return t; }
   417     /**
   418      * Store ending position for a tree.  The ending position should
   419      * be greater of the ending position of the previous token and errorEndPos.
   420      * @param t The tree.
   421      */
   422     protected <T extends JCTree> T toP(T t) { return t; }
   424     /** Get the start position for a tree node.  The start position is
   425      * defined to be the position of the first character of the first
   426      * token of the node's source text.
   427      * @param tree  The tree node
   428      */
   429     public int getStartPos(JCTree tree) {
   430         return TreeInfo.getStartPos(tree);
   431     }
   433     /**
   434      * Get the end position for a tree node.  The end position is
   435      * defined to be the position of the last character of the last
   436      * token of the node's source text.  Returns Position.NOPOS if end
   437      * positions are not generated or the position is otherwise not
   438      * found.
   439      * @param tree  The tree node
   440      */
   441     public int getEndPos(JCTree tree) {
   442         return Position.NOPOS;
   443     }
   447 /* ---------- parsing -------------- */
   449     /**
   450      * Ident = IDENTIFIER
   451      */
   452     Name ident() {
   453         if (token.kind == IDENTIFIER) {
   454             Name name = token.name();
   455             nextToken();
   456             return name;
   457         } else if (token.kind == ASSERT) {
   458             if (allowAsserts) {
   459                 error(token.pos, "assert.as.identifier");
   460                 nextToken();
   461                 return names.error;
   462             } else {
   463                 warning(token.pos, "assert.as.identifier");
   464                 Name name = token.name();
   465                 nextToken();
   466                 return name;
   467             }
   468         } else if (token.kind == ENUM) {
   469             if (allowEnums) {
   470                 error(token.pos, "enum.as.identifier");
   471                 nextToken();
   472                 return names.error;
   473             } else {
   474                 warning(token.pos, "enum.as.identifier");
   475                 Name name = token.name();
   476                 nextToken();
   477                 return name;
   478             }
   479         } else {
   480             accept(IDENTIFIER);
   481             return names.error;
   482         }
   483 }
   485     /**
   486      * Qualident = Ident { DOT Ident }
   487      */
   488     public JCExpression qualident() {
   489         JCExpression t = toP(F.at(token.pos).Ident(ident()));
   490         while (token.kind == DOT) {
   491             int pos = token.pos;
   492             nextToken();
   493             t = toP(F.at(pos).Select(t, ident()));
   494         }
   495         return t;
   496     }
   498     JCExpression literal(Name prefix) {
   499         return literal(prefix, token.pos);
   500     }
   502     /**
   503      * Literal =
   504      *     INTLITERAL
   505      *   | LONGLITERAL
   506      *   | FLOATLITERAL
   507      *   | DOUBLELITERAL
   508      *   | CHARLITERAL
   509      *   | STRINGLITERAL
   510      *   | TRUE
   511      *   | FALSE
   512      *   | NULL
   513      */
   514     JCExpression literal(Name prefix, int pos) {
   515         JCExpression t = errorTree;
   516         switch (token.kind) {
   517         case INTLITERAL:
   518             try {
   519                 t = F.at(pos).Literal(
   520                     TypeTags.INT,
   521                     Convert.string2int(strval(prefix), token.radix()));
   522             } catch (NumberFormatException ex) {
   523                 error(token.pos, "int.number.too.large", strval(prefix));
   524             }
   525             break;
   526         case LONGLITERAL:
   527             try {
   528                 t = F.at(pos).Literal(
   529                     TypeTags.LONG,
   530                     new Long(Convert.string2long(strval(prefix), token.radix())));
   531             } catch (NumberFormatException ex) {
   532                 error(token.pos, "int.number.too.large", strval(prefix));
   533             }
   534             break;
   535         case FLOATLITERAL: {
   536             String proper = token.radix() == 16 ?
   537                     ("0x"+ token.stringVal()) :
   538                     token.stringVal();
   539             Float n;
   540             try {
   541                 n = Float.valueOf(proper);
   542             } catch (NumberFormatException ex) {
   543                 // error already reported in scanner
   544                 n = Float.NaN;
   545             }
   546             if (n.floatValue() == 0.0f && !isZero(proper))
   547                 error(token.pos, "fp.number.too.small");
   548             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   549                 error(token.pos, "fp.number.too.large");
   550             else
   551                 t = F.at(pos).Literal(TypeTags.FLOAT, n);
   552             break;
   553         }
   554         case DOUBLELITERAL: {
   555             String proper = token.radix() == 16 ?
   556                     ("0x"+ token.stringVal()) :
   557                     token.stringVal();
   558             Double n;
   559             try {
   560                 n = Double.valueOf(proper);
   561             } catch (NumberFormatException ex) {
   562                 // error already reported in scanner
   563                 n = Double.NaN;
   564             }
   565             if (n.doubleValue() == 0.0d && !isZero(proper))
   566                 error(token.pos, "fp.number.too.small");
   567             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   568                 error(token.pos, "fp.number.too.large");
   569             else
   570                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
   571             break;
   572         }
   573         case CHARLITERAL:
   574             t = F.at(pos).Literal(
   575                 TypeTags.CHAR,
   576                 token.stringVal().charAt(0) + 0);
   577             break;
   578         case STRINGLITERAL:
   579             t = F.at(pos).Literal(
   580                 TypeTags.CLASS,
   581                 token.stringVal());
   582             break;
   583         case TRUE: case FALSE:
   584             t = F.at(pos).Literal(
   585                 TypeTags.BOOLEAN,
   586                 (token.kind == TRUE ? 1 : 0));
   587             break;
   588         case NULL:
   589             t = F.at(pos).Literal(
   590                 TypeTags.BOT,
   591                 null);
   592             break;
   593         default:
   594             Assert.error();
   595         }
   596         if (t == errorTree)
   597             t = F.at(pos).Erroneous();
   598         storeEnd(t, token.endPos);
   599         nextToken();
   600         return t;
   601     }
   602 //where
   603         boolean isZero(String s) {
   604             char[] cs = s.toCharArray();
   605             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   606             int i = ((base==16) ? 2 : 0);
   607             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   608             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   609         }
   611         String strval(Name prefix) {
   612             String s = token.stringVal();
   613             return prefix.isEmpty() ? s : prefix + s;
   614         }
   616     /** terms can be either expressions or types.
   617      */
   618     public JCExpression parseExpression() {
   619         return term(EXPR);
   620     }
   622     public JCExpression parseType() {
   623         return term(TYPE);
   624     }
   626     JCExpression term(int newmode) {
   627         int prevmode = mode;
   628         mode = newmode;
   629         JCExpression t = term();
   630         lastmode = mode;
   631         mode = prevmode;
   632         return t;
   633     }
   635     /**
   636      *  Expression = Expression1 [ExpressionRest]
   637      *  ExpressionRest = [AssignmentOperator Expression1]
   638      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   639      *                       "&=" | "|=" | "^=" |
   640      *                       "%=" | "<<=" | ">>=" | ">>>="
   641      *  Type = Type1
   642      *  TypeNoParams = TypeNoParams1
   643      *  StatementExpression = Expression
   644      *  ConstantExpression = Expression
   645      */
   646     JCExpression term() {
   647         JCExpression t = term1();
   648         if ((mode & EXPR) != 0 &&
   649             token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
   650             return termRest(t);
   651         else
   652             return t;
   653     }
   655     JCExpression termRest(JCExpression t) {
   656         switch (token.kind) {
   657         case EQ: {
   658             int pos = token.pos;
   659             nextToken();
   660             mode = EXPR;
   661             JCExpression t1 = term();
   662             return toP(F.at(pos).Assign(t, t1));
   663         }
   664         case PLUSEQ:
   665         case SUBEQ:
   666         case STAREQ:
   667         case SLASHEQ:
   668         case PERCENTEQ:
   669         case AMPEQ:
   670         case BAREQ:
   671         case CARETEQ:
   672         case LTLTEQ:
   673         case GTGTEQ:
   674         case GTGTGTEQ:
   675             int pos = token.pos;
   676             TokenKind tk = token.kind;
   677             nextToken();
   678             mode = EXPR;
   679             JCExpression t1 = term();
   680             return F.at(pos).Assignop(optag(tk), t, t1);
   681         default:
   682             return t;
   683         }
   684     }
   686     /** Expression1   = Expression2 [Expression1Rest]
   687      *  Type1         = Type2
   688      *  TypeNoParams1 = TypeNoParams2
   689      */
   690     JCExpression term1() {
   691         JCExpression t = term2();
   692         if ((mode & EXPR) != 0 && token.kind == QUES) {
   693             mode = EXPR;
   694             return term1Rest(t);
   695         } else {
   696             return t;
   697         }
   698     }
   700     /** Expression1Rest = ["?" Expression ":" Expression1]
   701      */
   702     JCExpression term1Rest(JCExpression t) {
   703         if (token.kind == QUES) {
   704             int pos = token.pos;
   705             nextToken();
   706             JCExpression t1 = term();
   707             accept(COLON);
   708             JCExpression t2 = term1();
   709             return F.at(pos).Conditional(t, t1, t2);
   710         } else {
   711             return t;
   712         }
   713     }
   715     /** Expression2   = Expression3 [Expression2Rest]
   716      *  Type2         = Type3
   717      *  TypeNoParams2 = TypeNoParams3
   718      */
   719     JCExpression term2() {
   720         JCExpression t = term3();
   721         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
   722             mode = EXPR;
   723             return term2Rest(t, TreeInfo.orPrec);
   724         } else {
   725             return t;
   726         }
   727     }
   729     /*  Expression2Rest = {infixop Expression3}
   730      *                  | Expression3 instanceof Type
   731      *  infixop         = "||"
   732      *                  | "&&"
   733      *                  | "|"
   734      *                  | "^"
   735      *                  | "&"
   736      *                  | "==" | "!="
   737      *                  | "<" | ">" | "<=" | ">="
   738      *                  | "<<" | ">>" | ">>>"
   739      *                  | "+" | "-"
   740      *                  | "*" | "/" | "%"
   741      */
   742     JCExpression term2Rest(JCExpression t, int minprec) {
   743         List<JCExpression[]> savedOd = odStackSupply.elems;
   744         JCExpression[] odStack = newOdStack();
   745         List<Token[]> savedOp = opStackSupply.elems;
   746         Token[] opStack = newOpStack();
   748         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   749         int top = 0;
   750         odStack[0] = t;
   751         int startPos = token.pos;
   752         Token topOp = Tokens.DUMMY;
   753         while (prec(token.kind) >= minprec) {
   754             opStack[top] = topOp;
   755             top++;
   756             topOp = token;
   757             nextToken();
   758             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
   759             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
   760                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
   761                                         odStack[top]);
   762                 top--;
   763                 topOp = opStack[top];
   764             }
   765         }
   766         Assert.check(top == 0);
   767         t = odStack[0];
   769         if (t.hasTag(JCTree.Tag.PLUS)) {
   770             StringBuffer buf = foldStrings(t);
   771             if (buf != null) {
   772                 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
   773             }
   774         }
   776         odStackSupply.elems = savedOd; // optimization
   777         opStackSupply.elems = savedOp; // optimization
   778         return t;
   779     }
   780 //where
   781         /** Construct a binary or type test node.
   782          */
   783         private JCExpression makeOp(int pos,
   784                                     TokenKind topOp,
   785                                     JCExpression od1,
   786                                     JCExpression od2)
   787         {
   788             if (topOp == INSTANCEOF) {
   789                 return F.at(pos).TypeTest(od1, od2);
   790             } else {
   791                 return F.at(pos).Binary(optag(topOp), od1, od2);
   792             }
   793         }
   794         /** If tree is a concatenation of string literals, replace it
   795          *  by a single literal representing the concatenated string.
   796          */
   797         protected StringBuffer foldStrings(JCTree tree) {
   798             if (!allowStringFolding)
   799                 return null;
   800             List<String> buf = List.nil();
   801             while (true) {
   802                 if (tree.hasTag(LITERAL)) {
   803                     JCLiteral lit = (JCLiteral) tree;
   804                     if (lit.typetag == TypeTags.CLASS) {
   805                         StringBuffer sbuf =
   806                             new StringBuffer((String)lit.value);
   807                         while (buf.nonEmpty()) {
   808                             sbuf.append(buf.head);
   809                             buf = buf.tail;
   810                         }
   811                         return sbuf;
   812                     }
   813                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
   814                     JCBinary op = (JCBinary)tree;
   815                     if (op.rhs.hasTag(LITERAL)) {
   816                         JCLiteral lit = (JCLiteral) op.rhs;
   817                         if (lit.typetag == TypeTags.CLASS) {
   818                             buf = buf.prepend((String) lit.value);
   819                             tree = op.lhs;
   820                             continue;
   821                         }
   822                     }
   823                 }
   824                 return null;
   825             }
   826         }
   828         /** optimization: To save allocating a new operand/operator stack
   829          *  for every binary operation, we use supplys.
   830          */
   831         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
   832         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
   834         private JCExpression[] newOdStack() {
   835             if (odStackSupply.elems == odStackSupply.last)
   836                 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
   837             JCExpression[] odStack = odStackSupply.elems.head;
   838             odStackSupply.elems = odStackSupply.elems.tail;
   839             return odStack;
   840         }
   842         private Token[] newOpStack() {
   843             if (opStackSupply.elems == opStackSupply.last)
   844                 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
   845             Token[] opStack = opStackSupply.elems.head;
   846             opStackSupply.elems = opStackSupply.elems.tail;
   847             return opStack;
   848         }
   850     /** Expression3    = PrefixOp Expression3
   851      *                 | "(" Expr | TypeNoParams ")" Expression3
   852      *                 | Primary {Selector} {PostfixOp}
   853      *  Primary        = "(" Expression ")"
   854      *                 | Literal
   855      *                 | [TypeArguments] THIS [Arguments]
   856      *                 | [TypeArguments] SUPER SuperSuffix
   857      *                 | NEW [TypeArguments] Creator
   858      *                 | Ident { "." Ident }
   859      *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   860      *                   | Arguments
   861      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   862      *                   ]
   863      *                 | BasicType BracketsOpt "." CLASS
   864      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   865      *  PostfixOp      = "++" | "--"
   866      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   867      *                 | BasicType
   868      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   869      *  Selector       = "." [TypeArguments] Ident [Arguments]
   870      *                 | "." THIS
   871      *                 | "." [TypeArguments] SUPER SuperSuffix
   872      *                 | "." NEW [TypeArguments] InnerCreator
   873      *                 | "[" Expression "]"
   874      *  TypeSelector   = "." Ident [TypeArguments]
   875      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   876      */
   877     protected JCExpression term3() {
   878         int pos = token.pos;
   879         JCExpression t;
   880         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   881         switch (token.kind) {
   882         case QUES:
   883             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   884                 mode = TYPE;
   885                 return typeArgument();
   886             } else
   887                 return illegal();
   888         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   889             if (typeArgs == null && (mode & EXPR) != 0) {
   890                 TokenKind tk = token.kind;
   891                 nextToken();
   892                 mode = EXPR;
   893                 if (tk == SUB &&
   894                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
   895                     token.radix() == 10) {
   896                     mode = EXPR;
   897                     t = literal(names.hyphen, pos);
   898                 } else {
   899                     t = term3();
   900                     return F.at(pos).Unary(unoptag(tk), t);
   901                 }
   902             } else return illegal();
   903             break;
   904         case LPAREN:
   905             if (typeArgs == null && (mode & EXPR) != 0) {
   906                 nextToken();
   907                 mode = EXPR | TYPE | NOPARAMS;
   908                 t = term3();
   909                 if ((mode & TYPE) != 0 && token.kind == LT) {
   910                     // Could be a cast to a parameterized type
   911                     JCTree.Tag op = JCTree.Tag.LT;
   912                     int pos1 = token.pos;
   913                     nextToken();
   914                     mode &= (EXPR | TYPE);
   915                     mode |= TYPEARG;
   916                     JCExpression t1 = term3();
   917                     if ((mode & TYPE) != 0 &&
   918                         (token.kind == COMMA || token.kind == GT)) {
   919                         mode = TYPE;
   920                         ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   921                         args.append(t1);
   922                         while (token.kind == COMMA) {
   923                             nextToken();
   924                             args.append(typeArgument());
   925                         }
   926                         accept(GT);
   927                         t = toP(F.at(pos1).TypeApply(t, args.toList()));
   928                         checkGenerics();
   929                         while (token.kind == DOT) {
   930                             nextToken();
   931                             mode = TYPE;
   932                             t = toP(F.at(token.pos).Select(t, ident()));
   933                             t = typeArgumentsOpt(t);
   934                         }
   935                         t = bracketsOpt(toP(t));
   936                     } else if ((mode & EXPR) != 0) {
   937                         mode = EXPR;
   938                         JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
   939                         t = F.at(pos1).Binary(op, t, e);
   940                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   941                     } else {
   942                         accept(GT);
   943                     }
   944                 }
   945                 else {
   946                     t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   947                 }
   948                 accept(RPAREN);
   949                 lastmode = mode;
   950                 mode = EXPR;
   951                 if ((lastmode & EXPR) == 0) {
   952                     JCExpression t1 = term3();
   953                     return F.at(pos).TypeCast(t, t1);
   954                 } else if ((lastmode & TYPE) != 0) {
   955                     switch (token.kind) {
   956                     /*case PLUSPLUS: case SUBSUB: */
   957                     case BANG: case TILDE:
   958                     case LPAREN: case THIS: case SUPER:
   959                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
   960                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
   961                     case TRUE: case FALSE: case NULL:
   962                     case NEW: case IDENTIFIER: case ASSERT: case ENUM:
   963                     case BYTE: case SHORT: case CHAR: case INT:
   964                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
   965                         JCExpression t1 = term3();
   966                         return F.at(pos).TypeCast(t, t1);
   967                     }
   968                 }
   969             } else return illegal();
   970             t = toP(F.at(pos).Parens(t));
   971             break;
   972         case THIS:
   973             if ((mode & EXPR) != 0) {
   974                 mode = EXPR;
   975                 t = to(F.at(pos).Ident(names._this));
   976                 nextToken();
   977                 if (typeArgs == null)
   978                     t = argumentsOpt(null, t);
   979                 else
   980                     t = arguments(typeArgs, t);
   981                 typeArgs = null;
   982             } else return illegal();
   983             break;
   984         case SUPER:
   985             if ((mode & EXPR) != 0) {
   986                 mode = EXPR;
   987                 t = to(F.at(pos).Ident(names._super));
   988                 t = superSuffix(typeArgs, t);
   989                 typeArgs = null;
   990             } else return illegal();
   991             break;
   992         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
   993         case CHARLITERAL: case STRINGLITERAL:
   994         case TRUE: case FALSE: case NULL:
   995             if (typeArgs == null && (mode & EXPR) != 0) {
   996                 mode = EXPR;
   997                 t = literal(names.empty);
   998             } else return illegal();
   999             break;
  1000         case NEW:
  1001             if (typeArgs != null) return illegal();
  1002             if ((mode & EXPR) != 0) {
  1003                 mode = EXPR;
  1004                 nextToken();
  1005                 if (token.kind == LT) typeArgs = typeArguments(false);
  1006                 t = creator(pos, typeArgs);
  1007                 typeArgs = null;
  1008             } else return illegal();
  1009             break;
  1010         case IDENTIFIER: case ASSERT: case ENUM:
  1011             if (typeArgs != null) return illegal();
  1012             t = toP(F.at(token.pos).Ident(ident()));
  1013             loop: while (true) {
  1014                 pos = token.pos;
  1015                 switch (token.kind) {
  1016                 case LBRACKET:
  1017                     nextToken();
  1018                     if (token.kind == RBRACKET) {
  1019                         nextToken();
  1020                         t = bracketsOpt(t);
  1021                         t = toP(F.at(pos).TypeArray(t));
  1022                         t = bracketsSuffix(t);
  1023                     } else {
  1024                         if ((mode & EXPR) != 0) {
  1025                             mode = EXPR;
  1026                             JCExpression t1 = term();
  1027                             t = to(F.at(pos).Indexed(t, t1));
  1029                         accept(RBRACKET);
  1031                     break loop;
  1032                 case LPAREN:
  1033                     if ((mode & EXPR) != 0) {
  1034                         mode = EXPR;
  1035                         t = arguments(typeArgs, t);
  1036                         typeArgs = null;
  1038                     break loop;
  1039                 case DOT:
  1040                     nextToken();
  1041                     int oldmode = mode;
  1042                     mode &= ~NOPARAMS;
  1043                     typeArgs = typeArgumentsOpt(EXPR);
  1044                     mode = oldmode;
  1045                     if ((mode & EXPR) != 0) {
  1046                         switch (token.kind) {
  1047                         case CLASS:
  1048                             if (typeArgs != null) return illegal();
  1049                             mode = EXPR;
  1050                             t = to(F.at(pos).Select(t, names._class));
  1051                             nextToken();
  1052                             break loop;
  1053                         case THIS:
  1054                             if (typeArgs != null) return illegal();
  1055                             mode = EXPR;
  1056                             t = to(F.at(pos).Select(t, names._this));
  1057                             nextToken();
  1058                             break loop;
  1059                         case SUPER:
  1060                             mode = EXPR;
  1061                             t = to(F.at(pos).Select(t, names._super));
  1062                             t = superSuffix(typeArgs, t);
  1063                             typeArgs = null;
  1064                             break loop;
  1065                         case NEW:
  1066                             if (typeArgs != null) return illegal();
  1067                             mode = EXPR;
  1068                             int pos1 = token.pos;
  1069                             nextToken();
  1070                             if (token.kind == LT) typeArgs = typeArguments(false);
  1071                             t = innerCreator(pos1, typeArgs, t);
  1072                             typeArgs = null;
  1073                             break loop;
  1076                     // typeArgs saved for next loop iteration.
  1077                     t = toP(F.at(pos).Select(t, ident()));
  1078                     break;
  1079                 default:
  1080                     break loop;
  1083             if (typeArgs != null) illegal();
  1084             t = typeArgumentsOpt(t);
  1085             break;
  1086         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1087         case DOUBLE: case BOOLEAN:
  1088             if (typeArgs != null) illegal();
  1089             t = bracketsSuffix(bracketsOpt(basicType()));
  1090             break;
  1091         case VOID:
  1092             if (typeArgs != null) illegal();
  1093             if ((mode & EXPR) != 0) {
  1094                 nextToken();
  1095                 if (token.kind == DOT) {
  1096                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
  1097                     t = bracketsSuffix(ti);
  1098                 } else {
  1099                     return illegal(pos);
  1101             } else {
  1102                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1103                 // a void type (like other primitive types) to the next phase.
  1104                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1105                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
  1106                 nextToken();
  1107                 return ti;
  1108                 //return illegal();
  1110             break;
  1111         default:
  1112             return illegal();
  1114         if (typeArgs != null) illegal();
  1115         while (true) {
  1116             int pos1 = token.pos;
  1117             if (token.kind == LBRACKET) {
  1118                 nextToken();
  1119                 if ((mode & TYPE) != 0) {
  1120                     int oldmode = mode;
  1121                     mode = TYPE;
  1122                     if (token.kind == RBRACKET) {
  1123                         nextToken();
  1124                         t = bracketsOpt(t);
  1125                         t = toP(F.at(pos1).TypeArray(t));
  1126                         return t;
  1128                     mode = oldmode;
  1130                 if ((mode & EXPR) != 0) {
  1131                     mode = EXPR;
  1132                     JCExpression t1 = term();
  1133                     t = to(F.at(pos1).Indexed(t, t1));
  1135                 accept(RBRACKET);
  1136             } else if (token.kind == DOT) {
  1137                 nextToken();
  1138                 typeArgs = typeArgumentsOpt(EXPR);
  1139                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1140                     mode = EXPR;
  1141                     t = to(F.at(pos1).Select(t, names._super));
  1142                     nextToken();
  1143                     t = arguments(typeArgs, t);
  1144                     typeArgs = null;
  1145                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1146                     if (typeArgs != null) return illegal();
  1147                     mode = EXPR;
  1148                     int pos2 = token.pos;
  1149                     nextToken();
  1150                     if (token.kind == LT) typeArgs = typeArguments(false);
  1151                     t = innerCreator(pos2, typeArgs, t);
  1152                     typeArgs = null;
  1153                 } else {
  1154                     t = toP(F.at(pos1).Select(t, ident()));
  1155                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1156                     typeArgs = null;
  1158             } else {
  1159                 break;
  1162         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1163             mode = EXPR;
  1164             t = to(F.at(token.pos).Unary(
  1165                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1166             nextToken();
  1168         return toP(t);
  1171     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1172      */
  1173     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1174         nextToken();
  1175         if (token.kind == LPAREN || typeArgs != null) {
  1176             t = arguments(typeArgs, t);
  1177         } else {
  1178             int pos = token.pos;
  1179             accept(DOT);
  1180             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1181             t = toP(F.at(pos).Select(t, ident()));
  1182             t = argumentsOpt(typeArgs, t);
  1184         return t;
  1187     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1188      */
  1189     JCPrimitiveTypeTree basicType() {
  1190         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1191         nextToken();
  1192         return t;
  1195     /** ArgumentsOpt = [ Arguments ]
  1196      */
  1197     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1198         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1199             mode = EXPR;
  1200             return arguments(typeArgs, t);
  1201         } else {
  1202             return t;
  1206     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1207      */
  1208     List<JCExpression> arguments() {
  1209         ListBuffer<JCExpression> args = lb();
  1210         if (token.kind == LPAREN) {
  1211             nextToken();
  1212             if (token.kind != RPAREN) {
  1213                 args.append(parseExpression());
  1214                 while (token.kind == COMMA) {
  1215                     nextToken();
  1216                     args.append(parseExpression());
  1219             accept(RPAREN);
  1220         } else {
  1221             syntaxError(token.pos, "expected", LPAREN);
  1223         return args.toList();
  1226     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1227         int pos = token.pos;
  1228         List<JCExpression> args = arguments();
  1229         return toP(F.at(pos).Apply(typeArgs, t, args));
  1232     /**  TypeArgumentsOpt = [ TypeArguments ]
  1233      */
  1234     JCExpression typeArgumentsOpt(JCExpression t) {
  1235         if (token.kind == LT &&
  1236             (mode & TYPE) != 0 &&
  1237             (mode & NOPARAMS) == 0) {
  1238             mode = TYPE;
  1239             checkGenerics();
  1240             return typeArguments(t, false);
  1241         } else {
  1242             return t;
  1245     List<JCExpression> typeArgumentsOpt() {
  1246         return typeArgumentsOpt(TYPE);
  1249     List<JCExpression> typeArgumentsOpt(int useMode) {
  1250         if (token.kind == LT) {
  1251             checkGenerics();
  1252             if ((mode & useMode) == 0 ||
  1253                 (mode & NOPARAMS) != 0) {
  1254                 illegal();
  1256             mode = useMode;
  1257             return typeArguments(false);
  1259         return null;
  1262     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1263      */
  1264     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1265         if (token.kind == LT) {
  1266             nextToken();
  1267             if (token.kind == GT && diamondAllowed) {
  1268                 checkDiamond();
  1269                 mode |= DIAMOND;
  1270                 nextToken();
  1271                 return List.nil();
  1272             } else {
  1273                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1274                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1275                 while (token.kind == COMMA) {
  1276                     nextToken();
  1277                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1279                 switch (token.kind) {
  1281                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1282                 case GTGTGT: case GTGT:
  1283                     token = S.split();
  1284                     break;
  1285                 case GT:
  1286                     nextToken();
  1287                     break;
  1288                 default:
  1289                     args.append(syntaxError(token.pos, "expected", GT));
  1290                     break;
  1292                 return args.toList();
  1294         } else {
  1295             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1299     /** TypeArgument = Type
  1300      *               | "?"
  1301      *               | "?" EXTENDS Type {"&" Type}
  1302      *               | "?" SUPER Type
  1303      */
  1304     JCExpression typeArgument() {
  1305         if (token.kind != QUES) return parseType();
  1306         int pos = token.pos;
  1307         nextToken();
  1308         if (token.kind == EXTENDS) {
  1309             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1310             nextToken();
  1311             JCExpression bound = parseType();
  1312             return F.at(pos).Wildcard(t, bound);
  1313         } else if (token.kind == SUPER) {
  1314             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1315             nextToken();
  1316             JCExpression bound = parseType();
  1317             return F.at(pos).Wildcard(t, bound);
  1318         } else if (token.kind == IDENTIFIER) {
  1319             //error recovery
  1320             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1321             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1322             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1323             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1324             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1325             return err;
  1326         } else {
  1327             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1328             return toP(F.at(pos).Wildcard(t, null));
  1332     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1333         int pos = token.pos;
  1334         List<JCExpression> args = typeArguments(diamondAllowed);
  1335         return toP(F.at(pos).TypeApply(t, args));
  1338     /** BracketsOpt = {"[" "]"}
  1339      */
  1340     private JCExpression bracketsOpt(JCExpression t) {
  1341         if (token.kind == LBRACKET) {
  1342             int pos = token.pos;
  1343             nextToken();
  1344             t = bracketsOptCont(t, pos);
  1345             F.at(pos);
  1347         return t;
  1350     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1351         accept(RBRACKET);
  1352         t = bracketsOpt(t);
  1353         return toP(F.at(pos).TypeArray(t));
  1356     /** BracketsSuffixExpr = "." CLASS
  1357      *  BracketsSuffixType =
  1358      */
  1359     JCExpression bracketsSuffix(JCExpression t) {
  1360         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1361             mode = EXPR;
  1362             int pos = token.pos;
  1363             nextToken();
  1364             accept(CLASS);
  1365             if (token.pos == errorEndPos) {
  1366                 // error recovery
  1367                 Name name = null;
  1368                 if (token.kind == IDENTIFIER) {
  1369                     name = token.name();
  1370                     nextToken();
  1371                 } else {
  1372                     name = names.error;
  1374                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1375             } else {
  1376                 t = toP(F.at(pos).Select(t, names._class));
  1378         } else if ((mode & TYPE) != 0) {
  1379             mode = TYPE;
  1380         } else {
  1381             syntaxError(token.pos, "dot.class.expected");
  1383         return t;
  1386     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1387      */
  1388     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1389         switch (token.kind) {
  1390         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1391         case DOUBLE: case BOOLEAN:
  1392             if (typeArgs == null)
  1393                 return arrayCreatorRest(newpos, basicType());
  1394             break;
  1395         default:
  1397         JCExpression t = qualident();
  1398         int oldmode = mode;
  1399         mode = TYPE;
  1400         boolean diamondFound = false;
  1401         int lastTypeargsPos = -1;
  1402         if (token.kind == LT) {
  1403             checkGenerics();
  1404             lastTypeargsPos = token.pos;
  1405             t = typeArguments(t, true);
  1406             diamondFound = (mode & DIAMOND) != 0;
  1408         while (token.kind == DOT) {
  1409             if (diamondFound) {
  1410                 //cannot select after a diamond
  1411                 illegal();
  1413             int pos = token.pos;
  1414             nextToken();
  1415             t = toP(F.at(pos).Select(t, ident()));
  1416             if (token.kind == LT) {
  1417                 lastTypeargsPos = token.pos;
  1418                 checkGenerics();
  1419                 t = typeArguments(t, true);
  1420                 diamondFound = (mode & DIAMOND) != 0;
  1423         mode = oldmode;
  1424         if (token.kind == LBRACKET) {
  1425             JCExpression e = arrayCreatorRest(newpos, t);
  1426             if (diamondFound) {
  1427                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  1428                 return toP(F.at(newpos).Erroneous(List.of(e)));
  1430             else if (typeArgs != null) {
  1431                 int pos = newpos;
  1432                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1433                     // note: this should always happen but we should
  1434                     // not rely on this as the parser is continuously
  1435                     // modified to improve error recovery.
  1436                     pos = typeArgs.head.pos;
  1438                 setErrorEndPos(S.prevToken().endPos);
  1439                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  1440                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  1441                 return toP(err);
  1443             return e;
  1444         } else if (token.kind == LPAREN) {
  1445             return classCreatorRest(newpos, null, typeArgs, t);
  1446         } else {
  1447             setErrorEndPos(token.pos);
  1448             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  1449             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1450             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1454     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1455      */
  1456     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1457         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  1458         if (token.kind == LT) {
  1459             int oldmode = mode;
  1460             checkGenerics();
  1461             t = typeArguments(t, true);
  1462             mode = oldmode;
  1464         return classCreatorRest(newpos, encl, typeArgs, t);
  1467     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1468      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1469      */
  1470     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1471         accept(LBRACKET);
  1472         if (token.kind == RBRACKET) {
  1473             accept(RBRACKET);
  1474             elemtype = bracketsOpt(elemtype);
  1475             if (token.kind == LBRACE) {
  1476                 return arrayInitializer(newpos, elemtype);
  1477             } else {
  1478                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  1479                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  1481         } else {
  1482             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1483             dims.append(parseExpression());
  1484             accept(RBRACKET);
  1485             while (token.kind == LBRACKET) {
  1486                 int pos = token.pos;
  1487                 nextToken();
  1488                 if (token.kind == RBRACKET) {
  1489                     elemtype = bracketsOptCont(elemtype, pos);
  1490                 } else {
  1491                     dims.append(parseExpression());
  1492                     accept(RBRACKET);
  1495             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1499     /** ClassCreatorRest = Arguments [ClassBody]
  1500      */
  1501     JCNewClass classCreatorRest(int newpos,
  1502                                   JCExpression encl,
  1503                                   List<JCExpression> typeArgs,
  1504                                   JCExpression t)
  1506         List<JCExpression> args = arguments();
  1507         JCClassDecl body = null;
  1508         if (token.kind == LBRACE) {
  1509             int pos = token.pos;
  1510             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1511             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1512             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1514         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1517     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1518      */
  1519     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1520         accept(LBRACE);
  1521         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1522         if (token.kind == COMMA) {
  1523             nextToken();
  1524         } else if (token.kind != RBRACE) {
  1525             elems.append(variableInitializer());
  1526             while (token.kind == COMMA) {
  1527                 nextToken();
  1528                 if (token.kind == RBRACE) break;
  1529                 elems.append(variableInitializer());
  1532         accept(RBRACE);
  1533         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1536     /** VariableInitializer = ArrayInitializer | Expression
  1537      */
  1538     public JCExpression variableInitializer() {
  1539         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  1542     /** ParExpression = "(" Expression ")"
  1543      */
  1544     JCExpression parExpression() {
  1545         accept(LPAREN);
  1546         JCExpression t = parseExpression();
  1547         accept(RPAREN);
  1548         return t;
  1551     /** Block = "{" BlockStatements "}"
  1552      */
  1553     JCBlock block(int pos, long flags) {
  1554         accept(LBRACE);
  1555         List<JCStatement> stats = blockStatements();
  1556         JCBlock t = F.at(pos).Block(flags, stats);
  1557         while (token.kind == CASE || token.kind == DEFAULT) {
  1558             syntaxError("orphaned", token.kind);
  1559             switchBlockStatementGroups();
  1561         // the Block node has a field "endpos" for first char of last token, which is
  1562         // usually but not necessarily the last char of the last token.
  1563         t.endpos = token.pos;
  1564         accept(RBRACE);
  1565         return toP(t);
  1568     public JCBlock block() {
  1569         return block(token.pos, 0);
  1572     /** BlockStatements = { BlockStatement }
  1573      *  BlockStatement  = LocalVariableDeclarationStatement
  1574      *                  | ClassOrInterfaceOrEnumDeclaration
  1575      *                  | [Ident ":"] Statement
  1576      *  LocalVariableDeclarationStatement
  1577      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1578      */
  1579     @SuppressWarnings("fallthrough")
  1580     List<JCStatement> blockStatements() {
  1581 //todo: skip to anchor on error(?)
  1582         int lastErrPos = -1;
  1583         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1584         while (true) {
  1585             int pos = token.pos;
  1586             switch (token.kind) {
  1587             case RBRACE: case CASE: case DEFAULT: case EOF:
  1588                 return stats.toList();
  1589             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1590             case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1591             case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1592                 stats.append(parseStatement());
  1593                 break;
  1594             case MONKEYS_AT:
  1595             case FINAL: {
  1596                 String dc = token.comment(CommentStyle.JAVADOC);
  1597                 JCModifiers mods = modifiersOpt();
  1598                 if (token.kind == INTERFACE ||
  1599                     token.kind == CLASS ||
  1600                     allowEnums && token.kind == ENUM) {
  1601                     stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1602                 } else {
  1603                     JCExpression t = parseType();
  1604                     stats.appendList(variableDeclarators(mods, t,
  1605                                                          new ListBuffer<JCStatement>()));
  1606                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1607                     storeEnd(stats.elems.last(), token.endPos);
  1608                     accept(SEMI);
  1610                 break;
  1612             case ABSTRACT: case STRICTFP: {
  1613                 String dc = token.comment(CommentStyle.JAVADOC);
  1614                 JCModifiers mods = modifiersOpt();
  1615                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1616                 break;
  1618             case INTERFACE:
  1619             case CLASS:
  1620                 String dc = token.comment(CommentStyle.JAVADOC);
  1621                 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  1622                 break;
  1623             case ENUM:
  1624             case ASSERT:
  1625                 if (allowEnums && token.kind == ENUM) {
  1626                     error(token.pos, "local.enum");
  1627                     dc = token.comment(CommentStyle.JAVADOC);
  1628                     stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  1629                     break;
  1630                 } else if (allowAsserts && token.kind == ASSERT) {
  1631                     stats.append(parseStatement());
  1632                     break;
  1634                 /* fall through to default */
  1635             default:
  1636                 Token prevToken = token;
  1637                 JCExpression t = term(EXPR | TYPE);
  1638                 if (token.kind == COLON && t.hasTag(IDENT)) {
  1639                     nextToken();
  1640                     JCStatement stat = parseStatement();
  1641                     stats.append(F.at(pos).Labelled(prevToken.name(), stat));
  1642                 } else if ((lastmode & TYPE) != 0 &&
  1643                            (token.kind == IDENTIFIER ||
  1644                             token.kind == ASSERT ||
  1645                             token.kind == ENUM)) {
  1646                     pos = token.pos;
  1647                     JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1648                     F.at(pos);
  1649                     stats.appendList(variableDeclarators(mods, t,
  1650                                                          new ListBuffer<JCStatement>()));
  1651                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1652                     storeEnd(stats.elems.last(), token.endPos);
  1653                     accept(SEMI);
  1654                 } else {
  1655                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1656                     stats.append(to(F.at(pos).Exec(checkExprStat(t))));
  1657                     accept(SEMI);
  1661             // error recovery
  1662             if (token.pos == lastErrPos)
  1663                 return stats.toList();
  1664             if (token.pos <= errorEndPos) {
  1665                 skip(false, true, true, true);
  1666                 lastErrPos = token.pos;
  1671     /** Statement =
  1672      *       Block
  1673      *     | IF ParExpression Statement [ELSE Statement]
  1674      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1675      *     | FOR "(" FormalParameter : Expression ")" Statement
  1676      *     | WHILE ParExpression Statement
  1677      *     | DO Statement WHILE ParExpression ";"
  1678      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1679      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  1680      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1681      *     | SYNCHRONIZED ParExpression Block
  1682      *     | RETURN [Expression] ";"
  1683      *     | THROW Expression ";"
  1684      *     | BREAK [Ident] ";"
  1685      *     | CONTINUE [Ident] ";"
  1686      *     | ASSERT Expression [ ":" Expression ] ";"
  1687      *     | ";"
  1688      *     | ExpressionStatement
  1689      *     | Ident ":" Statement
  1690      */
  1691     @SuppressWarnings("fallthrough")
  1692     public JCStatement parseStatement() {
  1693         int pos = token.pos;
  1694         switch (token.kind) {
  1695         case LBRACE:
  1696             return block();
  1697         case IF: {
  1698             nextToken();
  1699             JCExpression cond = parExpression();
  1700             JCStatement thenpart = parseStatement();
  1701             JCStatement elsepart = null;
  1702             if (token.kind == ELSE) {
  1703                 nextToken();
  1704                 elsepart = parseStatement();
  1706             return F.at(pos).If(cond, thenpart, elsepart);
  1708         case FOR: {
  1709             nextToken();
  1710             accept(LPAREN);
  1711             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  1712             if (inits.length() == 1 &&
  1713                 inits.head.hasTag(VARDEF) &&
  1714                 ((JCVariableDecl) inits.head).init == null &&
  1715                 token.kind == COLON) {
  1716                 checkForeach();
  1717                 JCVariableDecl var = (JCVariableDecl)inits.head;
  1718                 accept(COLON);
  1719                 JCExpression expr = parseExpression();
  1720                 accept(RPAREN);
  1721                 JCStatement body = parseStatement();
  1722                 return F.at(pos).ForeachLoop(var, expr, body);
  1723             } else {
  1724                 accept(SEMI);
  1725                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  1726                 accept(SEMI);
  1727                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  1728                 accept(RPAREN);
  1729                 JCStatement body = parseStatement();
  1730                 return F.at(pos).ForLoop(inits, cond, steps, body);
  1733         case WHILE: {
  1734             nextToken();
  1735             JCExpression cond = parExpression();
  1736             JCStatement body = parseStatement();
  1737             return F.at(pos).WhileLoop(cond, body);
  1739         case DO: {
  1740             nextToken();
  1741             JCStatement body = parseStatement();
  1742             accept(WHILE);
  1743             JCExpression cond = parExpression();
  1744             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  1745             accept(SEMI);
  1746             return t;
  1748         case TRY: {
  1749             nextToken();
  1750             List<JCTree> resources = List.<JCTree>nil();
  1751             if (token.kind == LPAREN) {
  1752                 checkTryWithResources();
  1753                 nextToken();
  1754                 resources = resources();
  1755                 accept(RPAREN);
  1757             JCBlock body = block();
  1758             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  1759             JCBlock finalizer = null;
  1760             if (token.kind == CATCH || token.kind == FINALLY) {
  1761                 while (token.kind == CATCH) catchers.append(catchClause());
  1762                 if (token.kind == FINALLY) {
  1763                     nextToken();
  1764                     finalizer = block();
  1766             } else {
  1767                 if (allowTWR) {
  1768                     if (resources.isEmpty())
  1769                         error(pos, "try.without.catch.finally.or.resource.decls");
  1770                 } else
  1771                     error(pos, "try.without.catch.or.finally");
  1773             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  1775         case SWITCH: {
  1776             nextToken();
  1777             JCExpression selector = parExpression();
  1778             accept(LBRACE);
  1779             List<JCCase> cases = switchBlockStatementGroups();
  1780             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  1781             accept(RBRACE);
  1782             return t;
  1784         case SYNCHRONIZED: {
  1785             nextToken();
  1786             JCExpression lock = parExpression();
  1787             JCBlock body = block();
  1788             return F.at(pos).Synchronized(lock, body);
  1790         case RETURN: {
  1791             nextToken();
  1792             JCExpression result = token.kind == SEMI ? null : parseExpression();
  1793             JCReturn t = to(F.at(pos).Return(result));
  1794             accept(SEMI);
  1795             return t;
  1797         case THROW: {
  1798             nextToken();
  1799             JCExpression exc = parseExpression();
  1800             JCThrow t = to(F.at(pos).Throw(exc));
  1801             accept(SEMI);
  1802             return t;
  1804         case BREAK: {
  1805             nextToken();
  1806             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  1807             JCBreak t = to(F.at(pos).Break(label));
  1808             accept(SEMI);
  1809             return t;
  1811         case CONTINUE: {
  1812             nextToken();
  1813             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  1814             JCContinue t =  to(F.at(pos).Continue(label));
  1815             accept(SEMI);
  1816             return t;
  1818         case SEMI:
  1819             nextToken();
  1820             return toP(F.at(pos).Skip());
  1821         case ELSE:
  1822             return toP(F.Exec(syntaxError("else.without.if")));
  1823         case FINALLY:
  1824             return toP(F.Exec(syntaxError("finally.without.try")));
  1825         case CATCH:
  1826             return toP(F.Exec(syntaxError("catch.without.try")));
  1827         case ASSERT: {
  1828             if (allowAsserts && token.kind == ASSERT) {
  1829                 nextToken();
  1830                 JCExpression assertion = parseExpression();
  1831                 JCExpression message = null;
  1832                 if (token.kind == COLON) {
  1833                     nextToken();
  1834                     message = parseExpression();
  1836                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  1837                 accept(SEMI);
  1838                 return t;
  1840             /* else fall through to default case */
  1842         case ENUM:
  1843         default:
  1844             Token prevToken = token;
  1845             JCExpression expr = parseExpression();
  1846             if (token.kind == COLON && expr.hasTag(IDENT)) {
  1847                 nextToken();
  1848                 JCStatement stat = parseStatement();
  1849                 return F.at(pos).Labelled(prevToken.name(), stat);
  1850             } else {
  1851                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1852                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  1853                 accept(SEMI);
  1854                 return stat;
  1859     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  1860      */
  1861     protected JCCatch catchClause() {
  1862         int pos = token.pos;
  1863         accept(CATCH);
  1864         accept(LPAREN);
  1865         JCModifiers mods = optFinal(Flags.PARAMETER);
  1866         List<JCExpression> catchTypes = catchTypes();
  1867         JCExpression paramType = catchTypes.size() > 1 ?
  1868                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  1869                 catchTypes.head;
  1870         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  1871         accept(RPAREN);
  1872         JCBlock body = block();
  1873         return F.at(pos).Catch(formal, body);
  1876     List<JCExpression> catchTypes() {
  1877         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  1878         catchTypes.add(parseType());
  1879         while (token.kind == BAR) {
  1880             checkMulticatch();
  1881             nextToken();
  1882             catchTypes.add(qualident());
  1884         return catchTypes.toList();
  1887     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  1888      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  1889      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  1890      */
  1891     List<JCCase> switchBlockStatementGroups() {
  1892         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  1893         while (true) {
  1894             int pos = token.pos;
  1895             switch (token.kind) {
  1896             case CASE: {
  1897                 nextToken();
  1898                 JCExpression pat = parseExpression();
  1899                 accept(COLON);
  1900                 List<JCStatement> stats = blockStatements();
  1901                 JCCase c = F.at(pos).Case(pat, stats);
  1902                 if (stats.isEmpty())
  1903                     storeEnd(c, S.prevToken().endPos);
  1904                 cases.append(c);
  1905                 break;
  1907             case DEFAULT: {
  1908                 nextToken();
  1909                 accept(COLON);
  1910                 List<JCStatement> stats = blockStatements();
  1911                 JCCase c = F.at(pos).Case(null, stats);
  1912                 if (stats.isEmpty())
  1913                     storeEnd(c, S.prevToken().endPos);
  1914                 cases.append(c);
  1915                 break;
  1917             case RBRACE: case EOF:
  1918                 return cases.toList();
  1919             default:
  1920                 nextToken(); // to ensure progress
  1921                 syntaxError(pos, "expected3",
  1922                     CASE, DEFAULT, RBRACE);
  1927     /** MoreStatementExpressions = { COMMA StatementExpression }
  1928      */
  1929     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  1930                                                                     JCExpression first,
  1931                                                                     T stats) {
  1932         // This Exec is a "StatementExpression"; it subsumes no terminating token
  1933         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  1934         while (token.kind == COMMA) {
  1935             nextToken();
  1936             pos = token.pos;
  1937             JCExpression t = parseExpression();
  1938             // This Exec is a "StatementExpression"; it subsumes no terminating token
  1939             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  1941         return stats;
  1944     /** ForInit = StatementExpression MoreStatementExpressions
  1945      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  1946      */
  1947     List<JCStatement> forInit() {
  1948         ListBuffer<JCStatement> stats = lb();
  1949         int pos = token.pos;
  1950         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  1951             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  1952         } else {
  1953             JCExpression t = term(EXPR | TYPE);
  1954             if ((lastmode & TYPE) != 0 &&
  1955                 (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM))
  1956                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  1957             else
  1958                 return moreStatementExpressions(pos, t, stats).toList();
  1962     /** ForUpdate = StatementExpression MoreStatementExpressions
  1963      */
  1964     List<JCExpressionStatement> forUpdate() {
  1965         return moreStatementExpressions(token.pos,
  1966                                         parseExpression(),
  1967                                         new ListBuffer<JCExpressionStatement>()).toList();
  1970     /** AnnotationsOpt = { '@' Annotation }
  1971      */
  1972     List<JCAnnotation> annotationsOpt() {
  1973         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  1974         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  1975         while (token.kind == MONKEYS_AT) {
  1976             int pos = token.pos;
  1977             nextToken();
  1978             buf.append(annotation(pos));
  1980         return buf.toList();
  1983     /** ModifiersOpt = { Modifier }
  1984      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  1985      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  1986      *           | "@" Annotation
  1987      */
  1988     JCModifiers modifiersOpt() {
  1989         return modifiersOpt(null);
  1991     protected JCModifiers modifiersOpt(JCModifiers partial) {
  1992         long flags;
  1993         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  1994         int pos;
  1995         if (partial == null) {
  1996             flags = 0;
  1997             pos = token.pos;
  1998         } else {
  1999             flags = partial.flags;
  2000             annotations.appendList(partial.annotations);
  2001             pos = partial.pos;
  2003         if (token.deprecatedFlag()) {
  2004             flags |= Flags.DEPRECATED;
  2006         int lastPos = Position.NOPOS;
  2007     loop:
  2008         while (true) {
  2009             long flag;
  2010             switch (token.kind) {
  2011             case PRIVATE     : flag = Flags.PRIVATE; break;
  2012             case PROTECTED   : flag = Flags.PROTECTED; break;
  2013             case PUBLIC      : flag = Flags.PUBLIC; break;
  2014             case STATIC      : flag = Flags.STATIC; break;
  2015             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2016             case FINAL       : flag = Flags.FINAL; break;
  2017             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2018             case NATIVE      : flag = Flags.NATIVE; break;
  2019             case VOLATILE    : flag = Flags.VOLATILE; break;
  2020             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2021             case STRICTFP    : flag = Flags.STRICTFP; break;
  2022             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2023             case ERROR       : flag = 0; nextToken(); break;
  2024             default: break loop;
  2026             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2027             lastPos = token.pos;
  2028             nextToken();
  2029             if (flag == Flags.ANNOTATION) {
  2030                 checkAnnotations();
  2031                 if (token.kind != INTERFACE) {
  2032                     JCAnnotation ann = annotation(lastPos);
  2033                     // if first modifier is an annotation, set pos to annotation's.
  2034                     if (flags == 0 && annotations.isEmpty())
  2035                         pos = ann.pos;
  2036                     annotations.append(ann);
  2037                     lastPos = ann.pos;
  2038                     flag = 0;
  2041             flags |= flag;
  2043         switch (token.kind) {
  2044         case ENUM: flags |= Flags.ENUM; break;
  2045         case INTERFACE: flags |= Flags.INTERFACE; break;
  2046         default: break;
  2049         /* A modifiers tree with no modifier tokens or annotations
  2050          * has no text position. */
  2051         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2052             pos = Position.NOPOS;
  2054         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2055         if (pos != Position.NOPOS)
  2056             storeEnd(mods, S.prevToken().endPos);
  2057         return mods;
  2060     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2061      * @param pos position of "@" token
  2062      */
  2063     JCAnnotation annotation(int pos) {
  2064         // accept(AT); // AT consumed by caller
  2065         checkAnnotations();
  2066         JCTree ident = qualident();
  2067         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2068         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  2069         storeEnd(ann, S.prevToken().endPos);
  2070         return ann;
  2073     List<JCExpression> annotationFieldValuesOpt() {
  2074         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2077     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2078     List<JCExpression> annotationFieldValues() {
  2079         accept(LPAREN);
  2080         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2081         if (token.kind != RPAREN) {
  2082             buf.append(annotationFieldValue());
  2083             while (token.kind == COMMA) {
  2084                 nextToken();
  2085                 buf.append(annotationFieldValue());
  2088         accept(RPAREN);
  2089         return buf.toList();
  2092     /** AnnotationFieldValue    = AnnotationValue
  2093      *                          | Identifier "=" AnnotationValue
  2094      */
  2095     JCExpression annotationFieldValue() {
  2096         if (token.kind == IDENTIFIER) {
  2097             mode = EXPR;
  2098             JCExpression t1 = term1();
  2099             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2100                 int pos = token.pos;
  2101                 accept(EQ);
  2102                 JCExpression v = annotationValue();
  2103                 return toP(F.at(pos).Assign(t1, v));
  2104             } else {
  2105                 return t1;
  2108         return annotationValue();
  2111     /* AnnotationValue          = ConditionalExpression
  2112      *                          | Annotation
  2113      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2114      */
  2115     JCExpression annotationValue() {
  2116         int pos;
  2117         switch (token.kind) {
  2118         case MONKEYS_AT:
  2119             pos = token.pos;
  2120             nextToken();
  2121             return annotation(pos);
  2122         case LBRACE:
  2123             pos = token.pos;
  2124             accept(LBRACE);
  2125             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2126             if (token.kind != RBRACE) {
  2127                 buf.append(annotationValue());
  2128                 while (token.kind == COMMA) {
  2129                     nextToken();
  2130                     if (token.kind == RBRACE) break;
  2131                     buf.append(annotationValue());
  2134             accept(RBRACE);
  2135             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2136         default:
  2137             mode = EXPR;
  2138             return term1();
  2142     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2143      */
  2144     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2145                                                                          JCExpression type,
  2146                                                                          T vdefs)
  2148         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2151     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2152      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2154      *  @param reqInit  Is an initializer always required?
  2155      *  @param dc       The documentation comment for the variable declarations, or null.
  2156      */
  2157     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2158                                                                      JCModifiers mods,
  2159                                                                      JCExpression type,
  2160                                                                      Name name,
  2161                                                                      boolean reqInit,
  2162                                                                      String dc,
  2163                                                                      T vdefs)
  2165         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2166         while (token.kind == COMMA) {
  2167             // All but last of multiple declarators subsume a comma
  2168             storeEnd((JCTree)vdefs.elems.last(), token.endPos);
  2169             nextToken();
  2170             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2172         return vdefs;
  2175     /** VariableDeclarator = Ident VariableDeclaratorRest
  2176      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2177      */
  2178     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
  2179         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2182     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2183      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2185      *  @param reqInit  Is an initializer always required?
  2186      *  @param dc       The documentation comment for the variable declarations, or null.
  2187      */
  2188     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2189                                   boolean reqInit, String dc) {
  2190         type = bracketsOpt(type);
  2191         JCExpression init = null;
  2192         if (token.kind == EQ) {
  2193             nextToken();
  2194             init = variableInitializer();
  2196         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2197         JCVariableDecl result =
  2198             toP(F.at(pos).VarDef(mods, name, type, init));
  2199         attach(result, dc);
  2200         return result;
  2203     /** VariableDeclaratorId = Ident BracketsOpt
  2204      */
  2205     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2206         int pos = token.pos;
  2207         Name name = ident();
  2208         if ((mods.flags & Flags.VARARGS) != 0 &&
  2209                 token.kind == LBRACKET) {
  2210             log.error(token.pos, "varargs.and.old.array.syntax");
  2212         type = bracketsOpt(type);
  2213         return toP(F.at(pos).VarDef(mods, name, type, null));
  2216     /** Resources = Resource { ";" Resources }
  2217      */
  2218     List<JCTree> resources() {
  2219         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2220         defs.append(resource());
  2221         while (token.kind == SEMI) {
  2222             // All but last of multiple declarators must subsume a semicolon
  2223             storeEnd(defs.elems.last(), token.endPos);
  2224             int semiColonPos = token.pos;
  2225             nextToken();
  2226             if (token.kind == RPAREN) { // Optional trailing semicolon
  2227                                        // after last resource
  2228                 break;
  2230             defs.append(resource());
  2232         return defs.toList();
  2235     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  2236      */
  2237     protected JCTree resource() {
  2238         JCModifiers optFinal = optFinal(Flags.FINAL);
  2239         JCExpression type = parseType();
  2240         int pos = token.pos;
  2241         Name ident = ident();
  2242         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  2245     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2246      */
  2247     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2248         Token firstToken = token;
  2249         JCExpression pid = null;
  2250         JCModifiers mods = null;
  2251         boolean consumedToplevelDoc = false;
  2252         boolean seenImport = false;
  2253         boolean seenPackage = false;
  2254         List<JCAnnotation> packageAnnotations = List.nil();
  2255         if (token.kind == MONKEYS_AT)
  2256             mods = modifiersOpt();
  2258         if (token.kind == PACKAGE) {
  2259             seenPackage = true;
  2260             if (mods != null) {
  2261                 checkNoMods(mods.flags);
  2262                 packageAnnotations = mods.annotations;
  2263                 mods = null;
  2265             nextToken();
  2266             pid = qualident();
  2267             accept(SEMI);
  2269         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2270         boolean checkForImports = true;
  2271         boolean firstTypeDecl = true;
  2272         while (token.kind != EOF) {
  2273             if (token.pos <= errorEndPos) {
  2274                 // error recovery
  2275                 skip(checkForImports, false, false, false);
  2276                 if (token.kind == EOF)
  2277                     break;
  2279             if (checkForImports && mods == null && token.kind == IMPORT) {
  2280                 seenImport = true;
  2281                 defs.append(importDeclaration());
  2282             } else {
  2283                 String docComment = token.comment(CommentStyle.JAVADOC);
  2284                 if (firstTypeDecl && !seenImport && !seenPackage) {
  2285                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  2286                     consumedToplevelDoc = true;
  2288                 JCTree def = typeDeclaration(mods, docComment);
  2289                 if (def instanceof JCExpressionStatement)
  2290                     def = ((JCExpressionStatement)def).expr;
  2291                 defs.append(def);
  2292                 if (def instanceof JCClassDecl)
  2293                     checkForImports = false;
  2294                 mods = null;
  2295                 firstTypeDecl = false;
  2298         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  2299         if (!consumedToplevelDoc)
  2300             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  2301         if (defs.elems.isEmpty())
  2302             storeEnd(toplevel, S.prevToken().endPos);
  2303         if (keepDocComments)
  2304             toplevel.docComments = docComments;
  2305         if (keepLineMap)
  2306             toplevel.lineMap = S.getLineMap();
  2307         return toplevel;
  2310     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2311      */
  2312     JCTree importDeclaration() {
  2313         int pos = token.pos;
  2314         nextToken();
  2315         boolean importStatic = false;
  2316         if (token.kind == STATIC) {
  2317             checkStaticImports();
  2318             importStatic = true;
  2319             nextToken();
  2321         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  2322         do {
  2323             int pos1 = token.pos;
  2324             accept(DOT);
  2325             if (token.kind == STAR) {
  2326                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2327                 nextToken();
  2328                 break;
  2329             } else {
  2330                 pid = toP(F.at(pos1).Select(pid, ident()));
  2332         } while (token.kind == DOT);
  2333         accept(SEMI);
  2334         return toP(F.at(pos).Import(pid, importStatic));
  2337     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2338      *                  | ";"
  2339      */
  2340     JCTree typeDeclaration(JCModifiers mods, String docComment) {
  2341         int pos = token.pos;
  2342         if (mods == null && token.kind == SEMI) {
  2343             nextToken();
  2344             return toP(F.at(pos).Skip());
  2345         } else {
  2346             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  2350     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2351      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2352      *  @param mods     Any modifiers starting the class or interface declaration
  2353      *  @param dc       The documentation comment for the class, or null.
  2354      */
  2355     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
  2356         if (token.kind == CLASS) {
  2357             return classDeclaration(mods, dc);
  2358         } else if (token.kind == INTERFACE) {
  2359             return interfaceDeclaration(mods, dc);
  2360         } else if (allowEnums) {
  2361             if (token.kind == ENUM) {
  2362                 return enumDeclaration(mods, dc);
  2363             } else {
  2364                 int pos = token.pos;
  2365                 List<JCTree> errs;
  2366                 if (token.kind == IDENTIFIER) {
  2367                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2368                     setErrorEndPos(token.pos);
  2369                 } else {
  2370                     errs = List.<JCTree>of(mods);
  2372                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2373                                               CLASS, INTERFACE, ENUM)));
  2375         } else {
  2376             if (token.kind == ENUM) {
  2377                 error(token.pos, "enums.not.supported.in.source", source.name);
  2378                 allowEnums = true;
  2379                 return enumDeclaration(mods, dc);
  2381             int pos = token.pos;
  2382             List<JCTree> errs;
  2383             if (token.kind == IDENTIFIER) {
  2384                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2385                 setErrorEndPos(token.pos);
  2386             } else {
  2387                 errs = List.<JCTree>of(mods);
  2389             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2390                                           CLASS, INTERFACE)));
  2394     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2395      *                     [IMPLEMENTS TypeList] ClassBody
  2396      *  @param mods    The modifiers starting the class declaration
  2397      *  @param dc       The documentation comment for the class, or null.
  2398      */
  2399     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
  2400         int pos = token.pos;
  2401         accept(CLASS);
  2402         Name name = ident();
  2404         List<JCTypeParameter> typarams = typeParametersOpt();
  2406         JCExpression extending = null;
  2407         if (token.kind == EXTENDS) {
  2408             nextToken();
  2409             extending = parseType();
  2411         List<JCExpression> implementing = List.nil();
  2412         if (token.kind == IMPLEMENTS) {
  2413             nextToken();
  2414             implementing = typeList();
  2416         List<JCTree> defs = classOrInterfaceBody(name, false);
  2417         JCClassDecl result = toP(F.at(pos).ClassDef(
  2418             mods, name, typarams, extending, implementing, defs));
  2419         attach(result, dc);
  2420         return result;
  2423     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2424      *                         [EXTENDS TypeList] InterfaceBody
  2425      *  @param mods    The modifiers starting the interface declaration
  2426      *  @param dc       The documentation comment for the interface, or null.
  2427      */
  2428     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
  2429         int pos = token.pos;
  2430         accept(INTERFACE);
  2431         Name name = ident();
  2433         List<JCTypeParameter> typarams = typeParametersOpt();
  2435         List<JCExpression> extending = List.nil();
  2436         if (token.kind == EXTENDS) {
  2437             nextToken();
  2438             extending = typeList();
  2440         List<JCTree> defs = classOrInterfaceBody(name, true);
  2441         JCClassDecl result = toP(F.at(pos).ClassDef(
  2442             mods, name, typarams, null, extending, defs));
  2443         attach(result, dc);
  2444         return result;
  2447     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2448      *  @param mods    The modifiers starting the enum declaration
  2449      *  @param dc       The documentation comment for the enum, or null.
  2450      */
  2451     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
  2452         int pos = token.pos;
  2453         accept(ENUM);
  2454         Name name = ident();
  2456         List<JCExpression> implementing = List.nil();
  2457         if (token.kind == IMPLEMENTS) {
  2458             nextToken();
  2459             implementing = typeList();
  2462         List<JCTree> defs = enumBody(name);
  2463         mods.flags |= Flags.ENUM;
  2464         JCClassDecl result = toP(F.at(pos).
  2465             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2466                 null, implementing, defs));
  2467         attach(result, dc);
  2468         return result;
  2471     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2472      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2473      */
  2474     List<JCTree> enumBody(Name enumName) {
  2475         accept(LBRACE);
  2476         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2477         if (token.kind == COMMA) {
  2478             nextToken();
  2479         } else if (token.kind != RBRACE && token.kind != SEMI) {
  2480             defs.append(enumeratorDeclaration(enumName));
  2481             while (token.kind == COMMA) {
  2482                 nextToken();
  2483                 if (token.kind == RBRACE || token.kind == SEMI) break;
  2484                 defs.append(enumeratorDeclaration(enumName));
  2486             if (token.kind != SEMI && token.kind != RBRACE) {
  2487                 defs.append(syntaxError(token.pos, "expected3",
  2488                                 COMMA, RBRACE, SEMI));
  2489                 nextToken();
  2492         if (token.kind == SEMI) {
  2493             nextToken();
  2494             while (token.kind != RBRACE && token.kind != EOF) {
  2495                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2496                                                                 false));
  2497                 if (token.pos <= errorEndPos) {
  2498                     // error recovery
  2499                    skip(false, true, true, false);
  2503         accept(RBRACE);
  2504         return defs.toList();
  2507     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2508      */
  2509     JCTree enumeratorDeclaration(Name enumName) {
  2510         String dc = token.comment(CommentStyle.JAVADOC);
  2511         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2512         if (token.deprecatedFlag()) {
  2513             flags |= Flags.DEPRECATED;
  2515         int pos = token.pos;
  2516         List<JCAnnotation> annotations = annotationsOpt();
  2517         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2518         List<JCExpression> typeArgs = typeArgumentsOpt();
  2519         int identPos = token.pos;
  2520         Name name = ident();
  2521         int createPos = token.pos;
  2522         List<JCExpression> args = (token.kind == LPAREN)
  2523             ? arguments() : List.<JCExpression>nil();
  2524         JCClassDecl body = null;
  2525         if (token.kind == LBRACE) {
  2526             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2527             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2528             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2530         if (args.isEmpty() && body == null)
  2531             createPos = identPos;
  2532         JCIdent ident = F.at(identPos).Ident(enumName);
  2533         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2534         if (createPos != identPos)
  2535             storeEnd(create, S.prevToken().endPos);
  2536         ident = F.at(identPos).Ident(enumName);
  2537         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2538         attach(result, dc);
  2539         return result;
  2542     /** TypeList = Type {"," Type}
  2543      */
  2544     List<JCExpression> typeList() {
  2545         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2546         ts.append(parseType());
  2547         while (token.kind == COMMA) {
  2548             nextToken();
  2549             ts.append(parseType());
  2551         return ts.toList();
  2554     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2555      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2556      */
  2557     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2558         accept(LBRACE);
  2559         if (token.pos <= errorEndPos) {
  2560             // error recovery
  2561             skip(false, true, false, false);
  2562             if (token.kind == LBRACE)
  2563                 nextToken();
  2565         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2566         while (token.kind != RBRACE && token.kind != EOF) {
  2567             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2568             if (token.pos <= errorEndPos) {
  2569                // error recovery
  2570                skip(false, true, true, false);
  2573         accept(RBRACE);
  2574         return defs.toList();
  2577     /** ClassBodyDeclaration =
  2578      *      ";"
  2579      *    | [STATIC] Block
  2580      *    | ModifiersOpt
  2581      *      ( Type Ident
  2582      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2583      *      | VOID Ident MethodDeclaratorRest
  2584      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2585      *      | Ident ConstructorDeclaratorRest
  2586      *      | TypeParameters Ident ConstructorDeclaratorRest
  2587      *      | ClassOrInterfaceOrEnumDeclaration
  2588      *      )
  2589      *  InterfaceBodyDeclaration =
  2590      *      ";"
  2591      *    | ModifiersOpt Type Ident
  2592      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2593      */
  2594     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2595         if (token.kind == SEMI) {
  2596             nextToken();
  2597             return List.<JCTree>nil();
  2598         } else {
  2599             String dc = token.comment(CommentStyle.JAVADOC);
  2600             int pos = token.pos;
  2601             JCModifiers mods = modifiersOpt();
  2602             if (token.kind == CLASS ||
  2603                 token.kind == INTERFACE ||
  2604                 allowEnums && token.kind == ENUM) {
  2605                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2606             } else if (token.kind == LBRACE && !isInterface &&
  2607                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2608                        mods.annotations.isEmpty()) {
  2609                 return List.<JCTree>of(block(pos, mods.flags));
  2610             } else {
  2611                 pos = token.pos;
  2612                 List<JCTypeParameter> typarams = typeParametersOpt();
  2613                 // if there are type parameters but no modifiers, save the start
  2614                 // position of the method in the modifiers.
  2615                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  2616                     mods.pos = pos;
  2617                     storeEnd(mods, pos);
  2619                 Token tk = token;
  2620                 pos = token.pos;
  2621                 JCExpression type;
  2622                 boolean isVoid = token.kind == VOID;
  2623                 if (isVoid) {
  2624                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  2625                     nextToken();
  2626                 } else {
  2627                     type = parseType();
  2629                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  2630                     if (isInterface || tk.name() != className)
  2631                         error(pos, "invalid.meth.decl.ret.type.req");
  2632                     return List.of(methodDeclaratorRest(
  2633                         pos, mods, null, names.init, typarams,
  2634                         isInterface, true, dc));
  2635                 } else {
  2636                     pos = token.pos;
  2637                     Name name = ident();
  2638                     if (token.kind == LPAREN) {
  2639                         return List.of(methodDeclaratorRest(
  2640                             pos, mods, type, name, typarams,
  2641                             isInterface, isVoid, dc));
  2642                     } else if (!isVoid && typarams.isEmpty()) {
  2643                         List<JCTree> defs =
  2644                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2645                                                     new ListBuffer<JCTree>()).toList();
  2646                         storeEnd(defs.last(), token.endPos);
  2647                         accept(SEMI);
  2648                         return defs;
  2649                     } else {
  2650                         pos = token.pos;
  2651                         List<JCTree> err = isVoid
  2652                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2653                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2654                             : null;
  2655                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  2662     /** MethodDeclaratorRest =
  2663      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2664      *  VoidMethodDeclaratorRest =
  2665      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  2666      *  InterfaceMethodDeclaratorRest =
  2667      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  2668      *  VoidInterfaceMethodDeclaratorRest =
  2669      *      FormalParameters [THROWS TypeList] ";"
  2670      *  ConstructorDeclaratorRest =
  2671      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  2672      */
  2673     JCTree methodDeclaratorRest(int pos,
  2674                               JCModifiers mods,
  2675                               JCExpression type,
  2676                               Name name,
  2677                               List<JCTypeParameter> typarams,
  2678                               boolean isInterface, boolean isVoid,
  2679                               String dc) {
  2680         List<JCVariableDecl> params = formalParameters();
  2681         if (!isVoid) type = bracketsOpt(type);
  2682         List<JCExpression> thrown = List.nil();
  2683         if (token.kind == THROWS) {
  2684             nextToken();
  2685             thrown = qualidentList();
  2687         JCBlock body = null;
  2688         JCExpression defaultValue;
  2689         if (token.kind == LBRACE) {
  2690             body = block();
  2691             defaultValue = null;
  2692         } else {
  2693             if (token.kind == DEFAULT) {
  2694                 accept(DEFAULT);
  2695                 defaultValue = annotationValue();
  2696             } else {
  2697                 defaultValue = null;
  2699             accept(SEMI);
  2700             if (token.pos <= errorEndPos) {
  2701                 // error recovery
  2702                 skip(false, true, false, false);
  2703                 if (token.kind == LBRACE) {
  2704                     body = block();
  2709         JCMethodDecl result =
  2710             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2711                                     params, thrown,
  2712                                     body, defaultValue));
  2713         attach(result, dc);
  2714         return result;
  2717     /** QualidentList = Qualident {"," Qualident}
  2718      */
  2719     List<JCExpression> qualidentList() {
  2720         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2721         ts.append(qualident());
  2722         while (token.kind == COMMA) {
  2723             nextToken();
  2724             ts.append(qualident());
  2726         return ts.toList();
  2729     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  2730      */
  2731     List<JCTypeParameter> typeParametersOpt() {
  2732         if (token.kind == LT) {
  2733             checkGenerics();
  2734             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  2735             nextToken();
  2736             typarams.append(typeParameter());
  2737             while (token.kind == COMMA) {
  2738                 nextToken();
  2739                 typarams.append(typeParameter());
  2741             accept(GT);
  2742             return typarams.toList();
  2743         } else {
  2744             return List.nil();
  2748     /** TypeParameter = TypeVariable [TypeParameterBound]
  2749      *  TypeParameterBound = EXTENDS Type {"&" Type}
  2750      *  TypeVariable = Ident
  2751      */
  2752     JCTypeParameter typeParameter() {
  2753         int pos = token.pos;
  2754         Name name = ident();
  2755         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  2756         if (token.kind == EXTENDS) {
  2757             nextToken();
  2758             bounds.append(parseType());
  2759             while (token.kind == AMP) {
  2760                 nextToken();
  2761                 bounds.append(parseType());
  2764         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  2767     /** FormalParameters = "(" [ FormalParameterList ] ")"
  2768      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  2769      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  2770      */
  2771     List<JCVariableDecl> formalParameters() {
  2772         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  2773         JCVariableDecl lastParam = null;
  2774         accept(LPAREN);
  2775         if (token.kind != RPAREN) {
  2776             params.append(lastParam = formalParameter());
  2777             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  2778                 nextToken();
  2779                 params.append(lastParam = formalParameter());
  2782         accept(RPAREN);
  2783         return params.toList();
  2786     JCModifiers optFinal(long flags) {
  2787         JCModifiers mods = modifiersOpt();
  2788         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  2789         mods.flags |= flags;
  2790         return mods;
  2793     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  2794      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  2795      */
  2796     protected JCVariableDecl formalParameter() {
  2797         JCModifiers mods = optFinal(Flags.PARAMETER);
  2798         JCExpression type = parseType();
  2799         if (token.kind == ELLIPSIS) {
  2800             checkVarargs();
  2801             mods.flags |= Flags.VARARGS;
  2802             type = to(F.at(token.pos).TypeArray(type));
  2803             nextToken();
  2805         return variableDeclaratorId(mods, type);
  2808 /* ---------- auxiliary methods -------------- */
  2810     void error(int pos, String key, Object ... args) {
  2811         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  2814     void error(DiagnosticPosition pos, String key, Object ... args) {
  2815         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  2818     void warning(int pos, String key, Object ... args) {
  2819         log.warning(pos, key, args);
  2822     /** Check that given tree is a legal expression statement.
  2823      */
  2824     protected JCExpression checkExprStat(JCExpression t) {
  2825         switch(t.getTag()) {
  2826         case PREINC: case PREDEC:
  2827         case POSTINC: case POSTDEC:
  2828         case ASSIGN:
  2829         case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
  2830         case SL_ASG: case SR_ASG: case USR_ASG:
  2831         case PLUS_ASG: case MINUS_ASG:
  2832         case MUL_ASG: case DIV_ASG: case MOD_ASG:
  2833         case APPLY: case NEWCLASS:
  2834         case ERRONEOUS:
  2835             return t;
  2836         default:
  2837             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  2838             error(ret, "not.stmt");
  2839             return ret;
  2843     /** Return precedence of operator represented by token,
  2844      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  2845      */
  2846     static int prec(TokenKind token) {
  2847         JCTree.Tag oc = optag(token);
  2848         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  2851     /**
  2852      * Return the lesser of two positions, making allowance for either one
  2853      * being unset.
  2854      */
  2855     static int earlier(int pos1, int pos2) {
  2856         if (pos1 == Position.NOPOS)
  2857             return pos2;
  2858         if (pos2 == Position.NOPOS)
  2859             return pos1;
  2860         return (pos1 < pos2 ? pos1 : pos2);
  2863     /** Return operation tag of binary operator represented by token,
  2864      *  No_TAG if token is not a binary operator.
  2865      */
  2866     static JCTree.Tag optag(TokenKind token) {
  2867         switch (token) {
  2868         case BARBAR:
  2869             return OR;
  2870         case AMPAMP:
  2871             return AND;
  2872         case BAR:
  2873             return BITOR;
  2874         case BAREQ:
  2875             return BITOR_ASG;
  2876         case CARET:
  2877             return BITXOR;
  2878         case CARETEQ:
  2879             return BITXOR_ASG;
  2880         case AMP:
  2881             return BITAND;
  2882         case AMPEQ:
  2883             return BITAND_ASG;
  2884         case EQEQ:
  2885             return JCTree.Tag.EQ;
  2886         case BANGEQ:
  2887             return NE;
  2888         case LT:
  2889             return JCTree.Tag.LT;
  2890         case GT:
  2891             return JCTree.Tag.GT;
  2892         case LTEQ:
  2893             return LE;
  2894         case GTEQ:
  2895             return GE;
  2896         case LTLT:
  2897             return SL;
  2898         case LTLTEQ:
  2899             return SL_ASG;
  2900         case GTGT:
  2901             return SR;
  2902         case GTGTEQ:
  2903             return SR_ASG;
  2904         case GTGTGT:
  2905             return USR;
  2906         case GTGTGTEQ:
  2907             return USR_ASG;
  2908         case PLUS:
  2909             return JCTree.Tag.PLUS;
  2910         case PLUSEQ:
  2911             return PLUS_ASG;
  2912         case SUB:
  2913             return MINUS;
  2914         case SUBEQ:
  2915             return MINUS_ASG;
  2916         case STAR:
  2917             return MUL;
  2918         case STAREQ:
  2919             return MUL_ASG;
  2920         case SLASH:
  2921             return DIV;
  2922         case SLASHEQ:
  2923             return DIV_ASG;
  2924         case PERCENT:
  2925             return MOD;
  2926         case PERCENTEQ:
  2927             return MOD_ASG;
  2928         case INSTANCEOF:
  2929             return TYPETEST;
  2930         default:
  2931             return NO_TAG;
  2935     /** Return operation tag of unary operator represented by token,
  2936      *  No_TAG if token is not a binary operator.
  2937      */
  2938     static JCTree.Tag unoptag(TokenKind token) {
  2939         switch (token) {
  2940         case PLUS:
  2941             return POS;
  2942         case SUB:
  2943             return NEG;
  2944         case BANG:
  2945             return NOT;
  2946         case TILDE:
  2947             return COMPL;
  2948         case PLUSPLUS:
  2949             return PREINC;
  2950         case SUBSUB:
  2951             return PREDEC;
  2952         default:
  2953             return NO_TAG;
  2957     /** Return type tag of basic type represented by token,
  2958      *  -1 if token is not a basic type identifier.
  2959      */
  2960     static int typetag(TokenKind token) {
  2961         switch (token) {
  2962         case BYTE:
  2963             return TypeTags.BYTE;
  2964         case CHAR:
  2965             return TypeTags.CHAR;
  2966         case SHORT:
  2967             return TypeTags.SHORT;
  2968         case INT:
  2969             return TypeTags.INT;
  2970         case LONG:
  2971             return TypeTags.LONG;
  2972         case FLOAT:
  2973             return TypeTags.FLOAT;
  2974         case DOUBLE:
  2975             return TypeTags.DOUBLE;
  2976         case BOOLEAN:
  2977             return TypeTags.BOOLEAN;
  2978         default:
  2979             return -1;
  2983     void checkGenerics() {
  2984         if (!allowGenerics) {
  2985             error(token.pos, "generics.not.supported.in.source", source.name);
  2986             allowGenerics = true;
  2989     void checkVarargs() {
  2990         if (!allowVarargs) {
  2991             error(token.pos, "varargs.not.supported.in.source", source.name);
  2992             allowVarargs = true;
  2995     void checkForeach() {
  2996         if (!allowForeach) {
  2997             error(token.pos, "foreach.not.supported.in.source", source.name);
  2998             allowForeach = true;
  3001     void checkStaticImports() {
  3002         if (!allowStaticImport) {
  3003             error(token.pos, "static.import.not.supported.in.source", source.name);
  3004             allowStaticImport = true;
  3007     void checkAnnotations() {
  3008         if (!allowAnnotations) {
  3009             error(token.pos, "annotations.not.supported.in.source", source.name);
  3010             allowAnnotations = true;
  3013     void checkDiamond() {
  3014         if (!allowDiamond) {
  3015             error(token.pos, "diamond.not.supported.in.source", source.name);
  3016             allowDiamond = true;
  3019     void checkMulticatch() {
  3020         if (!allowMulticatch) {
  3021             error(token.pos, "multicatch.not.supported.in.source", source.name);
  3022             allowMulticatch = true;
  3025     void checkTryWithResources() {
  3026         if (!allowTWR) {
  3027             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  3028             allowTWR = true;

mercurial