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

Mon, 14 Nov 2011 15:11:10 -0800

author
ksrini
date
Mon, 14 Nov 2011 15:11:10 -0800
changeset 1138
7375d4979bd3
parent 1127
ca49d50318dc
child 1144
9448fe783fd2
permissions
-rw-r--r--

7106166: (javac) re-factor EndPos parser
Reviewed-by: jjg

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

mercurial