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

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

mercurial