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

changeset 1
9a66ca7c79fa
child 26
25338c55e458
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/javac/parser/Parser.java	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,2863 @@
     1.4 +/*
     1.5 + * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Sun designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Sun in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.26 + * have any questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.tools.javac.parser;
    1.30 +
    1.31 +import java.util.*;
    1.32 +
    1.33 +import com.sun.tools.javac.tree.*;
    1.34 +import com.sun.tools.javac.code.*;
    1.35 +import com.sun.tools.javac.util.*;
    1.36 +import com.sun.tools.javac.util.List;
    1.37 +import static com.sun.tools.javac.util.ListBuffer.lb;
    1.38 +
    1.39 +import com.sun.tools.javac.tree.JCTree.*;
    1.40 +
    1.41 +import static com.sun.tools.javac.parser.Token.*;
    1.42 +
    1.43 +/** The parser maps a token sequence into an abstract syntax
    1.44 + *  tree. It operates by recursive descent, with code derived
    1.45 + *  systematically from an LL(1) grammar. For efficiency reasons, an
    1.46 + *  operator precedence scheme is used for parsing binary operation
    1.47 + *  expressions.
    1.48 + *
    1.49 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    1.50 + *  you write code that depends on this, you do so at your own risk.
    1.51 + *  This code and its internal interfaces are subject to change or
    1.52 + *  deletion without notice.</b>
    1.53 + */
    1.54 +public class Parser {
    1.55 +
    1.56 +    /** A factory for creating parsers. */
    1.57 +    public static class Factory {
    1.58 +        /** The context key for the parser factory. */
    1.59 +        protected static final Context.Key<Parser.Factory> parserFactoryKey =
    1.60 +            new Context.Key<Parser.Factory>();
    1.61 +
    1.62 +        /** Get the Factory instance for this context. */
    1.63 +        public static Factory instance(Context context) {
    1.64 +            Factory instance = context.get(parserFactoryKey);
    1.65 +            if (instance == null)
    1.66 +                instance = new Factory(context);
    1.67 +            return instance;
    1.68 +        }
    1.69 +
    1.70 +        final TreeMaker F;
    1.71 +        final Log log;
    1.72 +        final Keywords keywords;
    1.73 +        final Source source;
    1.74 +        final Name.Table names;
    1.75 +        final Options options;
    1.76 +
    1.77 +        /** Create a new parser factory. */
    1.78 +        protected Factory(Context context) {
    1.79 +            context.put(parserFactoryKey, this);
    1.80 +            this.F = TreeMaker.instance(context);
    1.81 +            this.log = Log.instance(context);
    1.82 +            this.names = Name.Table.instance(context);
    1.83 +            this.keywords = Keywords.instance(context);
    1.84 +            this.source = Source.instance(context);
    1.85 +            this.options = Options.instance(context);
    1.86 +        }
    1.87 +
    1.88 +        /**
    1.89 +         * Create a new Parser.
    1.90 +         * @param S Lexer for getting tokens while parsing
    1.91 +         * @param keepDocComments true if javadoc comments should be kept
    1.92 +         * @param genEndPos true if end positions should be generated
    1.93 +         */
    1.94 +        public Parser newParser(Lexer S, boolean keepDocComments, boolean genEndPos) {
    1.95 +            if (!genEndPos)
    1.96 +                return new Parser(this, S, keepDocComments);
    1.97 +            else
    1.98 +                return new EndPosParser(this, S, keepDocComments);
    1.99 +        }
   1.100 +    }
   1.101 +
   1.102 +    /** The number of precedence levels of infix operators.
   1.103 +     */
   1.104 +    private static final int infixPrecedenceLevels = 10;
   1.105 +
   1.106 +    /** The scanner used for lexical analysis.
   1.107 +     */
   1.108 +    private Lexer S;
   1.109 +
   1.110 +    /** The factory to be used for abstract syntax tree construction.
   1.111 +     */
   1.112 +    protected TreeMaker F;
   1.113 +
   1.114 +    /** The log to be used for error diagnostics.
   1.115 +     */
   1.116 +    private Log log;
   1.117 +
   1.118 +    /** The keyword table. */
   1.119 +    private Keywords keywords;
   1.120 +
   1.121 +    /** The Source language setting. */
   1.122 +    private Source source;
   1.123 +
   1.124 +    /** The name table. */
   1.125 +    private Name.Table names;
   1.126 +
   1.127 +    /** Construct a parser from a given scanner, tree factory and log.
   1.128 +     */
   1.129 +    protected Parser(Factory fac,
   1.130 +                     Lexer S,
   1.131 +                     boolean keepDocComments) {
   1.132 +        this.S = S;
   1.133 +        S.nextToken(); // prime the pump
   1.134 +        this.F = fac.F;
   1.135 +        this.log = fac.log;
   1.136 +        this.names = fac.names;
   1.137 +        this.keywords = fac.keywords;
   1.138 +        this.source = fac.source;
   1.139 +        Options options = fac.options;
   1.140 +        this.allowGenerics = source.allowGenerics();
   1.141 +        this.allowVarargs = source.allowVarargs();
   1.142 +        this.allowAsserts = source.allowAsserts();
   1.143 +        this.allowEnums = source.allowEnums();
   1.144 +        this.allowForeach = source.allowForeach();
   1.145 +        this.allowStaticImport = source.allowStaticImport();
   1.146 +        this.allowAnnotations = source.allowAnnotations();
   1.147 +        this.keepDocComments = keepDocComments;
   1.148 +        if (keepDocComments) docComments = new HashMap<JCTree,String>();
   1.149 +        this.errorTree = F.Erroneous();
   1.150 +    }
   1.151 +
   1.152 +    /** Switch: Should generics be recognized?
   1.153 +     */
   1.154 +    boolean allowGenerics;
   1.155 +
   1.156 +    /** Switch: Should varargs be recognized?
   1.157 +     */
   1.158 +    boolean allowVarargs;
   1.159 +
   1.160 +    /** Switch: should we recognize assert statements, or just give a warning?
   1.161 +     */
   1.162 +    boolean allowAsserts;
   1.163 +
   1.164 +    /** Switch: should we recognize enums, or just give a warning?
   1.165 +     */
   1.166 +    boolean allowEnums;
   1.167 +
   1.168 +    /** Switch: should we recognize foreach?
   1.169 +     */
   1.170 +    boolean allowForeach;
   1.171 +
   1.172 +    /** Switch: should we recognize foreach?
   1.173 +     */
   1.174 +    boolean allowStaticImport;
   1.175 +
   1.176 +    /** Switch: should we recognize annotations?
   1.177 +     */
   1.178 +    boolean allowAnnotations;
   1.179 +
   1.180 +    /** Switch: should we keep docComments?
   1.181 +     */
   1.182 +    boolean keepDocComments;
   1.183 +
   1.184 +    /** When terms are parsed, the mode determines which is expected:
   1.185 +     *     mode = EXPR        : an expression
   1.186 +     *     mode = TYPE        : a type
   1.187 +     *     mode = NOPARAMS    : no parameters allowed for type
   1.188 +     *     mode = TYPEARG     : type argument
   1.189 +     */
   1.190 +    static final int EXPR = 1;
   1.191 +    static final int TYPE = 2;
   1.192 +    static final int NOPARAMS = 4;
   1.193 +    static final int TYPEARG = 8;
   1.194 +
   1.195 +    /** The current mode.
   1.196 +     */
   1.197 +    private int mode = 0;
   1.198 +
   1.199 +    /** The mode of the term that was parsed last.
   1.200 +     */
   1.201 +    private int lastmode = 0;
   1.202 +
   1.203 +/* ---------- error recovery -------------- */
   1.204 +
   1.205 +    private JCErroneous errorTree;
   1.206 +
   1.207 +    /** Skip forward until a suitable stop token is found.
   1.208 +     */
   1.209 +    private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   1.210 +         while (true) {
   1.211 +             switch (S.token()) {
   1.212 +                case SEMI:
   1.213 +                    S.nextToken();
   1.214 +                    return;
   1.215 +                case PUBLIC:
   1.216 +                case FINAL:
   1.217 +                case ABSTRACT:
   1.218 +                case MONKEYS_AT:
   1.219 +                case EOF:
   1.220 +                case CLASS:
   1.221 +                case INTERFACE:
   1.222 +                case ENUM:
   1.223 +                    return;
   1.224 +                case IMPORT:
   1.225 +                    if (stopAtImport)
   1.226 +                        return;
   1.227 +                    break;
   1.228 +                case LBRACE:
   1.229 +                case RBRACE:
   1.230 +                case PRIVATE:
   1.231 +                case PROTECTED:
   1.232 +                case STATIC:
   1.233 +                case TRANSIENT:
   1.234 +                case NATIVE:
   1.235 +                case VOLATILE:
   1.236 +                case SYNCHRONIZED:
   1.237 +                case STRICTFP:
   1.238 +                case LT:
   1.239 +                case BYTE:
   1.240 +                case SHORT:
   1.241 +                case CHAR:
   1.242 +                case INT:
   1.243 +                case LONG:
   1.244 +                case FLOAT:
   1.245 +                case DOUBLE:
   1.246 +                case BOOLEAN:
   1.247 +                case VOID:
   1.248 +                    if (stopAtMemberDecl)
   1.249 +                        return;
   1.250 +                    break;
   1.251 +                case IDENTIFIER:
   1.252 +                   if (stopAtIdentifier)
   1.253 +                        return;
   1.254 +                    break;
   1.255 +                case CASE:
   1.256 +                case DEFAULT:
   1.257 +                case IF:
   1.258 +                case FOR:
   1.259 +                case WHILE:
   1.260 +                case DO:
   1.261 +                case TRY:
   1.262 +                case SWITCH:
   1.263 +                case RETURN:
   1.264 +                case THROW:
   1.265 +                case BREAK:
   1.266 +                case CONTINUE:
   1.267 +                case ELSE:
   1.268 +                case FINALLY:
   1.269 +                case CATCH:
   1.270 +                    if (stopAtStatement)
   1.271 +                        return;
   1.272 +                    break;
   1.273 +            }
   1.274 +            S.nextToken();
   1.275 +        }
   1.276 +    }
   1.277 +
   1.278 +    private JCErroneous syntaxError(int pos, String key, Object... arg) {
   1.279 +        return syntaxError(pos, null, key, arg);
   1.280 +    }
   1.281 +
   1.282 +    private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Object... arg) {
   1.283 +        setErrorEndPos(pos);
   1.284 +        reportSyntaxError(pos, key, arg);
   1.285 +        return toP(F.at(pos).Erroneous(errs));
   1.286 +    }
   1.287 +
   1.288 +    private int errorPos = Position.NOPOS;
   1.289 +    /**
   1.290 +     * Report a syntax error at given position using the given
   1.291 +     * argument unless one was already reported at the same position.
   1.292 +     */
   1.293 +    private void reportSyntaxError(int pos, String key, Object... arg) {
   1.294 +        if (pos > S.errPos() || pos == Position.NOPOS) {
   1.295 +            if (S.token() == EOF)
   1.296 +                log.error(pos, "premature.eof");
   1.297 +            else
   1.298 +                log.error(pos, key, arg);
   1.299 +        }
   1.300 +        S.errPos(pos);
   1.301 +        if (S.pos() == errorPos)
   1.302 +            S.nextToken(); // guarantee progress
   1.303 +        errorPos = S.pos();
   1.304 +    }
   1.305 +
   1.306 +
   1.307 +    /** Generate a syntax error at current position unless one was already
   1.308 +     *  reported at the same position.
   1.309 +     */
   1.310 +    private JCErroneous syntaxError(String key) {
   1.311 +        return syntaxError(S.pos(), key);
   1.312 +    }
   1.313 +
   1.314 +    /** Generate a syntax error at current position unless one was
   1.315 +     *  already reported at the same position.
   1.316 +     */
   1.317 +    private JCErroneous syntaxError(String key, String arg) {
   1.318 +        return syntaxError(S.pos(), key, arg);
   1.319 +    }
   1.320 +
   1.321 +    /** If next input token matches given token, skip it, otherwise report
   1.322 +     *  an error.
   1.323 +     */
   1.324 +    public void accept(Token token) {
   1.325 +        if (S.token() == token) {
   1.326 +            S.nextToken();
   1.327 +        } else {
   1.328 +            setErrorEndPos(S.pos());
   1.329 +            reportSyntaxError(S.prevEndPos(), "expected", keywords.token2string(token));
   1.330 +        }
   1.331 +    }
   1.332 +
   1.333 +    /** Report an illegal start of expression/type error at given position.
   1.334 +     */
   1.335 +    JCExpression illegal(int pos) {
   1.336 +        setErrorEndPos(S.pos());
   1.337 +        if ((mode & EXPR) != 0)
   1.338 +            return syntaxError(pos, "illegal.start.of.expr");
   1.339 +        else
   1.340 +            return syntaxError(pos, "illegal.start.of.type");
   1.341 +
   1.342 +    }
   1.343 +
   1.344 +    /** Report an illegal start of expression/type error at current position.
   1.345 +     */
   1.346 +    JCExpression illegal() {
   1.347 +        return illegal(S.pos());
   1.348 +    }
   1.349 +
   1.350 +    /** Diagnose a modifier flag from the set, if any. */
   1.351 +    void checkNoMods(long mods) {
   1.352 +        if (mods != 0) {
   1.353 +            long lowestMod = mods & -mods;
   1.354 +            log.error(S.pos(), "mod.not.allowed.here",
   1.355 +                      Flags.toString(lowestMod).trim());
   1.356 +        }
   1.357 +    }
   1.358 +
   1.359 +/* ---------- doc comments --------- */
   1.360 +
   1.361 +    /** A hashtable to store all documentation comments
   1.362 +     *  indexed by the tree nodes they refer to.
   1.363 +     *  defined only if option flag keepDocComment is set.
   1.364 +     */
   1.365 +    Map<JCTree, String> docComments;
   1.366 +
   1.367 +    /** Make an entry into docComments hashtable,
   1.368 +     *  provided flag keepDocComments is set and given doc comment is non-null.
   1.369 +     *  @param tree   The tree to be used as index in the hashtable
   1.370 +     *  @param dc     The doc comment to associate with the tree, or null.
   1.371 +     */
   1.372 +    void attach(JCTree tree, String dc) {
   1.373 +        if (keepDocComments && dc != null) {
   1.374 +//          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   1.375 +            docComments.put(tree, dc);
   1.376 +        }
   1.377 +    }
   1.378 +
   1.379 +/* -------- source positions ------- */
   1.380 +
   1.381 +    private int errorEndPos = -1;
   1.382 +
   1.383 +    private void setErrorEndPos(int errPos) {
   1.384 +        if (errPos > errorEndPos)
   1.385 +            errorEndPos = errPos;
   1.386 +    }
   1.387 +
   1.388 +    protected int getErrorEndPos() {
   1.389 +        return errorEndPos;
   1.390 +    }
   1.391 +
   1.392 +    /**
   1.393 +     * Store ending position for a tree.
   1.394 +     * @param tree   The tree.
   1.395 +     * @param endpos The ending position to associate with the tree.
   1.396 +     */
   1.397 +    protected void storeEnd(JCTree tree, int endpos) {}
   1.398 +
   1.399 +    /**
   1.400 +     * Store ending position for a tree.  The ending position should
   1.401 +     * be the ending position of the current token.
   1.402 +     * @param t The tree.
   1.403 +     */
   1.404 +    protected <T extends JCTree> T to(T t) { return t; }
   1.405 +
   1.406 +    /**
   1.407 +     * Store ending position for a tree.  The ending position should
   1.408 +     * be greater of the ending position of the previous token and errorEndPos.
   1.409 +     * @param t The tree.
   1.410 +     */
   1.411 +    protected <T extends JCTree> T toP(T t) { return t; }
   1.412 +
   1.413 +    /** Get the start position for a tree node.  The start position is
   1.414 +     * defined to be the position of the first character of the first
   1.415 +     * token of the node's source text.
   1.416 +     * @param tree  The tree node
   1.417 +     */
   1.418 +    public int getStartPos(JCTree tree) {
   1.419 +        return TreeInfo.getStartPos(tree);
   1.420 +    }
   1.421 +
   1.422 +    /**
   1.423 +     * Get the end position for a tree node.  The end position is
   1.424 +     * defined to be the position of the last character of the last
   1.425 +     * token of the node's source text.  Returns Position.NOPOS if end
   1.426 +     * positions are not generated or the position is otherwise not
   1.427 +     * found.
   1.428 +     * @param tree  The tree node
   1.429 +     */
   1.430 +    public int getEndPos(JCTree tree) {
   1.431 +        return Position.NOPOS;
   1.432 +    }
   1.433 +
   1.434 +
   1.435 +
   1.436 +/* ---------- parsing -------------- */
   1.437 +
   1.438 +    /**
   1.439 +     * Ident = IDENTIFIER
   1.440 +     */
   1.441 +    Name ident() {
   1.442 +        if (S.token() == IDENTIFIER) {
   1.443 +            Name name = S.name();
   1.444 +            S.nextToken();
   1.445 +            return name;
   1.446 +        } else if (S.token() == ASSERT) {
   1.447 +            if (allowAsserts) {
   1.448 +                log.error(S.pos(), "assert.as.identifier");
   1.449 +                S.nextToken();
   1.450 +                return names.error;
   1.451 +            } else {
   1.452 +                log.warning(S.pos(), "assert.as.identifier");
   1.453 +                Name name = S.name();
   1.454 +                S.nextToken();
   1.455 +                return name;
   1.456 +            }
   1.457 +        } else if (S.token() == ENUM) {
   1.458 +            if (allowEnums) {
   1.459 +                log.error(S.pos(), "enum.as.identifier");
   1.460 +                S.nextToken();
   1.461 +                return names.error;
   1.462 +            } else {
   1.463 +                log.warning(S.pos(), "enum.as.identifier");
   1.464 +                Name name = S.name();
   1.465 +                S.nextToken();
   1.466 +                return name;
   1.467 +            }
   1.468 +        } else {
   1.469 +            accept(IDENTIFIER);
   1.470 +            return names.error;
   1.471 +        }
   1.472 +}
   1.473 +
   1.474 +    /**
   1.475 +     * Qualident = Ident { DOT Ident }
   1.476 +     */
   1.477 +    public JCExpression qualident() {
   1.478 +        JCExpression t = toP(F.at(S.pos()).Ident(ident()));
   1.479 +        while (S.token() == DOT) {
   1.480 +            int pos = S.pos();
   1.481 +            S.nextToken();
   1.482 +            t = toP(F.at(pos).Select(t, ident()));
   1.483 +        }
   1.484 +        return t;
   1.485 +    }
   1.486 +
   1.487 +    /**
   1.488 +     * Literal =
   1.489 +     *     INTLITERAL
   1.490 +     *   | LONGLITERAL
   1.491 +     *   | FLOATLITERAL
   1.492 +     *   | DOUBLELITERAL
   1.493 +     *   | CHARLITERAL
   1.494 +     *   | STRINGLITERAL
   1.495 +     *   | TRUE
   1.496 +     *   | FALSE
   1.497 +     *   | NULL
   1.498 +     */
   1.499 +    JCExpression literal(Name prefix) {
   1.500 +        int pos = S.pos();
   1.501 +        JCExpression t = errorTree;
   1.502 +        switch (S.token()) {
   1.503 +        case INTLITERAL:
   1.504 +            try {
   1.505 +                t = F.at(pos).Literal(
   1.506 +                    TypeTags.INT,
   1.507 +                    Convert.string2int(strval(prefix), S.radix()));
   1.508 +            } catch (NumberFormatException ex) {
   1.509 +                log.error(S.pos(), "int.number.too.large", strval(prefix));
   1.510 +            }
   1.511 +            break;
   1.512 +        case LONGLITERAL:
   1.513 +            try {
   1.514 +                t = F.at(pos).Literal(
   1.515 +                    TypeTags.LONG,
   1.516 +                    new Long(Convert.string2long(strval(prefix), S.radix())));
   1.517 +            } catch (NumberFormatException ex) {
   1.518 +                log.error(S.pos(), "int.number.too.large", strval(prefix));
   1.519 +            }
   1.520 +            break;
   1.521 +        case FLOATLITERAL: {
   1.522 +            String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
   1.523 +            Float n;
   1.524 +            try {
   1.525 +                n = Float.valueOf(proper);
   1.526 +            } catch (NumberFormatException ex) {
   1.527 +                // error already repoted in scanner
   1.528 +                n = Float.NaN;
   1.529 +            }
   1.530 +            if (n.floatValue() == 0.0f && !isZero(proper))
   1.531 +                log.error(S.pos(), "fp.number.too.small");
   1.532 +            else if (n.floatValue() == Float.POSITIVE_INFINITY)
   1.533 +                log.error(S.pos(), "fp.number.too.large");
   1.534 +            else
   1.535 +                t = F.at(pos).Literal(TypeTags.FLOAT, n);
   1.536 +            break;
   1.537 +        }
   1.538 +        case DOUBLELITERAL: {
   1.539 +            String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
   1.540 +            Double n;
   1.541 +            try {
   1.542 +                n = Double.valueOf(proper);
   1.543 +            } catch (NumberFormatException ex) {
   1.544 +                // error already reported in scanner
   1.545 +                n = Double.NaN;
   1.546 +            }
   1.547 +            if (n.doubleValue() == 0.0d && !isZero(proper))
   1.548 +                log.error(S.pos(), "fp.number.too.small");
   1.549 +            else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   1.550 +                log.error(S.pos(), "fp.number.too.large");
   1.551 +            else
   1.552 +                t = F.at(pos).Literal(TypeTags.DOUBLE, n);
   1.553 +            break;
   1.554 +        }
   1.555 +        case CHARLITERAL:
   1.556 +            t = F.at(pos).Literal(
   1.557 +                TypeTags.CHAR,
   1.558 +                S.stringVal().charAt(0) + 0);
   1.559 +            break;
   1.560 +        case STRINGLITERAL:
   1.561 +            t = F.at(pos).Literal(
   1.562 +                TypeTags.CLASS,
   1.563 +                S.stringVal());
   1.564 +            break;
   1.565 +        case TRUE: case FALSE:
   1.566 +            t = F.at(pos).Literal(
   1.567 +                TypeTags.BOOLEAN,
   1.568 +                (S.token() == TRUE ? 1 : 0));
   1.569 +            break;
   1.570 +        case NULL:
   1.571 +            t = F.at(pos).Literal(
   1.572 +                TypeTags.BOT,
   1.573 +                null);
   1.574 +            break;
   1.575 +        default:
   1.576 +            assert false;
   1.577 +        }
   1.578 +        if (t == errorTree)
   1.579 +            t = F.at(pos).Erroneous();
   1.580 +        storeEnd(t, S.endPos());
   1.581 +        S.nextToken();
   1.582 +        return t;
   1.583 +    }
   1.584 +//where
   1.585 +        boolean isZero(String s) {
   1.586 +            char[] cs = s.toCharArray();
   1.587 +            int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10);
   1.588 +            int i = ((base==16) ? 2 : 0);
   1.589 +            while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   1.590 +            return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   1.591 +        }
   1.592 +
   1.593 +        String strval(Name prefix) {
   1.594 +            String s = S.stringVal();
   1.595 +            return (prefix.len == 0) ? s : prefix + s;
   1.596 +        }
   1.597 +
   1.598 +    /** terms can be either expressions or types.
   1.599 +     */
   1.600 +    public JCExpression expression() {
   1.601 +        return term(EXPR);
   1.602 +    }
   1.603 +
   1.604 +    public JCExpression type() {
   1.605 +        return term(TYPE);
   1.606 +    }
   1.607 +
   1.608 +    JCExpression term(int newmode) {
   1.609 +        int prevmode = mode;
   1.610 +        mode = newmode;
   1.611 +        JCExpression t = term();
   1.612 +        lastmode = mode;
   1.613 +        mode = prevmode;
   1.614 +        return t;
   1.615 +    }
   1.616 +
   1.617 +    /**
   1.618 +     *  Expression = Expression1 [ExpressionRest]
   1.619 +     *  ExpressionRest = [AssignmentOperator Expression1]
   1.620 +     *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   1.621 +     *                       "&=" | "|=" | "^=" |
   1.622 +     *                       "%=" | "<<=" | ">>=" | ">>>="
   1.623 +     *  Type = Type1
   1.624 +     *  TypeNoParams = TypeNoParams1
   1.625 +     *  StatementExpression = Expression
   1.626 +     *  ConstantExpression = Expression
   1.627 +     */
   1.628 +    JCExpression term() {
   1.629 +        JCExpression t = term1();
   1.630 +        if ((mode & EXPR) != 0 &&
   1.631 +            S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
   1.632 +            return termRest(t);
   1.633 +        else
   1.634 +            return t;
   1.635 +    }
   1.636 +
   1.637 +    JCExpression termRest(JCExpression t) {
   1.638 +        switch (S.token()) {
   1.639 +        case EQ: {
   1.640 +            int pos = S.pos();
   1.641 +            S.nextToken();
   1.642 +            mode = EXPR;
   1.643 +            JCExpression t1 = term();
   1.644 +            return toP(F.at(pos).Assign(t, t1));
   1.645 +        }
   1.646 +        case PLUSEQ:
   1.647 +        case SUBEQ:
   1.648 +        case STAREQ:
   1.649 +        case SLASHEQ:
   1.650 +        case PERCENTEQ:
   1.651 +        case AMPEQ:
   1.652 +        case BAREQ:
   1.653 +        case CARETEQ:
   1.654 +        case LTLTEQ:
   1.655 +        case GTGTEQ:
   1.656 +        case GTGTGTEQ:
   1.657 +            int pos = S.pos();
   1.658 +            Token token = S.token();
   1.659 +            S.nextToken();
   1.660 +            mode = EXPR;
   1.661 +            JCExpression t1 = term();
   1.662 +            return F.at(pos).Assignop(optag(token), t, t1);
   1.663 +        default:
   1.664 +            return t;
   1.665 +        }
   1.666 +    }
   1.667 +
   1.668 +    /** Expression1   = Expression2 [Expression1Rest]
   1.669 +     *  Type1         = Type2
   1.670 +     *  TypeNoParams1 = TypeNoParams2
   1.671 +     */
   1.672 +    JCExpression term1() {
   1.673 +        JCExpression t = term2();
   1.674 +        if ((mode & EXPR) != 0 && S.token() == QUES) {
   1.675 +            mode = EXPR;
   1.676 +            return term1Rest(t);
   1.677 +        } else {
   1.678 +            return t;
   1.679 +        }
   1.680 +    }
   1.681 +
   1.682 +    /** Expression1Rest = ["?" Expression ":" Expression1]
   1.683 +     */
   1.684 +    JCExpression term1Rest(JCExpression t) {
   1.685 +        if (S.token() == QUES) {
   1.686 +            int pos = S.pos();
   1.687 +            S.nextToken();
   1.688 +            JCExpression t1 = term();
   1.689 +            accept(COLON);
   1.690 +            JCExpression t2 = term1();
   1.691 +            return F.at(pos).Conditional(t, t1, t2);
   1.692 +        } else {
   1.693 +            return t;
   1.694 +        }
   1.695 +    }
   1.696 +
   1.697 +    /** Expression2   = Expression3 [Expression2Rest]
   1.698 +     *  Type2         = Type3
   1.699 +     *  TypeNoParams2 = TypeNoParams3
   1.700 +     */
   1.701 +    JCExpression term2() {
   1.702 +        JCExpression t = term3();
   1.703 +        if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
   1.704 +            mode = EXPR;
   1.705 +            return term2Rest(t, TreeInfo.orPrec);
   1.706 +        } else {
   1.707 +            return t;
   1.708 +        }
   1.709 +    }
   1.710 +
   1.711 +    /*  Expression2Rest = {infixop Expression3}
   1.712 +     *                  | Expression3 instanceof Type
   1.713 +     *  infixop         = "||"
   1.714 +     *                  | "&&"
   1.715 +     *                  | "|"
   1.716 +     *                  | "^"
   1.717 +     *                  | "&"
   1.718 +     *                  | "==" | "!="
   1.719 +     *                  | "<" | ">" | "<=" | ">="
   1.720 +     *                  | "<<" | ">>" | ">>>"
   1.721 +     *                  | "+" | "-"
   1.722 +     *                  | "*" | "/" | "%"
   1.723 +     */
   1.724 +    JCExpression term2Rest(JCExpression t, int minprec) {
   1.725 +        List<JCExpression[]> savedOd = odStackSupply.elems;
   1.726 +        JCExpression[] odStack = newOdStack();
   1.727 +        List<Token[]> savedOp = opStackSupply.elems;
   1.728 +        Token[] opStack = newOpStack();
   1.729 +        // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   1.730 +        int top = 0;
   1.731 +        odStack[0] = t;
   1.732 +        int startPos = S.pos();
   1.733 +        Token topOp = ERROR;
   1.734 +        while (prec(S.token()) >= minprec) {
   1.735 +            opStack[top] = topOp;
   1.736 +            top++;
   1.737 +            topOp = S.token();
   1.738 +            int pos = S.pos();
   1.739 +            S.nextToken();
   1.740 +            odStack[top] = topOp == INSTANCEOF ? type() : term3();
   1.741 +            while (top > 0 && prec(topOp) >= prec(S.token())) {
   1.742 +                odStack[top-1] = makeOp(pos, topOp, odStack[top-1],
   1.743 +                                        odStack[top]);
   1.744 +                top--;
   1.745 +                topOp = opStack[top];
   1.746 +            }
   1.747 +        }
   1.748 +        assert top == 0;
   1.749 +        t = odStack[0];
   1.750 +
   1.751 +        if (t.getTag() == JCTree.PLUS) {
   1.752 +            StringBuffer buf = foldStrings(t);
   1.753 +            if (buf != null) {
   1.754 +                t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
   1.755 +            }
   1.756 +        }
   1.757 +
   1.758 +        odStackSupply.elems = savedOd; // optimization
   1.759 +        opStackSupply.elems = savedOp; // optimization
   1.760 +        return t;
   1.761 +    }
   1.762 +//where
   1.763 +        /** Construct a binary or type test node.
   1.764 +         */
   1.765 +        private JCExpression makeOp(int pos,
   1.766 +                                    Token topOp,
   1.767 +                                    JCExpression od1,
   1.768 +                                    JCExpression od2)
   1.769 +        {
   1.770 +            if (topOp == INSTANCEOF) {
   1.771 +                return F.at(pos).TypeTest(od1, od2);
   1.772 +            } else {
   1.773 +                return F.at(pos).Binary(optag(topOp), od1, od2);
   1.774 +            }
   1.775 +        }
   1.776 +        /** If tree is a concatenation of string literals, replace it
   1.777 +         *  by a single literal representing the concatenated string.
   1.778 +         */
   1.779 +        protected StringBuffer foldStrings(JCTree tree) {
   1.780 +            List<String> buf = List.nil();
   1.781 +            while (true) {
   1.782 +                if (tree.getTag() == JCTree.LITERAL) {
   1.783 +                    JCLiteral lit = (JCLiteral) tree;
   1.784 +                    if (lit.typetag == TypeTags.CLASS) {
   1.785 +                        StringBuffer sbuf =
   1.786 +                            new StringBuffer((String)lit.value);
   1.787 +                        while (buf.nonEmpty()) {
   1.788 +                            sbuf.append(buf.head);
   1.789 +                            buf = buf.tail;
   1.790 +                        }
   1.791 +                        return sbuf;
   1.792 +                    }
   1.793 +                } else if (tree.getTag() == JCTree.PLUS) {
   1.794 +                    JCBinary op = (JCBinary)tree;
   1.795 +                    if (op.rhs.getTag() == JCTree.LITERAL) {
   1.796 +                        JCLiteral lit = (JCLiteral) op.rhs;
   1.797 +                        if (lit.typetag == TypeTags.CLASS) {
   1.798 +                            buf = buf.prepend((String) lit.value);
   1.799 +                            tree = op.lhs;
   1.800 +                            continue;
   1.801 +                        }
   1.802 +                    }
   1.803 +                }
   1.804 +                return null;
   1.805 +            }
   1.806 +        }
   1.807 +
   1.808 +        /** optimization: To save allocating a new operand/operator stack
   1.809 +         *  for every binary operation, we use supplys.
   1.810 +         */
   1.811 +        ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
   1.812 +        ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
   1.813 +
   1.814 +        private JCExpression[] newOdStack() {
   1.815 +            if (odStackSupply.elems == odStackSupply.last)
   1.816 +                odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
   1.817 +            JCExpression[] odStack = odStackSupply.elems.head;
   1.818 +            odStackSupply.elems = odStackSupply.elems.tail;
   1.819 +            return odStack;
   1.820 +        }
   1.821 +
   1.822 +        private Token[] newOpStack() {
   1.823 +            if (opStackSupply.elems == opStackSupply.last)
   1.824 +                opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
   1.825 +            Token[] opStack = opStackSupply.elems.head;
   1.826 +            opStackSupply.elems = opStackSupply.elems.tail;
   1.827 +            return opStack;
   1.828 +        }
   1.829 +
   1.830 +    /** Expression3    = PrefixOp Expression3
   1.831 +     *                 | "(" Expr | TypeNoParams ")" Expression3
   1.832 +     *                 | Primary {Selector} {PostfixOp}
   1.833 +     *  Primary        = "(" Expression ")"
   1.834 +     *                 | Literal
   1.835 +     *                 | [TypeArguments] THIS [Arguments]
   1.836 +     *                 | [TypeArguments] SUPER SuperSuffix
   1.837 +     *                 | NEW [TypeArguments] Creator
   1.838 +     *                 | Ident { "." Ident }
   1.839 +     *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   1.840 +     *                   | Arguments
   1.841 +     *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   1.842 +     *                   ]
   1.843 +     *                 | BasicType BracketsOpt "." CLASS
   1.844 +     *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   1.845 +     *  PostfixOp      = "++" | "--"
   1.846 +     *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   1.847 +     *                 | BasicType
   1.848 +     *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   1.849 +     *  Selector       = "." [TypeArguments] Ident [Arguments]
   1.850 +     *                 | "." THIS
   1.851 +     *                 | "." [TypeArguments] SUPER SuperSuffix
   1.852 +     *                 | "." NEW [TypeArguments] InnerCreator
   1.853 +     *                 | "[" Expression "]"
   1.854 +     *  TypeSelector   = "." Ident [TypeArguments]
   1.855 +     *  SuperSuffix    = Arguments | "." Ident [Arguments]
   1.856 +     */
   1.857 +    protected JCExpression term3() {
   1.858 +        int pos = S.pos();
   1.859 +        JCExpression t;
   1.860 +        List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   1.861 +        switch (S.token()) {
   1.862 +        case QUES:
   1.863 +            if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   1.864 +                mode = TYPE;
   1.865 +                return typeArgument();
   1.866 +            } else
   1.867 +                return illegal();
   1.868 +        case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   1.869 +            if (typeArgs == null && (mode & EXPR) != 0) {
   1.870 +                Token token = S.token();
   1.871 +                S.nextToken();
   1.872 +                mode = EXPR;
   1.873 +                if (token == SUB &&
   1.874 +                    (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
   1.875 +                    S.radix() == 10) {
   1.876 +                    mode = EXPR;
   1.877 +                    t = literal(names.hyphen);
   1.878 +                } else {
   1.879 +                    t = term3();
   1.880 +                    return F.at(pos).Unary(unoptag(token), t);
   1.881 +                }
   1.882 +            } else return illegal();
   1.883 +            break;
   1.884 +        case LPAREN:
   1.885 +            if (typeArgs == null && (mode & EXPR) != 0) {
   1.886 +                S.nextToken();
   1.887 +                mode = EXPR | TYPE | NOPARAMS;
   1.888 +                t = term3();
   1.889 +                if ((mode & TYPE) != 0 && S.token() == LT) {
   1.890 +                    // Could be a cast to a parameterized type
   1.891 +                    int op = JCTree.LT;
   1.892 +                    int pos1 = S.pos();
   1.893 +                    S.nextToken();
   1.894 +                    mode &= (EXPR | TYPE);
   1.895 +                    mode |= TYPEARG;
   1.896 +                    JCExpression t1 = term3();
   1.897 +                    if ((mode & TYPE) != 0 &&
   1.898 +                        (S.token() == COMMA || S.token() == GT)) {
   1.899 +                        mode = TYPE;
   1.900 +                        ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   1.901 +                        args.append(t1);
   1.902 +                        while (S.token() == COMMA) {
   1.903 +                            S.nextToken();
   1.904 +                            args.append(typeArgument());
   1.905 +                        }
   1.906 +                        accept(GT);
   1.907 +                        t = F.at(pos1).TypeApply(t, args.toList());
   1.908 +                        checkGenerics();
   1.909 +                        t = bracketsOpt(toP(t));
   1.910 +                    } else if ((mode & EXPR) != 0) {
   1.911 +                        mode = EXPR;
   1.912 +                        t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec));
   1.913 +                        t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   1.914 +                    } else {
   1.915 +                        accept(GT);
   1.916 +                    }
   1.917 +                } else {
   1.918 +                    t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   1.919 +                }
   1.920 +                accept(RPAREN);
   1.921 +                lastmode = mode;
   1.922 +                mode = EXPR;
   1.923 +                if ((lastmode & EXPR) == 0) {
   1.924 +                    JCExpression t1 = term3();
   1.925 +                    return F.at(pos).TypeCast(t, t1);
   1.926 +                } else if ((lastmode & TYPE) != 0) {
   1.927 +                    switch (S.token()) {
   1.928 +                    /*case PLUSPLUS: case SUBSUB: */
   1.929 +                    case BANG: case TILDE:
   1.930 +                    case LPAREN: case THIS: case SUPER:
   1.931 +                    case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
   1.932 +                    case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
   1.933 +                    case TRUE: case FALSE: case NULL:
   1.934 +                    case NEW: case IDENTIFIER: case ASSERT: case ENUM:
   1.935 +                    case BYTE: case SHORT: case CHAR: case INT:
   1.936 +                    case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
   1.937 +                        JCExpression t1 = term3();
   1.938 +                        return F.at(pos).TypeCast(t, t1);
   1.939 +                    }
   1.940 +                }
   1.941 +            } else return illegal();
   1.942 +            t = toP(F.at(pos).Parens(t));
   1.943 +            break;
   1.944 +        case THIS:
   1.945 +            if ((mode & EXPR) != 0) {
   1.946 +                mode = EXPR;
   1.947 +                t = to(F.at(pos).Ident(names._this));
   1.948 +                S.nextToken();
   1.949 +                if (typeArgs == null)
   1.950 +                    t = argumentsOpt(null, t);
   1.951 +                else
   1.952 +                    t = arguments(typeArgs, t);
   1.953 +                typeArgs = null;
   1.954 +            } else return illegal();
   1.955 +            break;
   1.956 +        case SUPER:
   1.957 +            if ((mode & EXPR) != 0) {
   1.958 +                mode = EXPR;
   1.959 +                t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super)));
   1.960 +                typeArgs = null;
   1.961 +            } else return illegal();
   1.962 +            break;
   1.963 +        case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
   1.964 +        case CHARLITERAL: case STRINGLITERAL:
   1.965 +        case TRUE: case FALSE: case NULL:
   1.966 +            if (typeArgs == null && (mode & EXPR) != 0) {
   1.967 +                mode = EXPR;
   1.968 +                t = literal(names.empty);
   1.969 +            } else return illegal();
   1.970 +            break;
   1.971 +        case NEW:
   1.972 +            if (typeArgs != null) return illegal();
   1.973 +            if ((mode & EXPR) != 0) {
   1.974 +                mode = EXPR;
   1.975 +                S.nextToken();
   1.976 +                if (S.token() == LT) typeArgs = typeArguments();
   1.977 +                t = creator(pos, typeArgs);
   1.978 +                typeArgs = null;
   1.979 +            } else return illegal();
   1.980 +            break;
   1.981 +        case IDENTIFIER: case ASSERT: case ENUM:
   1.982 +            if (typeArgs != null) return illegal();
   1.983 +            t = toP(F.at(S.pos()).Ident(ident()));
   1.984 +            loop: while (true) {
   1.985 +                pos = S.pos();
   1.986 +                switch (S.token()) {
   1.987 +                case LBRACKET:
   1.988 +                    S.nextToken();
   1.989 +                    if (S.token() == RBRACKET) {
   1.990 +                        S.nextToken();
   1.991 +                        t = bracketsOpt(t);
   1.992 +                        t = toP(F.at(pos).TypeArray(t));
   1.993 +                        t = bracketsSuffix(t);
   1.994 +                    } else {
   1.995 +                        if ((mode & EXPR) != 0) {
   1.996 +                            mode = EXPR;
   1.997 +                            JCExpression t1 = term();
   1.998 +                            t = to(F.at(pos).Indexed(t, t1));
   1.999 +                        }
  1.1000 +                        accept(RBRACKET);
  1.1001 +                    }
  1.1002 +                    break loop;
  1.1003 +                case LPAREN:
  1.1004 +                    if ((mode & EXPR) != 0) {
  1.1005 +                        mode = EXPR;
  1.1006 +                        t = arguments(typeArgs, t);
  1.1007 +                        typeArgs = null;
  1.1008 +                    }
  1.1009 +                    break loop;
  1.1010 +                case DOT:
  1.1011 +                    S.nextToken();
  1.1012 +                    typeArgs = typeArgumentsOpt(EXPR);
  1.1013 +                    if ((mode & EXPR) != 0) {
  1.1014 +                        switch (S.token()) {
  1.1015 +                        case CLASS:
  1.1016 +                            if (typeArgs != null) return illegal();
  1.1017 +                            mode = EXPR;
  1.1018 +                            t = to(F.at(pos).Select(t, names._class));
  1.1019 +                            S.nextToken();
  1.1020 +                            break loop;
  1.1021 +                        case THIS:
  1.1022 +                            if (typeArgs != null) return illegal();
  1.1023 +                            mode = EXPR;
  1.1024 +                            t = to(F.at(pos).Select(t, names._this));
  1.1025 +                            S.nextToken();
  1.1026 +                            break loop;
  1.1027 +                        case SUPER:
  1.1028 +                            mode = EXPR;
  1.1029 +                            t = to(F.at(pos).Select(t, names._super));
  1.1030 +                            t = superSuffix(typeArgs, t);
  1.1031 +                            typeArgs = null;
  1.1032 +                            break loop;
  1.1033 +                        case NEW:
  1.1034 +                            if (typeArgs != null) return illegal();
  1.1035 +                            mode = EXPR;
  1.1036 +                            int pos1 = S.pos();
  1.1037 +                            S.nextToken();
  1.1038 +                            if (S.token() == LT) typeArgs = typeArguments();
  1.1039 +                            t = innerCreator(pos1, typeArgs, t);
  1.1040 +                            typeArgs = null;
  1.1041 +                            break loop;
  1.1042 +                        }
  1.1043 +                    }
  1.1044 +                    // typeArgs saved for next loop iteration.
  1.1045 +                    t = toP(F.at(pos).Select(t, ident()));
  1.1046 +                    break;
  1.1047 +                default:
  1.1048 +                    break loop;
  1.1049 +                }
  1.1050 +            }
  1.1051 +            if (typeArgs != null) illegal();
  1.1052 +            t = typeArgumentsOpt(t);
  1.1053 +            break;
  1.1054 +        case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1.1055 +        case DOUBLE: case BOOLEAN:
  1.1056 +            if (typeArgs != null) illegal();
  1.1057 +            t = bracketsSuffix(bracketsOpt(basicType()));
  1.1058 +            break;
  1.1059 +        case VOID:
  1.1060 +            if (typeArgs != null) illegal();
  1.1061 +            if ((mode & EXPR) != 0) {
  1.1062 +                S.nextToken();
  1.1063 +                if (S.token() == DOT) {
  1.1064 +                    JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
  1.1065 +                    t = bracketsSuffix(ti);
  1.1066 +                } else {
  1.1067 +                    return illegal(pos);
  1.1068 +                }
  1.1069 +            } else {
  1.1070 +                return illegal();
  1.1071 +            }
  1.1072 +            break;
  1.1073 +        default:
  1.1074 +            return illegal();
  1.1075 +        }
  1.1076 +        if (typeArgs != null) illegal();
  1.1077 +        while (true) {
  1.1078 +            int pos1 = S.pos();
  1.1079 +            if (S.token() == LBRACKET) {
  1.1080 +                S.nextToken();
  1.1081 +                if ((mode & TYPE) != 0) {
  1.1082 +                    int oldmode = mode;
  1.1083 +                    mode = TYPE;
  1.1084 +                    if (S.token() == RBRACKET) {
  1.1085 +                        S.nextToken();
  1.1086 +                        t = bracketsOpt(t);
  1.1087 +                        t = toP(F.at(pos1).TypeArray(t));
  1.1088 +                        return t;
  1.1089 +                    }
  1.1090 +                    mode = oldmode;
  1.1091 +                }
  1.1092 +                if ((mode & EXPR) != 0) {
  1.1093 +                    mode = EXPR;
  1.1094 +                    JCExpression t1 = term();
  1.1095 +                    t = to(F.at(pos1).Indexed(t, t1));
  1.1096 +                }
  1.1097 +                accept(RBRACKET);
  1.1098 +            } else if (S.token() == DOT) {
  1.1099 +                S.nextToken();
  1.1100 +                typeArgs = typeArgumentsOpt(EXPR);
  1.1101 +                if (S.token() == SUPER && (mode & EXPR) != 0) {
  1.1102 +                    mode = EXPR;
  1.1103 +                    t = to(F.at(pos1).Select(t, names._super));
  1.1104 +                    S.nextToken();
  1.1105 +                    t = arguments(typeArgs, t);
  1.1106 +                    typeArgs = null;
  1.1107 +                } else if (S.token() == NEW && (mode & EXPR) != 0) {
  1.1108 +                    if (typeArgs != null) return illegal();
  1.1109 +                    mode = EXPR;
  1.1110 +                    int pos2 = S.pos();
  1.1111 +                    S.nextToken();
  1.1112 +                    if (S.token() == LT) typeArgs = typeArguments();
  1.1113 +                    t = innerCreator(pos2, typeArgs, t);
  1.1114 +                    typeArgs = null;
  1.1115 +                } else {
  1.1116 +                    t = toP(F.at(pos1).Select(t, ident()));
  1.1117 +                    t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1.1118 +                    typeArgs = null;
  1.1119 +                }
  1.1120 +            } else {
  1.1121 +                break;
  1.1122 +            }
  1.1123 +        }
  1.1124 +        while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
  1.1125 +            mode = EXPR;
  1.1126 +            t = to(F.at(S.pos()).Unary(
  1.1127 +                  S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
  1.1128 +            S.nextToken();
  1.1129 +        }
  1.1130 +        return toP(t);
  1.1131 +    }
  1.1132 +
  1.1133 +    /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1.1134 +     */
  1.1135 +    JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1.1136 +        S.nextToken();
  1.1137 +        if (S.token() == LPAREN || typeArgs != null) {
  1.1138 +            t = arguments(typeArgs, t);
  1.1139 +        } else {
  1.1140 +            int pos = S.pos();
  1.1141 +            accept(DOT);
  1.1142 +            typeArgs = (S.token() == LT) ? typeArguments() : null;
  1.1143 +            t = toP(F.at(pos).Select(t, ident()));
  1.1144 +            t = argumentsOpt(typeArgs, t);
  1.1145 +        }
  1.1146 +        return t;
  1.1147 +    }
  1.1148 +
  1.1149 +    /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1.1150 +     */
  1.1151 +    JCPrimitiveTypeTree basicType() {
  1.1152 +        JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
  1.1153 +        S.nextToken();
  1.1154 +        return t;
  1.1155 +    }
  1.1156 +
  1.1157 +    /** ArgumentsOpt = [ Arguments ]
  1.1158 +     */
  1.1159 +    JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1.1160 +        if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
  1.1161 +            mode = EXPR;
  1.1162 +            return arguments(typeArgs, t);
  1.1163 +        } else {
  1.1164 +            return t;
  1.1165 +        }
  1.1166 +    }
  1.1167 +
  1.1168 +    /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1.1169 +     */
  1.1170 +    List<JCExpression> arguments() {
  1.1171 +        ListBuffer<JCExpression> args = lb();
  1.1172 +        if (S.token() == LPAREN) {
  1.1173 +            S.nextToken();
  1.1174 +            if (S.token() != RPAREN) {
  1.1175 +                args.append(expression());
  1.1176 +                while (S.token() == COMMA) {
  1.1177 +                    S.nextToken();
  1.1178 +                    args.append(expression());
  1.1179 +                }
  1.1180 +            }
  1.1181 +            accept(RPAREN);
  1.1182 +        } else {
  1.1183 +            syntaxError(S.pos(), "expected", keywords.token2string(LPAREN));
  1.1184 +        }
  1.1185 +        return args.toList();
  1.1186 +    }
  1.1187 +
  1.1188 +    JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1.1189 +        int pos = S.pos();
  1.1190 +        List<JCExpression> args = arguments();
  1.1191 +        return toP(F.at(pos).Apply(typeArgs, t, args));
  1.1192 +    }
  1.1193 +
  1.1194 +    /**  TypeArgumentsOpt = [ TypeArguments ]
  1.1195 +     */
  1.1196 +    JCExpression typeArgumentsOpt(JCExpression t) {
  1.1197 +        if (S.token() == LT &&
  1.1198 +            (mode & TYPE) != 0 &&
  1.1199 +            (mode & NOPARAMS) == 0) {
  1.1200 +            mode = TYPE;
  1.1201 +            checkGenerics();
  1.1202 +            return typeArguments(t);
  1.1203 +        } else {
  1.1204 +            return t;
  1.1205 +        }
  1.1206 +    }
  1.1207 +    List<JCExpression> typeArgumentsOpt() {
  1.1208 +        return typeArgumentsOpt(TYPE);
  1.1209 +    }
  1.1210 +
  1.1211 +    List<JCExpression> typeArgumentsOpt(int useMode) {
  1.1212 +        if (S.token() == LT) {
  1.1213 +            checkGenerics();
  1.1214 +            if ((mode & useMode) == 0 ||
  1.1215 +                (mode & NOPARAMS) != 0) {
  1.1216 +                illegal();
  1.1217 +            }
  1.1218 +            mode = useMode;
  1.1219 +            return typeArguments();
  1.1220 +        }
  1.1221 +        return null;
  1.1222 +    }
  1.1223 +
  1.1224 +    /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1.1225 +     */
  1.1226 +    List<JCExpression> typeArguments() {
  1.1227 +        ListBuffer<JCExpression> args = lb();
  1.1228 +        if (S.token() == LT) {
  1.1229 +            S.nextToken();
  1.1230 +            args.append(((mode & EXPR) == 0) ? typeArgument() : type());
  1.1231 +            while (S.token() == COMMA) {
  1.1232 +                S.nextToken();
  1.1233 +                args.append(((mode & EXPR) == 0) ? typeArgument() : type());
  1.1234 +            }
  1.1235 +            switch (S.token()) {
  1.1236 +            case GTGTGTEQ:
  1.1237 +                S.token(GTGTEQ);
  1.1238 +                break;
  1.1239 +            case GTGTEQ:
  1.1240 +                S.token(GTEQ);
  1.1241 +                break;
  1.1242 +            case GTEQ:
  1.1243 +                S.token(EQ);
  1.1244 +                break;
  1.1245 +            case GTGTGT:
  1.1246 +                S.token(GTGT);
  1.1247 +                break;
  1.1248 +            case GTGT:
  1.1249 +                S.token(GT);
  1.1250 +                break;
  1.1251 +            default:
  1.1252 +                accept(GT);
  1.1253 +                break;
  1.1254 +            }
  1.1255 +        } else {
  1.1256 +            syntaxError(S.pos(), "expected", keywords.token2string(LT));
  1.1257 +        }
  1.1258 +        return args.toList();
  1.1259 +    }
  1.1260 +
  1.1261 +    /** TypeArgument = Type
  1.1262 +     *               | "?"
  1.1263 +     *               | "?" EXTENDS Type {"&" Type}
  1.1264 +     *               | "?" SUPER Type
  1.1265 +     */
  1.1266 +    JCExpression typeArgument() {
  1.1267 +        if (S.token() != QUES) return type();
  1.1268 +        int pos = S.pos();
  1.1269 +        S.nextToken();
  1.1270 +        if (S.token() == EXTENDS) {
  1.1271 +            TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
  1.1272 +            S.nextToken();
  1.1273 +            return F.at(pos).Wildcard(t, type());
  1.1274 +        } else if (S.token() == SUPER) {
  1.1275 +            TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
  1.1276 +            S.nextToken();
  1.1277 +            return F.at(pos).Wildcard(t, type());
  1.1278 +        } else if (S.token() == IDENTIFIER) {
  1.1279 +            //error recovery
  1.1280 +            reportSyntaxError(S.prevEndPos(), "expected3",
  1.1281 +                    keywords.token2string(GT),
  1.1282 +                    keywords.token2string(EXTENDS),
  1.1283 +                    keywords.token2string(SUPER));
  1.1284 +            TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1.1285 +            JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1.1286 +            JCIdent id = toP(F.at(S.pos()).Ident(ident()));
  1.1287 +            return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1.1288 +        } else {
  1.1289 +            TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1.1290 +            return toP(F.at(pos).Wildcard(t, null));
  1.1291 +        }
  1.1292 +    }
  1.1293 +
  1.1294 +    JCTypeApply typeArguments(JCExpression t) {
  1.1295 +        int pos = S.pos();
  1.1296 +        List<JCExpression> args = typeArguments();
  1.1297 +        return toP(F.at(pos).TypeApply(t, args));
  1.1298 +    }
  1.1299 +
  1.1300 +    /** BracketsOpt = {"[" "]"}
  1.1301 +     */
  1.1302 +    private JCExpression bracketsOpt(JCExpression t) {
  1.1303 +        if (S.token() == LBRACKET) {
  1.1304 +            int pos = S.pos();
  1.1305 +            S.nextToken();
  1.1306 +            t = bracketsOptCont(t, pos);
  1.1307 +            F.at(pos);
  1.1308 +        }
  1.1309 +        return t;
  1.1310 +    }
  1.1311 +
  1.1312 +    private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1.1313 +        accept(RBRACKET);
  1.1314 +        t = bracketsOpt(t);
  1.1315 +        return toP(F.at(pos).TypeArray(t));
  1.1316 +    }
  1.1317 +
  1.1318 +    /** BracketsSuffixExpr = "." CLASS
  1.1319 +     *  BracketsSuffixType =
  1.1320 +     */
  1.1321 +    JCExpression bracketsSuffix(JCExpression t) {
  1.1322 +        if ((mode & EXPR) != 0 && S.token() == DOT) {
  1.1323 +            mode = EXPR;
  1.1324 +            int pos = S.pos();
  1.1325 +            S.nextToken();
  1.1326 +            accept(CLASS);
  1.1327 +            if (S.pos() == errorEndPos) {
  1.1328 +                // error recovery
  1.1329 +                Name name = null;
  1.1330 +                if (S.token() == IDENTIFIER) {
  1.1331 +                    name = S.name();
  1.1332 +                    S.nextToken();
  1.1333 +                } else {
  1.1334 +                    name = names.error;
  1.1335 +                }
  1.1336 +                t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1.1337 +            } else {
  1.1338 +                t = toP(F.at(pos).Select(t, names._class));
  1.1339 +            }
  1.1340 +        } else if ((mode & TYPE) != 0) {
  1.1341 +            mode = TYPE;
  1.1342 +        } else {
  1.1343 +            syntaxError(S.pos(), "dot.class.expected");
  1.1344 +        }
  1.1345 +        return t;
  1.1346 +    }
  1.1347 +
  1.1348 +    /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1.1349 +     */
  1.1350 +    JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1.1351 +        switch (S.token()) {
  1.1352 +        case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1.1353 +        case DOUBLE: case BOOLEAN:
  1.1354 +            if (typeArgs == null)
  1.1355 +                return arrayCreatorRest(newpos, basicType());
  1.1356 +            break;
  1.1357 +        default:
  1.1358 +        }
  1.1359 +        JCExpression t = qualident();
  1.1360 +        int oldmode = mode;
  1.1361 +        mode = TYPE;
  1.1362 +        if (S.token() == LT) {
  1.1363 +            checkGenerics();
  1.1364 +            t = typeArguments(t);
  1.1365 +        }
  1.1366 +        while (S.token() == DOT) {
  1.1367 +            int pos = S.pos();
  1.1368 +            S.nextToken();
  1.1369 +            t = toP(F.at(pos).Select(t, ident()));
  1.1370 +            if (S.token() == LT) {
  1.1371 +                checkGenerics();
  1.1372 +                t = typeArguments(t);
  1.1373 +            }
  1.1374 +        }
  1.1375 +        mode = oldmode;
  1.1376 +        if (S.token() == LBRACKET) {
  1.1377 +            JCExpression e = arrayCreatorRest(newpos, t);
  1.1378 +            if (typeArgs != null) {
  1.1379 +                int pos = newpos;
  1.1380 +                if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1.1381 +                    // note: this should always happen but we should
  1.1382 +                    // not rely on this as the parser is continuously
  1.1383 +                    // modified to improve error recovery.
  1.1384 +                    pos = typeArgs.head.pos;
  1.1385 +                }
  1.1386 +                setErrorEndPos(S.prevEndPos());
  1.1387 +                reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
  1.1388 +                return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
  1.1389 +            }
  1.1390 +            return e;
  1.1391 +        } else if (S.token() == LPAREN) {
  1.1392 +            return classCreatorRest(newpos, null, typeArgs, t);
  1.1393 +        } else {
  1.1394 +            reportSyntaxError(S.pos(), "expected2",
  1.1395 +                               keywords.token2string(LPAREN),
  1.1396 +                               keywords.token2string(LBRACKET));
  1.1397 +            t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1.1398 +            return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1.1399 +        }
  1.1400 +    }
  1.1401 +
  1.1402 +    /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1.1403 +     */
  1.1404 +    JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1.1405 +        JCExpression t = toP(F.at(S.pos()).Ident(ident()));
  1.1406 +        if (S.token() == LT) {
  1.1407 +            checkGenerics();
  1.1408 +            t = typeArguments(t);
  1.1409 +        }
  1.1410 +        return classCreatorRest(newpos, encl, typeArgs, t);
  1.1411 +    }
  1.1412 +
  1.1413 +    /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1.1414 +     *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1.1415 +     */
  1.1416 +    JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1.1417 +        accept(LBRACKET);
  1.1418 +        if (S.token() == RBRACKET) {
  1.1419 +            accept(RBRACKET);
  1.1420 +            elemtype = bracketsOpt(elemtype);
  1.1421 +            if (S.token() == LBRACE) {
  1.1422 +                return arrayInitializer(newpos, elemtype);
  1.1423 +            } else {
  1.1424 +                return syntaxError(S.pos(), "array.dimension.missing");
  1.1425 +            }
  1.1426 +        } else {
  1.1427 +            ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1.1428 +            dims.append(expression());
  1.1429 +            accept(RBRACKET);
  1.1430 +            while (S.token() == LBRACKET) {
  1.1431 +                int pos = S.pos();
  1.1432 +                S.nextToken();
  1.1433 +                if (S.token() == RBRACKET) {
  1.1434 +                    elemtype = bracketsOptCont(elemtype, pos);
  1.1435 +                } else {
  1.1436 +                    dims.append(expression());
  1.1437 +                    accept(RBRACKET);
  1.1438 +                }
  1.1439 +            }
  1.1440 +            return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1.1441 +        }
  1.1442 +    }
  1.1443 +
  1.1444 +    /** ClassCreatorRest = Arguments [ClassBody]
  1.1445 +     */
  1.1446 +    JCExpression classCreatorRest(int newpos,
  1.1447 +                                  JCExpression encl,
  1.1448 +                                  List<JCExpression> typeArgs,
  1.1449 +                                  JCExpression t)
  1.1450 +    {
  1.1451 +        List<JCExpression> args = arguments();
  1.1452 +        JCClassDecl body = null;
  1.1453 +        if (S.token() == LBRACE) {
  1.1454 +            int pos = S.pos();
  1.1455 +            List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1.1456 +            JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1.1457 +            body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1.1458 +        }
  1.1459 +        return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1.1460 +    }
  1.1461 +
  1.1462 +    /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1.1463 +     */
  1.1464 +    JCExpression arrayInitializer(int newpos, JCExpression t) {
  1.1465 +        accept(LBRACE);
  1.1466 +        ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1.1467 +        if (S.token() == COMMA) {
  1.1468 +            S.nextToken();
  1.1469 +        } else if (S.token() != RBRACE) {
  1.1470 +            elems.append(variableInitializer());
  1.1471 +            while (S.token() == COMMA) {
  1.1472 +                S.nextToken();
  1.1473 +                if (S.token() == RBRACE) break;
  1.1474 +                elems.append(variableInitializer());
  1.1475 +            }
  1.1476 +        }
  1.1477 +        accept(RBRACE);
  1.1478 +        return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1.1479 +    }
  1.1480 +
  1.1481 +    /** VariableInitializer = ArrayInitializer | Expression
  1.1482 +     */
  1.1483 +    public JCExpression variableInitializer() {
  1.1484 +        return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : expression();
  1.1485 +    }
  1.1486 +
  1.1487 +    /** ParExpression = "(" Expression ")"
  1.1488 +     */
  1.1489 +    JCExpression parExpression() {
  1.1490 +        accept(LPAREN);
  1.1491 +        JCExpression t = expression();
  1.1492 +        accept(RPAREN);
  1.1493 +        return t;
  1.1494 +    }
  1.1495 +
  1.1496 +    /** Block = "{" BlockStatements "}"
  1.1497 +     */
  1.1498 +    JCBlock block(int pos, long flags) {
  1.1499 +        accept(LBRACE);
  1.1500 +        List<JCStatement> stats = blockStatements();
  1.1501 +        JCBlock t = F.at(pos).Block(flags, stats);
  1.1502 +        while (S.token() == CASE || S.token() == DEFAULT) {
  1.1503 +            syntaxError("orphaned", keywords.token2string(S.token()));
  1.1504 +            switchBlockStatementGroups();
  1.1505 +        }
  1.1506 +        // the Block node has a field "endpos" for first char of last token, which is
  1.1507 +        // usually but not necessarily the last char of the last token.
  1.1508 +        t.endpos = S.pos();
  1.1509 +        accept(RBRACE);
  1.1510 +        return toP(t);
  1.1511 +    }
  1.1512 +
  1.1513 +    public JCBlock block() {
  1.1514 +        return block(S.pos(), 0);
  1.1515 +    }
  1.1516 +
  1.1517 +    /** BlockStatements = { BlockStatement }
  1.1518 +     *  BlockStatement  = LocalVariableDeclarationStatement
  1.1519 +     *                  | ClassOrInterfaceOrEnumDeclaration
  1.1520 +     *                  | [Ident ":"] Statement
  1.1521 +     *  LocalVariableDeclarationStatement
  1.1522 +     *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1.1523 +     */
  1.1524 +    @SuppressWarnings("fallthrough")
  1.1525 +    List<JCStatement> blockStatements() {
  1.1526 +//todo: skip to anchor on error(?)
  1.1527 +        int lastErrPos = -1;
  1.1528 +        ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1.1529 +        while (true) {
  1.1530 +            int pos = S.pos();
  1.1531 +            switch (S.token()) {
  1.1532 +            case RBRACE: case CASE: case DEFAULT: case EOF:
  1.1533 +                return stats.toList();
  1.1534 +            case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1.1535 +            case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1.1536 +            case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1.1537 +                stats.append(statement());
  1.1538 +                break;
  1.1539 +            case MONKEYS_AT:
  1.1540 +            case FINAL: {
  1.1541 +                String dc = S.docComment();
  1.1542 +                JCModifiers mods = modifiersOpt();
  1.1543 +                if (S.token() == INTERFACE ||
  1.1544 +                    S.token() == CLASS ||
  1.1545 +                    allowEnums && S.token() == ENUM) {
  1.1546 +                    stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1.1547 +                } else {
  1.1548 +                    JCExpression t = type();
  1.1549 +                    stats.appendList(variableDeclarators(mods, t,
  1.1550 +                                                         new ListBuffer<JCStatement>()));
  1.1551 +                    // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1.1552 +                    storeEnd(stats.elems.last(), S.endPos());
  1.1553 +                    accept(SEMI);
  1.1554 +                }
  1.1555 +                break;
  1.1556 +            }
  1.1557 +            case ABSTRACT: case STRICTFP: {
  1.1558 +                String dc = S.docComment();
  1.1559 +                JCModifiers mods = modifiersOpt();
  1.1560 +                stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
  1.1561 +                break;
  1.1562 +            }
  1.1563 +            case INTERFACE:
  1.1564 +            case CLASS:
  1.1565 +                stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1.1566 +                                                               S.docComment()));
  1.1567 +                break;
  1.1568 +            case ENUM:
  1.1569 +            case ASSERT:
  1.1570 +                if (allowEnums && S.token() == ENUM) {
  1.1571 +                    log.error(S.pos(), "local.enum");
  1.1572 +                    stats.
  1.1573 +                        append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
  1.1574 +                                                                 S.docComment()));
  1.1575 +                    break;
  1.1576 +                } else if (allowAsserts && S.token() == ASSERT) {
  1.1577 +                    stats.append(statement());
  1.1578 +                    break;
  1.1579 +                }
  1.1580 +                /* fall through to default */
  1.1581 +            default:
  1.1582 +                Name name = S.name();
  1.1583 +                JCExpression t = term(EXPR | TYPE);
  1.1584 +                if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
  1.1585 +                    S.nextToken();
  1.1586 +                    JCStatement stat = statement();
  1.1587 +                    stats.append(F.at(pos).Labelled(name, stat));
  1.1588 +                } else if ((lastmode & TYPE) != 0 &&
  1.1589 +                           (S.token() == IDENTIFIER ||
  1.1590 +                            S.token() == ASSERT ||
  1.1591 +                            S.token() == ENUM)) {
  1.1592 +                    pos = S.pos();
  1.1593 +                    JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1.1594 +                    F.at(pos);
  1.1595 +                    stats.appendList(variableDeclarators(mods, t,
  1.1596 +                                                         new ListBuffer<JCStatement>()));
  1.1597 +                    // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1.1598 +                    storeEnd(stats.elems.last(), S.endPos());
  1.1599 +                    accept(SEMI);
  1.1600 +                } else {
  1.1601 +                    // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1.1602 +                    stats.append(to(F.at(pos).Exec(checkExprStat(t))));
  1.1603 +                    accept(SEMI);
  1.1604 +                }
  1.1605 +            }
  1.1606 +
  1.1607 +            // error recovery
  1.1608 +            if (S.pos() == lastErrPos)
  1.1609 +                return stats.toList();
  1.1610 +            if (S.pos() <= errorEndPos) {
  1.1611 +                skip(false, true, true, true);
  1.1612 +                lastErrPos = S.pos();
  1.1613 +            }
  1.1614 +
  1.1615 +            // ensure no dangling /** @deprecated */ active
  1.1616 +            S.resetDeprecatedFlag();
  1.1617 +        }
  1.1618 +    }
  1.1619 +
  1.1620 +    /** Statement =
  1.1621 +     *       Block
  1.1622 +     *     | IF ParExpression Statement [ELSE Statement]
  1.1623 +     *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1.1624 +     *     | FOR "(" FormalParameter : Expression ")" Statement
  1.1625 +     *     | WHILE ParExpression Statement
  1.1626 +     *     | DO Statement WHILE ParExpression ";"
  1.1627 +     *     | TRY Block ( Catches | [Catches] FinallyPart )
  1.1628 +     *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1.1629 +     *     | SYNCHRONIZED ParExpression Block
  1.1630 +     *     | RETURN [Expression] ";"
  1.1631 +     *     | THROW Expression ";"
  1.1632 +     *     | BREAK [Ident] ";"
  1.1633 +     *     | CONTINUE [Ident] ";"
  1.1634 +     *     | ASSERT Expression [ ":" Expression ] ";"
  1.1635 +     *     | ";"
  1.1636 +     *     | ExpressionStatement
  1.1637 +     *     | Ident ":" Statement
  1.1638 +     */
  1.1639 +    @SuppressWarnings("fallthrough")
  1.1640 +    public JCStatement statement() {
  1.1641 +        int pos = S.pos();
  1.1642 +        switch (S.token()) {
  1.1643 +        case LBRACE:
  1.1644 +            return block();
  1.1645 +        case IF: {
  1.1646 +            S.nextToken();
  1.1647 +            JCExpression cond = parExpression();
  1.1648 +            JCStatement thenpart = statement();
  1.1649 +            JCStatement elsepart = null;
  1.1650 +            if (S.token() == ELSE) {
  1.1651 +                S.nextToken();
  1.1652 +                elsepart = statement();
  1.1653 +            }
  1.1654 +            return F.at(pos).If(cond, thenpart, elsepart);
  1.1655 +        }
  1.1656 +        case FOR: {
  1.1657 +            S.nextToken();
  1.1658 +            accept(LPAREN);
  1.1659 +            List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
  1.1660 +            if (inits.length() == 1 &&
  1.1661 +                inits.head.getTag() == JCTree.VARDEF &&
  1.1662 +                ((JCVariableDecl) inits.head).init == null &&
  1.1663 +                S.token() == COLON) {
  1.1664 +                checkForeach();
  1.1665 +                JCVariableDecl var = (JCVariableDecl)inits.head;
  1.1666 +                accept(COLON);
  1.1667 +                JCExpression expr = expression();
  1.1668 +                accept(RPAREN);
  1.1669 +                JCStatement body = statement();
  1.1670 +                return F.at(pos).ForeachLoop(var, expr, body);
  1.1671 +            } else {
  1.1672 +                accept(SEMI);
  1.1673 +                JCExpression cond = S.token() == SEMI ? null : expression();
  1.1674 +                accept(SEMI);
  1.1675 +                List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  1.1676 +                accept(RPAREN);
  1.1677 +                JCStatement body = statement();
  1.1678 +                return F.at(pos).ForLoop(inits, cond, steps, body);
  1.1679 +            }
  1.1680 +        }
  1.1681 +        case WHILE: {
  1.1682 +            S.nextToken();
  1.1683 +            JCExpression cond = parExpression();
  1.1684 +            JCStatement body = statement();
  1.1685 +            return F.at(pos).WhileLoop(cond, body);
  1.1686 +        }
  1.1687 +        case DO: {
  1.1688 +            S.nextToken();
  1.1689 +            JCStatement body = statement();
  1.1690 +            accept(WHILE);
  1.1691 +            JCExpression cond = parExpression();
  1.1692 +            JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  1.1693 +            accept(SEMI);
  1.1694 +            return t;
  1.1695 +        }
  1.1696 +        case TRY: {
  1.1697 +            S.nextToken();
  1.1698 +            JCBlock body = block();
  1.1699 +            ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  1.1700 +            JCBlock finalizer = null;
  1.1701 +            if (S.token() == CATCH || S.token() == FINALLY) {
  1.1702 +                while (S.token() == CATCH) catchers.append(catchClause());
  1.1703 +                if (S.token() == FINALLY) {
  1.1704 +                    S.nextToken();
  1.1705 +                    finalizer = block();
  1.1706 +                }
  1.1707 +            } else {
  1.1708 +                log.error(pos, "try.without.catch.or.finally");
  1.1709 +            }
  1.1710 +            return F.at(pos).Try(body, catchers.toList(), finalizer);
  1.1711 +        }
  1.1712 +        case SWITCH: {
  1.1713 +            S.nextToken();
  1.1714 +            JCExpression selector = parExpression();
  1.1715 +            accept(LBRACE);
  1.1716 +            List<JCCase> cases = switchBlockStatementGroups();
  1.1717 +            JCSwitch t = to(F.at(pos).Switch(selector, cases));
  1.1718 +            accept(RBRACE);
  1.1719 +            return t;
  1.1720 +        }
  1.1721 +        case SYNCHRONIZED: {
  1.1722 +            S.nextToken();
  1.1723 +            JCExpression lock = parExpression();
  1.1724 +            JCBlock body = block();
  1.1725 +            return F.at(pos).Synchronized(lock, body);
  1.1726 +        }
  1.1727 +        case RETURN: {
  1.1728 +            S.nextToken();
  1.1729 +            JCExpression result = S.token() == SEMI ? null : expression();
  1.1730 +            JCReturn t = to(F.at(pos).Return(result));
  1.1731 +            accept(SEMI);
  1.1732 +            return t;
  1.1733 +        }
  1.1734 +        case THROW: {
  1.1735 +            S.nextToken();
  1.1736 +            JCExpression exc = expression();
  1.1737 +            JCThrow t = to(F.at(pos).Throw(exc));
  1.1738 +            accept(SEMI);
  1.1739 +            return t;
  1.1740 +        }
  1.1741 +        case BREAK: {
  1.1742 +            S.nextToken();
  1.1743 +            Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1.1744 +            JCBreak t = to(F.at(pos).Break(label));
  1.1745 +            accept(SEMI);
  1.1746 +            return t;
  1.1747 +        }
  1.1748 +        case CONTINUE: {
  1.1749 +            S.nextToken();
  1.1750 +            Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
  1.1751 +            JCContinue t =  to(F.at(pos).Continue(label));
  1.1752 +            accept(SEMI);
  1.1753 +            return t;
  1.1754 +        }
  1.1755 +        case SEMI:
  1.1756 +            S.nextToken();
  1.1757 +            return toP(F.at(pos).Skip());
  1.1758 +        case ELSE:
  1.1759 +            return toP(F.Exec(syntaxError("else.without.if")));
  1.1760 +        case FINALLY:
  1.1761 +            return toP(F.Exec(syntaxError("finally.without.try")));
  1.1762 +        case CATCH:
  1.1763 +            return toP(F.Exec(syntaxError("catch.without.try")));
  1.1764 +        case ASSERT: {
  1.1765 +            if (allowAsserts && S.token() == ASSERT) {
  1.1766 +                S.nextToken();
  1.1767 +                JCExpression assertion = expression();
  1.1768 +                JCExpression message = null;
  1.1769 +                if (S.token() == COLON) {
  1.1770 +                    S.nextToken();
  1.1771 +                    message = expression();
  1.1772 +                }
  1.1773 +                JCAssert t = to(F.at(pos).Assert(assertion, message));
  1.1774 +                accept(SEMI);
  1.1775 +                return t;
  1.1776 +            }
  1.1777 +            /* else fall through to default case */
  1.1778 +        }
  1.1779 +        case ENUM:
  1.1780 +        default:
  1.1781 +            Name name = S.name();
  1.1782 +            JCExpression expr = expression();
  1.1783 +            if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
  1.1784 +                S.nextToken();
  1.1785 +                JCStatement stat = statement();
  1.1786 +                return F.at(pos).Labelled(name, stat);
  1.1787 +            } else {
  1.1788 +                // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1.1789 +                JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  1.1790 +                accept(SEMI);
  1.1791 +                return stat;
  1.1792 +            }
  1.1793 +        }
  1.1794 +    }
  1.1795 +
  1.1796 +    /** CatchClause     = CATCH "(" FormalParameter ")" Block
  1.1797 +     */
  1.1798 +    JCCatch catchClause() {
  1.1799 +        int pos = S.pos();
  1.1800 +        accept(CATCH);
  1.1801 +        accept(LPAREN);
  1.1802 +        JCVariableDecl formal =
  1.1803 +            variableDeclaratorId(optFinal(Flags.PARAMETER),
  1.1804 +                                 qualident());
  1.1805 +        accept(RPAREN);
  1.1806 +        JCBlock body = block();
  1.1807 +        return F.at(pos).Catch(formal, body);
  1.1808 +    }
  1.1809 +
  1.1810 +    /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  1.1811 +     *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  1.1812 +     *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  1.1813 +     */
  1.1814 +    List<JCCase> switchBlockStatementGroups() {
  1.1815 +        ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  1.1816 +        while (true) {
  1.1817 +            int pos = S.pos();
  1.1818 +            switch (S.token()) {
  1.1819 +            case CASE: {
  1.1820 +                S.nextToken();
  1.1821 +                JCExpression pat = expression();
  1.1822 +                accept(COLON);
  1.1823 +                List<JCStatement> stats = blockStatements();
  1.1824 +                JCCase c = F.at(pos).Case(pat, stats);
  1.1825 +                if (stats.isEmpty())
  1.1826 +                    storeEnd(c, S.prevEndPos());
  1.1827 +                cases.append(c);
  1.1828 +                break;
  1.1829 +            }
  1.1830 +            case DEFAULT: {
  1.1831 +                S.nextToken();
  1.1832 +                accept(COLON);
  1.1833 +                List<JCStatement> stats = blockStatements();
  1.1834 +                JCCase c = F.at(pos).Case(null, stats);
  1.1835 +                if (stats.isEmpty())
  1.1836 +                    storeEnd(c, S.prevEndPos());
  1.1837 +                cases.append(c);
  1.1838 +                break;
  1.1839 +            }
  1.1840 +            case RBRACE: case EOF:
  1.1841 +                return cases.toList();
  1.1842 +            default:
  1.1843 +                S.nextToken(); // to ensure progress
  1.1844 +                syntaxError(pos, "expected3",
  1.1845 +                    keywords.token2string(CASE),
  1.1846 +                    keywords.token2string(DEFAULT),
  1.1847 +                    keywords.token2string(RBRACE));
  1.1848 +            }
  1.1849 +        }
  1.1850 +    }
  1.1851 +
  1.1852 +    /** MoreStatementExpressions = { COMMA StatementExpression }
  1.1853 +     */
  1.1854 +    <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  1.1855 +                                                                    JCExpression first,
  1.1856 +                                                                    T stats) {
  1.1857 +        // This Exec is a "StatementExpression"; it subsumes no terminating token
  1.1858 +        stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  1.1859 +        while (S.token() == COMMA) {
  1.1860 +            S.nextToken();
  1.1861 +            pos = S.pos();
  1.1862 +            JCExpression t = expression();
  1.1863 +            // This Exec is a "StatementExpression"; it subsumes no terminating token
  1.1864 +            stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  1.1865 +        }
  1.1866 +        return stats;
  1.1867 +    }
  1.1868 +
  1.1869 +    /** ForInit = StatementExpression MoreStatementExpressions
  1.1870 +     *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  1.1871 +     */
  1.1872 +    List<JCStatement> forInit() {
  1.1873 +        ListBuffer<JCStatement> stats = lb();
  1.1874 +        int pos = S.pos();
  1.1875 +        if (S.token() == FINAL || S.token() == MONKEYS_AT) {
  1.1876 +            return variableDeclarators(optFinal(0), type(), stats).toList();
  1.1877 +        } else {
  1.1878 +            JCExpression t = term(EXPR | TYPE);
  1.1879 +            if ((lastmode & TYPE) != 0 &&
  1.1880 +                (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
  1.1881 +                return variableDeclarators(modifiersOpt(), t, stats).toList();
  1.1882 +            else
  1.1883 +                return moreStatementExpressions(pos, t, stats).toList();
  1.1884 +        }
  1.1885 +    }
  1.1886 +
  1.1887 +    /** ForUpdate = StatementExpression MoreStatementExpressions
  1.1888 +     */
  1.1889 +    List<JCExpressionStatement> forUpdate() {
  1.1890 +        return moreStatementExpressions(S.pos(),
  1.1891 +                                        expression(),
  1.1892 +                                        new ListBuffer<JCExpressionStatement>()).toList();
  1.1893 +    }
  1.1894 +
  1.1895 +    /** AnnotationsOpt = { '@' Annotation }
  1.1896 +     */
  1.1897 +    List<JCAnnotation> annotationsOpt() {
  1.1898 +        if (S.token() != MONKEYS_AT) return List.nil(); // optimization
  1.1899 +        ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  1.1900 +        while (S.token() == MONKEYS_AT) {
  1.1901 +            int pos = S.pos();
  1.1902 +            S.nextToken();
  1.1903 +            buf.append(annotation(pos));
  1.1904 +        }
  1.1905 +        return buf.toList();
  1.1906 +    }
  1.1907 +
  1.1908 +    /** ModifiersOpt = { Modifier }
  1.1909 +     *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  1.1910 +     *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  1.1911 +     *           | "@" Annotation
  1.1912 +     */
  1.1913 +    JCModifiers modifiersOpt() {
  1.1914 +        return modifiersOpt(null);
  1.1915 +    }
  1.1916 +    JCModifiers modifiersOpt(JCModifiers partial) {
  1.1917 +        long flags = (partial == null) ? 0 : partial.flags;
  1.1918 +        if (S.deprecatedFlag()) {
  1.1919 +            flags |= Flags.DEPRECATED;
  1.1920 +            S.resetDeprecatedFlag();
  1.1921 +        }
  1.1922 +        ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  1.1923 +        if (partial != null) annotations.appendList(partial.annotations);
  1.1924 +        int pos = S.pos();
  1.1925 +        int lastPos = Position.NOPOS;
  1.1926 +    loop:
  1.1927 +        while (true) {
  1.1928 +            long flag;
  1.1929 +            switch (S.token()) {
  1.1930 +            case PRIVATE     : flag = Flags.PRIVATE; break;
  1.1931 +            case PROTECTED   : flag = Flags.PROTECTED; break;
  1.1932 +            case PUBLIC      : flag = Flags.PUBLIC; break;
  1.1933 +            case STATIC      : flag = Flags.STATIC; break;
  1.1934 +            case TRANSIENT   : flag = Flags.TRANSIENT; break;
  1.1935 +            case FINAL       : flag = Flags.FINAL; break;
  1.1936 +            case ABSTRACT    : flag = Flags.ABSTRACT; break;
  1.1937 +            case NATIVE      : flag = Flags.NATIVE; break;
  1.1938 +            case VOLATILE    : flag = Flags.VOLATILE; break;
  1.1939 +            case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  1.1940 +            case STRICTFP    : flag = Flags.STRICTFP; break;
  1.1941 +            case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  1.1942 +            default: break loop;
  1.1943 +            }
  1.1944 +            if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
  1.1945 +            lastPos = S.pos();
  1.1946 +            S.nextToken();
  1.1947 +            if (flag == Flags.ANNOTATION) {
  1.1948 +                checkAnnotations();
  1.1949 +                if (S.token() != INTERFACE) {
  1.1950 +                JCAnnotation ann = annotation(lastPos);
  1.1951 +                // if first modifier is an annotation, set pos to annotation's.
  1.1952 +                if (flags == 0 && annotations.isEmpty())
  1.1953 +                    pos = ann.pos;
  1.1954 +                annotations.append(ann);
  1.1955 +                lastPos = ann.pos;
  1.1956 +                    flag = 0;
  1.1957 +                }
  1.1958 +            }
  1.1959 +            flags |= flag;
  1.1960 +        }
  1.1961 +        switch (S.token()) {
  1.1962 +        case ENUM: flags |= Flags.ENUM; break;
  1.1963 +        case INTERFACE: flags |= Flags.INTERFACE; break;
  1.1964 +        default: break;
  1.1965 +        }
  1.1966 +
  1.1967 +        /* A modifiers tree with no modifier tokens or annotations
  1.1968 +         * has no text position. */
  1.1969 +        if (flags == 0 && annotations.isEmpty())
  1.1970 +            pos = Position.NOPOS;
  1.1971 +
  1.1972 +        JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  1.1973 +        if (pos != Position.NOPOS)
  1.1974 +            storeEnd(mods, S.prevEndPos());
  1.1975 +        return mods;
  1.1976 +    }
  1.1977 +
  1.1978 +    /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  1.1979 +     * @param pos position of "@" token
  1.1980 +     */
  1.1981 +    JCAnnotation annotation(int pos) {
  1.1982 +        // accept(AT); // AT consumed by caller
  1.1983 +        checkAnnotations();
  1.1984 +        JCTree ident = qualident();
  1.1985 +        List<JCExpression> fieldValues = annotationFieldValuesOpt();
  1.1986 +        JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  1.1987 +        storeEnd(ann, S.prevEndPos());
  1.1988 +        return ann;
  1.1989 +    }
  1.1990 +
  1.1991 +    List<JCExpression> annotationFieldValuesOpt() {
  1.1992 +        return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  1.1993 +    }
  1.1994 +
  1.1995 +    /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  1.1996 +    List<JCExpression> annotationFieldValues() {
  1.1997 +        accept(LPAREN);
  1.1998 +        ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  1.1999 +        if (S.token() != RPAREN) {
  1.2000 +            buf.append(annotationFieldValue());
  1.2001 +            while (S.token() == COMMA) {
  1.2002 +                S.nextToken();
  1.2003 +                buf.append(annotationFieldValue());
  1.2004 +            }
  1.2005 +        }
  1.2006 +        accept(RPAREN);
  1.2007 +        return buf.toList();
  1.2008 +    }
  1.2009 +
  1.2010 +    /** AnnotationFieldValue    = AnnotationValue
  1.2011 +     *                          | Identifier "=" AnnotationValue
  1.2012 +     */
  1.2013 +    JCExpression annotationFieldValue() {
  1.2014 +        if (S.token() == IDENTIFIER) {
  1.2015 +            mode = EXPR;
  1.2016 +            JCExpression t1 = term1();
  1.2017 +            if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
  1.2018 +                int pos = S.pos();
  1.2019 +                accept(EQ);
  1.2020 +                return toP(F.at(pos).Assign(t1, annotationValue()));
  1.2021 +            } else {
  1.2022 +                return t1;
  1.2023 +            }
  1.2024 +        }
  1.2025 +        return annotationValue();
  1.2026 +    }
  1.2027 +
  1.2028 +    /* AnnotationValue          = ConditionalExpression
  1.2029 +     *                          | Annotation
  1.2030 +     *                          | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
  1.2031 +     */
  1.2032 +    JCExpression annotationValue() {
  1.2033 +        int pos;
  1.2034 +        switch (S.token()) {
  1.2035 +        case MONKEYS_AT:
  1.2036 +            pos = S.pos();
  1.2037 +            S.nextToken();
  1.2038 +            return annotation(pos);
  1.2039 +        case LBRACE:
  1.2040 +            pos = S.pos();
  1.2041 +            accept(LBRACE);
  1.2042 +            ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  1.2043 +            if (S.token() != RBRACE) {
  1.2044 +                buf.append(annotationValue());
  1.2045 +                while (S.token() == COMMA) {
  1.2046 +                    S.nextToken();
  1.2047 +                    if (S.token() == RPAREN) break;
  1.2048 +                    buf.append(annotationValue());
  1.2049 +                }
  1.2050 +            }
  1.2051 +            accept(RBRACE);
  1.2052 +            return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  1.2053 +        default:
  1.2054 +            mode = EXPR;
  1.2055 +            return term1();
  1.2056 +        }
  1.2057 +    }
  1.2058 +
  1.2059 +    /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  1.2060 +     */
  1.2061 +    public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  1.2062 +                                                                         JCExpression type,
  1.2063 +                                                                         T vdefs)
  1.2064 +    {
  1.2065 +        return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
  1.2066 +    }
  1.2067 +
  1.2068 +    /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  1.2069 +     *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  1.2070 +     *
  1.2071 +     *  @param reqInit  Is an initializer always required?
  1.2072 +     *  @param dc       The documentation comment for the variable declarations, or null.
  1.2073 +     */
  1.2074 +    <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  1.2075 +                                                                     JCModifiers mods,
  1.2076 +                                                                     JCExpression type,
  1.2077 +                                                                     Name name,
  1.2078 +                                                                     boolean reqInit,
  1.2079 +                                                                     String dc,
  1.2080 +                                                                     T vdefs)
  1.2081 +    {
  1.2082 +        vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  1.2083 +        while (S.token() == COMMA) {
  1.2084 +            // All but last of multiple declarators subsume a comma
  1.2085 +            storeEnd((JCTree)vdefs.elems.last(), S.endPos());
  1.2086 +            S.nextToken();
  1.2087 +            vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  1.2088 +        }
  1.2089 +        return vdefs;
  1.2090 +    }
  1.2091 +
  1.2092 +    /** VariableDeclarator = Ident VariableDeclaratorRest
  1.2093 +     *  ConstantDeclarator = Ident ConstantDeclaratorRest
  1.2094 +     */
  1.2095 +    JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
  1.2096 +        return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
  1.2097 +    }
  1.2098 +
  1.2099 +    /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  1.2100 +     *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  1.2101 +     *
  1.2102 +     *  @param reqInit  Is an initializer always required?
  1.2103 +     *  @param dc       The documentation comment for the variable declarations, or null.
  1.2104 +     */
  1.2105 +    JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  1.2106 +                                  boolean reqInit, String dc) {
  1.2107 +        type = bracketsOpt(type);
  1.2108 +        JCExpression init = null;
  1.2109 +        if (S.token() == EQ) {
  1.2110 +            S.nextToken();
  1.2111 +            init = variableInitializer();
  1.2112 +        }
  1.2113 +        else if (reqInit) syntaxError(S.pos(), "expected", keywords.token2string(EQ));
  1.2114 +        JCVariableDecl result =
  1.2115 +            toP(F.at(pos).VarDef(mods, name, type, init));
  1.2116 +        attach(result, dc);
  1.2117 +        return result;
  1.2118 +    }
  1.2119 +
  1.2120 +    /** VariableDeclaratorId = Ident BracketsOpt
  1.2121 +     */
  1.2122 +    JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  1.2123 +        int pos = S.pos();
  1.2124 +        Name name = ident();
  1.2125 +        if ((mods.flags & Flags.VARARGS) == 0)
  1.2126 +            type = bracketsOpt(type);
  1.2127 +        return toP(F.at(pos).VarDef(mods, name, type, null));
  1.2128 +    }
  1.2129 +
  1.2130 +    /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  1.2131 +     */
  1.2132 +    public JCTree.JCCompilationUnit compilationUnit() {
  1.2133 +        int pos = S.pos();
  1.2134 +        JCExpression pid = null;
  1.2135 +        String dc = S.docComment();
  1.2136 +        JCModifiers mods = null;
  1.2137 +        List<JCAnnotation> packageAnnotations = List.nil();
  1.2138 +        if (S.token() == MONKEYS_AT)
  1.2139 +            mods = modifiersOpt();
  1.2140 +
  1.2141 +        if (S.token() == PACKAGE) {
  1.2142 +            if (mods != null) {
  1.2143 +                checkNoMods(mods.flags);
  1.2144 +                packageAnnotations = mods.annotations;
  1.2145 +                mods = null;
  1.2146 +            }
  1.2147 +            S.nextToken();
  1.2148 +            pid = qualident();
  1.2149 +            accept(SEMI);
  1.2150 +        }
  1.2151 +        ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  1.2152 +       boolean checkForImports = true;
  1.2153 +        while (S.token() != EOF) {
  1.2154 +            if (S.pos() <= errorEndPos) {
  1.2155 +                // error recovery
  1.2156 +                skip(checkForImports, false, false, false);
  1.2157 +                if (S.token() == EOF)
  1.2158 +                    break;
  1.2159 +            }
  1.2160 +            if (checkForImports && mods == null && S.token() == IMPORT) {
  1.2161 +                defs.append(importDeclaration());
  1.2162 +            } else {
  1.2163 +                JCTree def = typeDeclaration(mods);
  1.2164 +                if (def instanceof JCExpressionStatement)
  1.2165 +                    def = ((JCExpressionStatement)def).expr;
  1.2166 +                defs.append(def);
  1.2167 +                if (def instanceof JCClassDecl)
  1.2168 +                    checkForImports = false;
  1.2169 +                mods = null;
  1.2170 +            }
  1.2171 +        }
  1.2172 +        JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
  1.2173 +        attach(toplevel, dc);
  1.2174 +        if (defs.elems.isEmpty())
  1.2175 +            storeEnd(toplevel, S.prevEndPos());
  1.2176 +        if (keepDocComments) toplevel.docComments = docComments;
  1.2177 +        return toplevel;
  1.2178 +    }
  1.2179 +
  1.2180 +    /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  1.2181 +     */
  1.2182 +    JCTree importDeclaration() {
  1.2183 +        int pos = S.pos();
  1.2184 +        S.nextToken();
  1.2185 +        boolean importStatic = false;
  1.2186 +        if (S.token() == STATIC) {
  1.2187 +            checkStaticImports();
  1.2188 +            importStatic = true;
  1.2189 +            S.nextToken();
  1.2190 +        }
  1.2191 +        JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
  1.2192 +        do {
  1.2193 +            int pos1 = S.pos();
  1.2194 +            accept(DOT);
  1.2195 +            if (S.token() == STAR) {
  1.2196 +                pid = to(F.at(pos1).Select(pid, names.asterisk));
  1.2197 +                S.nextToken();
  1.2198 +                break;
  1.2199 +            } else {
  1.2200 +                pid = toP(F.at(pos1).Select(pid, ident()));
  1.2201 +            }
  1.2202 +        } while (S.token() == DOT);
  1.2203 +        accept(SEMI);
  1.2204 +        return toP(F.at(pos).Import(pid, importStatic));
  1.2205 +    }
  1.2206 +
  1.2207 +    /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  1.2208 +     *                  | ";"
  1.2209 +     */
  1.2210 +    JCTree typeDeclaration(JCModifiers mods) {
  1.2211 +        int pos = S.pos();
  1.2212 +        if (mods == null && S.token() == SEMI) {
  1.2213 +            S.nextToken();
  1.2214 +            return toP(F.at(pos).Skip());
  1.2215 +        } else {
  1.2216 +            String dc = S.docComment();
  1.2217 +            return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
  1.2218 +        }
  1.2219 +    }
  1.2220 +
  1.2221 +    /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  1.2222 +     *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  1.2223 +     *  @param mods     Any modifiers starting the class or interface declaration
  1.2224 +     *  @param dc       The documentation comment for the class, or null.
  1.2225 +     */
  1.2226 +    JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
  1.2227 +        if (S.token() == CLASS) {
  1.2228 +            return classDeclaration(mods, dc);
  1.2229 +        } else if (S.token() == INTERFACE) {
  1.2230 +            return interfaceDeclaration(mods, dc);
  1.2231 +        } else if (allowEnums) {
  1.2232 +            if (S.token() == ENUM) {
  1.2233 +                return enumDeclaration(mods, dc);
  1.2234 +            } else {
  1.2235 +                int pos = S.pos();
  1.2236 +                List<JCTree> errs;
  1.2237 +                if (S.token() == IDENTIFIER) {
  1.2238 +                    errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  1.2239 +                    setErrorEndPos(S.pos());
  1.2240 +                } else {
  1.2241 +                    errs = List.<JCTree>of(mods);
  1.2242 +                }
  1.2243 +                return toP(F.Exec(syntaxError(pos, errs, "expected3",
  1.2244 +                                              keywords.token2string(CLASS),
  1.2245 +                                              keywords.token2string(INTERFACE),
  1.2246 +                                              keywords.token2string(ENUM))));
  1.2247 +            }
  1.2248 +        } else {
  1.2249 +            if (S.token() == ENUM) {
  1.2250 +                log.error(S.pos(), "enums.not.supported.in.source", source.name);
  1.2251 +                allowEnums = true;
  1.2252 +                return enumDeclaration(mods, dc);
  1.2253 +            }
  1.2254 +            int pos = S.pos();
  1.2255 +            List<JCTree> errs;
  1.2256 +            if (S.token() == IDENTIFIER) {
  1.2257 +                errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  1.2258 +                setErrorEndPos(S.pos());
  1.2259 +            } else {
  1.2260 +                errs = List.<JCTree>of(mods);
  1.2261 +            }
  1.2262 +            return toP(F.Exec(syntaxError(pos, errs, "expected2",
  1.2263 +                                          keywords.token2string(CLASS),
  1.2264 +                                          keywords.token2string(INTERFACE))));
  1.2265 +        }
  1.2266 +    }
  1.2267 +
  1.2268 +    /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  1.2269 +     *                     [IMPLEMENTS TypeList] ClassBody
  1.2270 +     *  @param mods    The modifiers starting the class declaration
  1.2271 +     *  @param dc       The documentation comment for the class, or null.
  1.2272 +     */
  1.2273 +    JCClassDecl classDeclaration(JCModifiers mods, String dc) {
  1.2274 +        int pos = S.pos();
  1.2275 +        accept(CLASS);
  1.2276 +        Name name = ident();
  1.2277 +
  1.2278 +        List<JCTypeParameter> typarams = typeParametersOpt();
  1.2279 +
  1.2280 +        JCTree extending = null;
  1.2281 +        if (S.token() == EXTENDS) {
  1.2282 +            S.nextToken();
  1.2283 +            extending = type();
  1.2284 +        }
  1.2285 +        List<JCExpression> implementing = List.nil();
  1.2286 +        if (S.token() == IMPLEMENTS) {
  1.2287 +            S.nextToken();
  1.2288 +            implementing = typeList();
  1.2289 +        }
  1.2290 +        List<JCTree> defs = classOrInterfaceBody(name, false);
  1.2291 +        JCClassDecl result = toP(F.at(pos).ClassDef(
  1.2292 +            mods, name, typarams, extending, implementing, defs));
  1.2293 +        attach(result, dc);
  1.2294 +        return result;
  1.2295 +    }
  1.2296 +
  1.2297 +    /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  1.2298 +     *                         [EXTENDS TypeList] InterfaceBody
  1.2299 +     *  @param mods    The modifiers starting the interface declaration
  1.2300 +     *  @param dc       The documentation comment for the interface, or null.
  1.2301 +     */
  1.2302 +    JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
  1.2303 +        int pos = S.pos();
  1.2304 +        accept(INTERFACE);
  1.2305 +        Name name = ident();
  1.2306 +
  1.2307 +        List<JCTypeParameter> typarams = typeParametersOpt();
  1.2308 +
  1.2309 +        List<JCExpression> extending = List.nil();
  1.2310 +        if (S.token() == EXTENDS) {
  1.2311 +            S.nextToken();
  1.2312 +            extending = typeList();
  1.2313 +        }
  1.2314 +        List<JCTree> defs = classOrInterfaceBody(name, true);
  1.2315 +        JCClassDecl result = toP(F.at(pos).ClassDef(
  1.2316 +            mods, name, typarams, null, extending, defs));
  1.2317 +        attach(result, dc);
  1.2318 +        return result;
  1.2319 +    }
  1.2320 +
  1.2321 +    /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  1.2322 +     *  @param mods    The modifiers starting the enum declaration
  1.2323 +     *  @param dc       The documentation comment for the enum, or null.
  1.2324 +     */
  1.2325 +    JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
  1.2326 +        int pos = S.pos();
  1.2327 +        accept(ENUM);
  1.2328 +        Name name = ident();
  1.2329 +
  1.2330 +        List<JCExpression> implementing = List.nil();
  1.2331 +        if (S.token() == IMPLEMENTS) {
  1.2332 +            S.nextToken();
  1.2333 +            implementing = typeList();
  1.2334 +        }
  1.2335 +
  1.2336 +        List<JCTree> defs = enumBody(name);
  1.2337 +        JCModifiers newMods =
  1.2338 +            F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
  1.2339 +        JCClassDecl result = toP(F.at(pos).
  1.2340 +            ClassDef(newMods, name, List.<JCTypeParameter>nil(),
  1.2341 +                null, implementing, defs));
  1.2342 +        attach(result, dc);
  1.2343 +        return result;
  1.2344 +    }
  1.2345 +
  1.2346 +    /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  1.2347 +     *                  [ ";" {ClassBodyDeclaration} ] "}"
  1.2348 +     */
  1.2349 +    List<JCTree> enumBody(Name enumName) {
  1.2350 +        accept(LBRACE);
  1.2351 +        ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  1.2352 +        if (S.token() == COMMA) {
  1.2353 +            S.nextToken();
  1.2354 +        } else if (S.token() != RBRACE && S.token() != SEMI) {
  1.2355 +            defs.append(enumeratorDeclaration(enumName));
  1.2356 +            while (S.token() == COMMA) {
  1.2357 +                S.nextToken();
  1.2358 +                if (S.token() == RBRACE || S.token() == SEMI) break;
  1.2359 +                defs.append(enumeratorDeclaration(enumName));
  1.2360 +            }
  1.2361 +            if (S.token() != SEMI && S.token() != RBRACE) {
  1.2362 +                defs.append(syntaxError(S.pos(), "expected3",
  1.2363 +                                keywords.token2string(COMMA),
  1.2364 +                                keywords.token2string(RBRACE),
  1.2365 +                                keywords.token2string(SEMI)));
  1.2366 +                S.nextToken();
  1.2367 +            }
  1.2368 +        }
  1.2369 +        if (S.token() == SEMI) {
  1.2370 +            S.nextToken();
  1.2371 +            while (S.token() != RBRACE && S.token() != EOF) {
  1.2372 +                defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  1.2373 +                                                                false));
  1.2374 +                if (S.pos() <= errorEndPos) {
  1.2375 +                    // error recovery
  1.2376 +                   skip(false, true, true, false);
  1.2377 +                }
  1.2378 +            }
  1.2379 +        }
  1.2380 +        accept(RBRACE);
  1.2381 +        return defs.toList();
  1.2382 +    }
  1.2383 +
  1.2384 +    /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  1.2385 +     */
  1.2386 +    JCTree enumeratorDeclaration(Name enumName) {
  1.2387 +        String dc = S.docComment();
  1.2388 +        int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  1.2389 +        if (S.deprecatedFlag()) {
  1.2390 +            flags |= Flags.DEPRECATED;
  1.2391 +            S.resetDeprecatedFlag();
  1.2392 +        }
  1.2393 +        int pos = S.pos();
  1.2394 +        List<JCAnnotation> annotations = annotationsOpt();
  1.2395 +        JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  1.2396 +        List<JCExpression> typeArgs = typeArgumentsOpt();
  1.2397 +        int identPos = S.pos();
  1.2398 +        Name name = ident();
  1.2399 +        int createPos = S.pos();
  1.2400 +        List<JCExpression> args = (S.token() == LPAREN)
  1.2401 +            ? arguments() : List.<JCExpression>nil();
  1.2402 +        JCClassDecl body = null;
  1.2403 +        if (S.token() == LBRACE) {
  1.2404 +            JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  1.2405 +            List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1.2406 +            body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  1.2407 +        }
  1.2408 +        if (args.isEmpty() && body == null)
  1.2409 +            createPos = Position.NOPOS;
  1.2410 +        JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
  1.2411 +        JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  1.2412 +        if (createPos != Position.NOPOS)
  1.2413 +            storeEnd(create, S.prevEndPos());
  1.2414 +        ident = F.at(Position.NOPOS).Ident(enumName);
  1.2415 +        JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  1.2416 +        attach(result, dc);
  1.2417 +        return result;
  1.2418 +    }
  1.2419 +
  1.2420 +    /** TypeList = Type {"," Type}
  1.2421 +     */
  1.2422 +    List<JCExpression> typeList() {
  1.2423 +        ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  1.2424 +        ts.append(type());
  1.2425 +        while (S.token() == COMMA) {
  1.2426 +            S.nextToken();
  1.2427 +            ts.append(type());
  1.2428 +        }
  1.2429 +        return ts.toList();
  1.2430 +    }
  1.2431 +
  1.2432 +    /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  1.2433 +     *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  1.2434 +     */
  1.2435 +    List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  1.2436 +        accept(LBRACE);
  1.2437 +        if (S.pos() <= errorEndPos) {
  1.2438 +            // error recovery
  1.2439 +            skip(false, true, false, false);
  1.2440 +            if (S.token() == LBRACE)
  1.2441 +                S.nextToken();
  1.2442 +        }
  1.2443 +        ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  1.2444 +        while (S.token() != RBRACE && S.token() != EOF) {
  1.2445 +            defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  1.2446 +            if (S.pos() <= errorEndPos) {
  1.2447 +               // error recovery
  1.2448 +               skip(false, true, true, false);
  1.2449 +           }
  1.2450 +        }
  1.2451 +        accept(RBRACE);
  1.2452 +        return defs.toList();
  1.2453 +    }
  1.2454 +
  1.2455 +    /** ClassBodyDeclaration =
  1.2456 +     *      ";"
  1.2457 +     *    | [STATIC] Block
  1.2458 +     *    | ModifiersOpt
  1.2459 +     *      ( Type Ident
  1.2460 +     *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  1.2461 +     *      | VOID Ident MethodDeclaratorRest
  1.2462 +     *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  1.2463 +     *      | Ident ConstructorDeclaratorRest
  1.2464 +     *      | TypeParameters Ident ConstructorDeclaratorRest
  1.2465 +     *      | ClassOrInterfaceOrEnumDeclaration
  1.2466 +     *      )
  1.2467 +     *  InterfaceBodyDeclaration =
  1.2468 +     *      ";"
  1.2469 +     *    | ModifiersOpt Type Ident
  1.2470 +     *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  1.2471 +     */
  1.2472 +    List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  1.2473 +        if (S.token() == SEMI) {
  1.2474 +            S.nextToken();
  1.2475 +            return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
  1.2476 +        } else {
  1.2477 +            String dc = S.docComment();
  1.2478 +            int pos = S.pos();
  1.2479 +            JCModifiers mods = modifiersOpt();
  1.2480 +            if (S.token() == CLASS ||
  1.2481 +                S.token() == INTERFACE ||
  1.2482 +                allowEnums && S.token() == ENUM) {
  1.2483 +                return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1.2484 +            } else if (S.token() == LBRACE && !isInterface &&
  1.2485 +                       (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  1.2486 +                       mods.annotations.isEmpty()) {
  1.2487 +                return List.<JCTree>of(block(pos, mods.flags));
  1.2488 +            } else {
  1.2489 +                pos = S.pos();
  1.2490 +                List<JCTypeParameter> typarams = typeParametersOpt();
  1.2491 +                // Hack alert:  if there are type arguments but no Modifiers, the start
  1.2492 +                // position will be lost unless we set the Modifiers position.  There
  1.2493 +                // should be an AST node for type parameters (BugId 5005090).
  1.2494 +                if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
  1.2495 +                    mods.pos = pos;
  1.2496 +                }
  1.2497 +                Token token = S.token();
  1.2498 +                Name name = S.name();
  1.2499 +                pos = S.pos();
  1.2500 +                JCExpression type;
  1.2501 +                boolean isVoid = S.token() == VOID;
  1.2502 +                if (isVoid) {
  1.2503 +                    type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  1.2504 +                    S.nextToken();
  1.2505 +                } else {
  1.2506 +                    type = type();
  1.2507 +                }
  1.2508 +                if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
  1.2509 +                    if (isInterface || name != className)
  1.2510 +                        log.error(pos, "invalid.meth.decl.ret.type.req");
  1.2511 +                    return List.of(methodDeclaratorRest(
  1.2512 +                        pos, mods, null, names.init, typarams,
  1.2513 +                        isInterface, true, dc));
  1.2514 +                } else {
  1.2515 +                    pos = S.pos();
  1.2516 +                    name = ident();
  1.2517 +                    if (S.token() == LPAREN) {
  1.2518 +                        return List.of(methodDeclaratorRest(
  1.2519 +                            pos, mods, type, name, typarams,
  1.2520 +                            isInterface, isVoid, dc));
  1.2521 +                    } else if (!isVoid && typarams.isEmpty()) {
  1.2522 +                        List<JCTree> defs =
  1.2523 +                            variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  1.2524 +                                                    new ListBuffer<JCTree>()).toList();
  1.2525 +                        storeEnd(defs.last(), S.endPos());
  1.2526 +                        accept(SEMI);
  1.2527 +                        return defs;
  1.2528 +                    } else {
  1.2529 +                        pos = S.pos();
  1.2530 +                        List<JCTree> err = isVoid
  1.2531 +                            ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  1.2532 +                                List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  1.2533 +                            : null;
  1.2534 +                        return List.<JCTree>of(syntaxError(S.pos(), err, "expected", keywords.token2string(LPAREN)));
  1.2535 +                    }
  1.2536 +                }
  1.2537 +            }
  1.2538 +        }
  1.2539 +    }
  1.2540 +
  1.2541 +    /** MethodDeclaratorRest =
  1.2542 +     *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  1.2543 +     *  VoidMethodDeclaratorRest =
  1.2544 +     *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  1.2545 +     *  InterfaceMethodDeclaratorRest =
  1.2546 +     *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  1.2547 +     *  VoidInterfaceMethodDeclaratorRest =
  1.2548 +     *      FormalParameters [THROWS TypeList] ";"
  1.2549 +     *  ConstructorDeclaratorRest =
  1.2550 +     *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  1.2551 +     */
  1.2552 +    JCTree methodDeclaratorRest(int pos,
  1.2553 +                              JCModifiers mods,
  1.2554 +                              JCExpression type,
  1.2555 +                              Name name,
  1.2556 +                              List<JCTypeParameter> typarams,
  1.2557 +                              boolean isInterface, boolean isVoid,
  1.2558 +                              String dc) {
  1.2559 +        List<JCVariableDecl> params = formalParameters();
  1.2560 +        if (!isVoid) type = bracketsOpt(type);
  1.2561 +        List<JCExpression> thrown = List.nil();
  1.2562 +        if (S.token() == THROWS) {
  1.2563 +            S.nextToken();
  1.2564 +            thrown = qualidentList();
  1.2565 +        }
  1.2566 +        JCBlock body = null;
  1.2567 +        JCExpression defaultValue;
  1.2568 +        if (S.token() == LBRACE) {
  1.2569 +            body = block();
  1.2570 +            defaultValue = null;
  1.2571 +        } else {
  1.2572 +            if (S.token() == DEFAULT) {
  1.2573 +                accept(DEFAULT);
  1.2574 +                defaultValue = annotationValue();
  1.2575 +            } else {
  1.2576 +                defaultValue = null;
  1.2577 +            }
  1.2578 +            accept(SEMI);
  1.2579 +            if (S.pos() <= errorEndPos) {
  1.2580 +                // error recovery
  1.2581 +                skip(false, true, false, false);
  1.2582 +                if (S.token() == LBRACE) {
  1.2583 +                    body = block();
  1.2584 +                }
  1.2585 +            }
  1.2586 +        }
  1.2587 +        JCMethodDecl result =
  1.2588 +            toP(F.at(pos).MethodDef(mods, name, type, typarams,
  1.2589 +                                    params, thrown,
  1.2590 +                                    body, defaultValue));
  1.2591 +        attach(result, dc);
  1.2592 +        return result;
  1.2593 +    }
  1.2594 +
  1.2595 +    /** QualidentList = Qualident {"," Qualident}
  1.2596 +     */
  1.2597 +    List<JCExpression> qualidentList() {
  1.2598 +        ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  1.2599 +        ts.append(qualident());
  1.2600 +        while (S.token() == COMMA) {
  1.2601 +            S.nextToken();
  1.2602 +            ts.append(qualident());
  1.2603 +        }
  1.2604 +        return ts.toList();
  1.2605 +    }
  1.2606 +
  1.2607 +    /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  1.2608 +     */
  1.2609 +    List<JCTypeParameter> typeParametersOpt() {
  1.2610 +        if (S.token() == LT) {
  1.2611 +            checkGenerics();
  1.2612 +            ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  1.2613 +            S.nextToken();
  1.2614 +            typarams.append(typeParameter());
  1.2615 +            while (S.token() == COMMA) {
  1.2616 +                S.nextToken();
  1.2617 +                typarams.append(typeParameter());
  1.2618 +            }
  1.2619 +            accept(GT);
  1.2620 +            return typarams.toList();
  1.2621 +        } else {
  1.2622 +            return List.nil();
  1.2623 +        }
  1.2624 +    }
  1.2625 +
  1.2626 +    /** TypeParameter = TypeVariable [TypeParameterBound]
  1.2627 +     *  TypeParameterBound = EXTENDS Type {"&" Type}
  1.2628 +     *  TypeVariable = Ident
  1.2629 +     */
  1.2630 +    JCTypeParameter typeParameter() {
  1.2631 +        int pos = S.pos();
  1.2632 +        Name name = ident();
  1.2633 +        ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  1.2634 +        if (S.token() == EXTENDS) {
  1.2635 +            S.nextToken();
  1.2636 +            bounds.append(type());
  1.2637 +            while (S.token() == AMP) {
  1.2638 +                S.nextToken();
  1.2639 +                bounds.append(type());
  1.2640 +            }
  1.2641 +        }
  1.2642 +        return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  1.2643 +    }
  1.2644 +
  1.2645 +    /** FormalParameters = "(" [ FormalParameterList ] ")"
  1.2646 +     *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  1.2647 +     *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  1.2648 +     */
  1.2649 +    List<JCVariableDecl> formalParameters() {
  1.2650 +        ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  1.2651 +        JCVariableDecl lastParam = null;
  1.2652 +        accept(LPAREN);
  1.2653 +        if (S.token() != RPAREN) {
  1.2654 +            params.append(lastParam = formalParameter());
  1.2655 +            while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
  1.2656 +                S.nextToken();
  1.2657 +                params.append(lastParam = formalParameter());
  1.2658 +            }
  1.2659 +        }
  1.2660 +        accept(RPAREN);
  1.2661 +        return params.toList();
  1.2662 +    }
  1.2663 +
  1.2664 +    JCModifiers optFinal(long flags) {
  1.2665 +        JCModifiers mods = modifiersOpt();
  1.2666 +        checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  1.2667 +        mods.flags |= flags;
  1.2668 +        return mods;
  1.2669 +    }
  1.2670 +
  1.2671 +    /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  1.2672 +     *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  1.2673 +     */
  1.2674 +    JCVariableDecl formalParameter() {
  1.2675 +        JCModifiers mods = optFinal(Flags.PARAMETER);
  1.2676 +        JCExpression type = type();
  1.2677 +        if (S.token() == ELLIPSIS) {
  1.2678 +            checkVarargs();
  1.2679 +            mods.flags |= Flags.VARARGS;
  1.2680 +            type = to(F.at(S.pos()).TypeArray(type));
  1.2681 +            S.nextToken();
  1.2682 +        }
  1.2683 +        return variableDeclaratorId(mods, type);
  1.2684 +    }
  1.2685 +
  1.2686 +/* ---------- auxiliary methods -------------- */
  1.2687 +
  1.2688 +    /** Check that given tree is a legal expression statement.
  1.2689 +     */
  1.2690 +    protected JCExpression checkExprStat(JCExpression t) {
  1.2691 +        switch(t.getTag()) {
  1.2692 +        case JCTree.PREINC: case JCTree.PREDEC:
  1.2693 +        case JCTree.POSTINC: case JCTree.POSTDEC:
  1.2694 +        case JCTree.ASSIGN:
  1.2695 +        case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
  1.2696 +        case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
  1.2697 +        case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
  1.2698 +        case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
  1.2699 +        case JCTree.APPLY: case JCTree.NEWCLASS:
  1.2700 +        case JCTree.ERRONEOUS:
  1.2701 +            return t;
  1.2702 +        default:
  1.2703 +            log.error(t.pos, "not.stmt");
  1.2704 +            return F.at(t.pos).Erroneous(List.<JCTree>of(t));
  1.2705 +        }
  1.2706 +    }
  1.2707 +
  1.2708 +    /** Return precedence of operator represented by token,
  1.2709 +     *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  1.2710 +     */
  1.2711 +    static int prec(Token token) {
  1.2712 +        int oc = optag(token);
  1.2713 +        return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
  1.2714 +    }
  1.2715 +
  1.2716 +    /** Return operation tag of binary operator represented by token,
  1.2717 +     *  -1 if token is not a binary operator.
  1.2718 +     */
  1.2719 +    static int optag(Token token) {
  1.2720 +        switch (token) {
  1.2721 +        case BARBAR:
  1.2722 +            return JCTree.OR;
  1.2723 +        case AMPAMP:
  1.2724 +            return JCTree.AND;
  1.2725 +        case BAR:
  1.2726 +            return JCTree.BITOR;
  1.2727 +        case BAREQ:
  1.2728 +            return JCTree.BITOR_ASG;
  1.2729 +        case CARET:
  1.2730 +            return JCTree.BITXOR;
  1.2731 +        case CARETEQ:
  1.2732 +            return JCTree.BITXOR_ASG;
  1.2733 +        case AMP:
  1.2734 +            return JCTree.BITAND;
  1.2735 +        case AMPEQ:
  1.2736 +            return JCTree.BITAND_ASG;
  1.2737 +        case EQEQ:
  1.2738 +            return JCTree.EQ;
  1.2739 +        case BANGEQ:
  1.2740 +            return JCTree.NE;
  1.2741 +        case LT:
  1.2742 +            return JCTree.LT;
  1.2743 +        case GT:
  1.2744 +            return JCTree.GT;
  1.2745 +        case LTEQ:
  1.2746 +            return JCTree.LE;
  1.2747 +        case GTEQ:
  1.2748 +            return JCTree.GE;
  1.2749 +        case LTLT:
  1.2750 +            return JCTree.SL;
  1.2751 +        case LTLTEQ:
  1.2752 +            return JCTree.SL_ASG;
  1.2753 +        case GTGT:
  1.2754 +            return JCTree.SR;
  1.2755 +        case GTGTEQ:
  1.2756 +            return JCTree.SR_ASG;
  1.2757 +        case GTGTGT:
  1.2758 +            return JCTree.USR;
  1.2759 +        case GTGTGTEQ:
  1.2760 +            return JCTree.USR_ASG;
  1.2761 +        case PLUS:
  1.2762 +            return JCTree.PLUS;
  1.2763 +        case PLUSEQ:
  1.2764 +            return JCTree.PLUS_ASG;
  1.2765 +        case SUB:
  1.2766 +            return JCTree.MINUS;
  1.2767 +        case SUBEQ:
  1.2768 +            return JCTree.MINUS_ASG;
  1.2769 +        case STAR:
  1.2770 +            return JCTree.MUL;
  1.2771 +        case STAREQ:
  1.2772 +            return JCTree.MUL_ASG;
  1.2773 +        case SLASH:
  1.2774 +            return JCTree.DIV;
  1.2775 +        case SLASHEQ:
  1.2776 +            return JCTree.DIV_ASG;
  1.2777 +        case PERCENT:
  1.2778 +            return JCTree.MOD;
  1.2779 +        case PERCENTEQ:
  1.2780 +            return JCTree.MOD_ASG;
  1.2781 +        case INSTANCEOF:
  1.2782 +            return JCTree.TYPETEST;
  1.2783 +        default:
  1.2784 +            return -1;
  1.2785 +        }
  1.2786 +    }
  1.2787 +
  1.2788 +    /** Return operation tag of unary operator represented by token,
  1.2789 +     *  -1 if token is not a binary operator.
  1.2790 +     */
  1.2791 +    static int unoptag(Token token) {
  1.2792 +        switch (token) {
  1.2793 +        case PLUS:
  1.2794 +            return JCTree.POS;
  1.2795 +        case SUB:
  1.2796 +            return JCTree.NEG;
  1.2797 +        case BANG:
  1.2798 +            return JCTree.NOT;
  1.2799 +        case TILDE:
  1.2800 +            return JCTree.COMPL;
  1.2801 +        case PLUSPLUS:
  1.2802 +            return JCTree.PREINC;
  1.2803 +        case SUBSUB:
  1.2804 +            return JCTree.PREDEC;
  1.2805 +        default:
  1.2806 +            return -1;
  1.2807 +        }
  1.2808 +    }
  1.2809 +
  1.2810 +    /** Return type tag of basic type represented by token,
  1.2811 +     *  -1 if token is not a basic type identifier.
  1.2812 +     */
  1.2813 +    static int typetag(Token token) {
  1.2814 +        switch (token) {
  1.2815 +        case BYTE:
  1.2816 +            return TypeTags.BYTE;
  1.2817 +        case CHAR:
  1.2818 +            return TypeTags.CHAR;
  1.2819 +        case SHORT:
  1.2820 +            return TypeTags.SHORT;
  1.2821 +        case INT:
  1.2822 +            return TypeTags.INT;
  1.2823 +        case LONG:
  1.2824 +            return TypeTags.LONG;
  1.2825 +        case FLOAT:
  1.2826 +            return TypeTags.FLOAT;
  1.2827 +        case DOUBLE:
  1.2828 +            return TypeTags.DOUBLE;
  1.2829 +        case BOOLEAN:
  1.2830 +            return TypeTags.BOOLEAN;
  1.2831 +        default:
  1.2832 +            return -1;
  1.2833 +        }
  1.2834 +    }
  1.2835 +
  1.2836 +    void checkGenerics() {
  1.2837 +        if (!allowGenerics) {
  1.2838 +            log.error(S.pos(), "generics.not.supported.in.source", source.name);
  1.2839 +            allowGenerics = true;
  1.2840 +        }
  1.2841 +    }
  1.2842 +    void checkVarargs() {
  1.2843 +        if (!allowVarargs) {
  1.2844 +            log.error(S.pos(), "varargs.not.supported.in.source", source.name);
  1.2845 +            allowVarargs = true;
  1.2846 +        }
  1.2847 +    }
  1.2848 +    void checkForeach() {
  1.2849 +        if (!allowForeach) {
  1.2850 +            log.error(S.pos(), "foreach.not.supported.in.source", source.name);
  1.2851 +            allowForeach = true;
  1.2852 +        }
  1.2853 +    }
  1.2854 +    void checkStaticImports() {
  1.2855 +        if (!allowStaticImport) {
  1.2856 +            log.error(S.pos(), "static.import.not.supported.in.source", source.name);
  1.2857 +            allowStaticImport = true;
  1.2858 +        }
  1.2859 +    }
  1.2860 +    void checkAnnotations() {
  1.2861 +        if (!allowAnnotations) {
  1.2862 +            log.error(S.pos(), "annotations.not.supported.in.source", source.name);
  1.2863 +            allowAnnotations = true;
  1.2864 +        }
  1.2865 +    }
  1.2866 +}

mercurial