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

Wed, 06 Apr 2011 19:30:57 -0700

author
darcy
date
Wed, 06 Apr 2011 19:30:57 -0700
changeset 969
8cc5b440fdde
parent 948
2007998f89f2
child 1061
e427c42e1a7e
permissions
-rw-r--r--

7033809: Rename "disjunctive" to "union" in javax.lang.model
Reviewed-by: mcimadamore, jjg

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

mercurial