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

Fri, 04 Nov 2011 12:36:40 +0000

author
mcimadamore
date
Fri, 04 Nov 2011 12:36:40 +0000
changeset 1125
56830d5cb5bb
parent 1113
d346ab55031b
child 1127
ca49d50318dc
permissions
-rw-r--r--

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

mercurial