/*
 * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.tools.java;

import sun.tools.tree.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Vector;

/**
 * This class is used to parse Java statements and expressions.
 * The result is a parse tree.<p>
 *
 * This class implements an operator precedence parser. Errors are
 * reported to the Environment object, if the error can't be
 * resolved immediately, a SyntaxError exception is thrown.<p>
 *
 * Error recovery is implemented by catching SyntaxError exceptions
 * and discarding input tokens until an input token is reached that
 * is possibly a legal continuation.<p>
 *
 * The parse tree that is constructed represents the input
 * exactly (no rewrites to simpler forms). This is important
 * if the resulting tree is to be used for code formatting in
 * a programming environment. Currently only documentation comments
 * are retained.<p>
 *
 * The parsing algorithm does NOT use any type information. Changes
 * in the type system do not affect the structure of the parse tree.
 * This restriction does introduce an ambiguity an expression of the
 * form: (e1) e2 is assumed to be a cast if e2 does not start with
 * an operator. That means that (a) - b is interpreted as subtract
 * b from a and not cast negative b to type a. However, if a is a
 * simple type (byte, int, ...) then it is assumed to be a cast.<p>
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 *
 * @author      Arthur van Hoff
 */

public
class Parser extends Scanner implements ParserActions, Constants {
    /**
     * Create a parser
     */
    protected Parser(Environment env, InputStream in) throws IOException {
        super(env, in);
        this.scanner = this;
        this.actions = this;
    }

    /**
     * Create a parser, given a scanner.
     */
    protected Parser(Scanner scanner) throws IOException {
        super(scanner.env);
        this.scanner = scanner;
        ((Scanner)this).env = scanner.env;
        ((Scanner)this).token = scanner.token;
        ((Scanner)this).pos = scanner.pos;
        this.actions = this;
    }

    /**
     * Create a parser, given a scanner and the semantic callback.
     */
    public Parser(Scanner scanner, ParserActions actions) throws IOException {
        this(scanner);
        this.actions = actions;
    }

    /**
     * Usually <code>this.actions == (ParserActions)this</code>.
     * However, a delegate scanner can produce tokens for this parser,
     * in which case <code>(Scanner)this</code> is unused,
     * except for <code>this.token</code> and <code>this.pos</code>
     * instance variables which are filled from the real scanner
     * by <code>this.scan()</code> and the constructor.
     */
    ParserActions actions;

    // Note:  The duplication of methods allows pre-1.1 classes to
    // be binary compatible with the new version of the parser,
    // which now passes IdentifierTokens to the semantics phase,
    // rather than just Identifiers.  This change is necessary,
    // since the parser is no longer responsible for managing the
    // resolution of type names.  (That caused the "Vector" bug.)
    //
    // In a future release, the old "plain-Identifier" methods will
    // go away, and the corresponding "IdentifierToken" methods
    // may become abstract.

    /**
     * package declaration
     * @deprecated
     */
    @Deprecated
    public void packageDeclaration(long off, IdentifierToken nm) {
        // By default, call the deprecated version.
        // Any application must override one of the packageDeclaration methods.
        packageDeclaration(off, nm.id);
    }
    /**
     * @deprecated
     */
    @Deprecated
    protected void packageDeclaration(long off, Identifier nm) {
        throw new RuntimeException("beginClass method is abstract");
    }

    /**
     * import class
     * @deprecated
     */
    @Deprecated
    public void importClass(long off, IdentifierToken nm) {
        // By default, call the deprecated version.
        // Any application must override one of the packageDeclaration methods.
        importClass(off, nm.id);
    }
    /**
     * @deprecated Use the version with the IdentifierToken arguments.
     */
    @Deprecated
    protected void importClass(long off, Identifier nm) {
        throw new RuntimeException("importClass method is abstract");
    }

    /**
     * import package
     * @deprecated
     */
    @Deprecated
    public void importPackage(long off, IdentifierToken nm) {
        // By default, call the deprecated version.
        // Any application must override one of the importPackage methods.
        importPackage(off, nm.id);
    }
    /**
     * @deprecated Use the version with the IdentifierToken arguments.
     */
    @Deprecated
    protected void importPackage(long off, Identifier nm) {
        throw new RuntimeException("importPackage method is abstract");
    }

    /**
     * Define class
     * @deprecated
     */
    @Deprecated
    public ClassDefinition beginClass(long off, String doc,
                                      int mod, IdentifierToken nm,
                                      IdentifierToken sup,
                                      IdentifierToken impl[]) {
        // By default, call the deprecated version.
        // Any application must override one of the beginClass methods.
        Identifier supId = (sup == null) ? null : sup.id;
        Identifier implIds[] = null;
        if (impl != null) {
            implIds = new Identifier[impl.length];
            for (int i = 0; i < impl.length; i++) {
                implIds[i] = impl[i].id;
            }
        }
        beginClass(off, doc, mod, nm.id, supId, implIds);
        return getCurrentClass();
    }
    /**
     * @deprecated Use the version with the IdentifierToken arguments.
     */
    @Deprecated
    protected void beginClass(long off, String doc, int mod, Identifier nm,
                              Identifier sup, Identifier impl[]) {
        throw new RuntimeException("beginClass method is abstract");
    }

    /**
     * Report the current class under construction.
     * By default, it's a no-op which returns null.
     * It may only be called before the corresponding endClass().
     */
    protected ClassDefinition getCurrentClass() {
        return null;
    }

    /**
     * End class
     * @deprecated
     */
    @Deprecated
    public void endClass(long off, ClassDefinition c) {
        // By default, call the deprecated version.
        // Any application must override one of the beginClass methods.
        endClass(off, c.getName().getFlatName().getName());
    }
    /**
     * @deprecated Use the version with the IdentifierToken arguments.
     */
    @Deprecated
    protected void endClass(long off, Identifier nm) {
        throw new RuntimeException("endClass method is abstract");
    }

    /**
     * Define a field
     * @deprecated
     */
    @Deprecated
    public void defineField(long where, ClassDefinition c,
                            String doc, int mod, Type t,
                            IdentifierToken nm, IdentifierToken args[],
                            IdentifierToken exp[], Node val) {
        // By default, call the deprecated version.
        // Any application must override one of the defineField methods.
        Identifier argIds[] = null;
        Identifier expIds[] = null;
        if (args != null) {
            argIds = new Identifier[args.length];
            for (int i = 0; i < args.length; i++) {
                argIds[i] = args[i].id;
            }
        }
        if (exp != null) {
            expIds = new Identifier[exp.length];
            for (int i = 0; i < exp.length; i++) {
                expIds[i] = exp[i].id;
            }
        }
        defineField(where, doc, mod, t, nm.id, argIds, expIds, val);
    }

    /**
     * @deprecated Use the version with the IdentifierToken arguments.
     */
    @Deprecated
    protected void defineField(long where, String doc, int mod, Type t,
                               Identifier nm, Identifier args[],
                               Identifier exp[], Node val) {
        throw new RuntimeException("defineField method is abstract");
    }

    /*
     * A growable array of nodes. It is used as a growable
     * buffer to hold argument lists and expression lists.
     * I'm not using Vector to make it more efficient.
     */
    private Node args[] = new Node[32];
    protected int argIndex = 0;

    protected final void addArgument(Node n) {
        if (argIndex == args.length) {
            Node newArgs[] = new Node[args.length * 2];
            System.arraycopy(args, 0, newArgs, 0, args.length);
            args = newArgs;
        }
        args[argIndex++] = n;
    }
    protected final Expression exprArgs(int index)[] {
        Expression e[] = new Expression[argIndex - index];
        System.arraycopy(args, index, e, 0, argIndex - index);
        argIndex = index;
        return e;
    }
    protected final Statement statArgs(int index)[] {
        Statement s[] = new Statement[argIndex - index];
        System.arraycopy(args, index, s, 0, argIndex - index);
        argIndex = index;
        return s;
    }

    /**
     * Expect a token, return its value, scan the next token or
     * throw an exception.
     */
    protected void expect(int t) throws SyntaxError, IOException {
        if (token != t) {
            switch (t) {
              case IDENT:
                env.error(scanner.prevPos, "identifier.expected");
                break;
              default:
                env.error(scanner.prevPos, "token.expected", opNames[t]);
                break;
            }
                throw new SyntaxError();
        }
        scan();
    }

    /**
     * Parse a type expression. Does not parse the []'s.
     */
    protected Expression parseTypeExpression() throws SyntaxError, IOException {
        switch (token) {
          case VOID:
            return new TypeExpression(scan(), Type.tVoid);
          case BOOLEAN:
            return new TypeExpression(scan(), Type.tBoolean);
          case BYTE:
            return new TypeExpression(scan(), Type.tByte);
          case CHAR:
            return new TypeExpression(scan(), Type.tChar);
          case SHORT:
            return new TypeExpression(scan(), Type.tShort);
          case INT:
            return new TypeExpression(scan(), Type.tInt);
          case LONG:
            return new TypeExpression(scan(), Type.tLong);
          case FLOAT:
            return new TypeExpression(scan(), Type.tFloat);
          case DOUBLE:
            return new TypeExpression(scan(), Type.tDouble);
          case IDENT:
            Expression e = new IdentifierExpression(pos, scanner.idValue);
            scan();
            while (token == FIELD) {
                e = new FieldExpression(scan(), e, scanner.idValue);
                expect(IDENT);
            }
            return e;
        }

        env.error(pos, "type.expected");
        throw new SyntaxError();
    }

    /**
     * Parse a method invocation. Should be called when the current
     * then is the '(' of the argument list.
     */
    protected Expression parseMethodExpression(Expression e, Identifier id) throws SyntaxError, IOException {
       long p = scan();
       int i = argIndex;
       if (token != RPAREN) {
           addArgument(parseExpression());
           while (token == COMMA) {
               scan();
               addArgument(parseExpression());
           }
       }
       expect(RPAREN);
       return new MethodExpression(p, e, id, exprArgs(i));
    }

    /**
     * Parse a new instance expression.  Should be called when the current
     * token is the '(' of the argument list.
     */
    protected Expression parseNewInstanceExpression(long p, Expression outerArg, Expression type) throws SyntaxError, IOException {
        int i = argIndex;
        expect(LPAREN);
        if (token != RPAREN) {
            addArgument(parseExpression());
            while (token == COMMA) {
                scan();
                addArgument(parseExpression());
            }
        }
        expect(RPAREN);
        ClassDefinition body = null;
        if (token == LBRACE && !(type instanceof TypeExpression)) {
            long tp = pos;
            // x = new Type(arg) { subclass body ... }
            Identifier superName = FieldExpression.toIdentifier(type);
            if (superName == null) {
                env.error(type.getWhere(), "type.expected");
            }
            Vector ext = new Vector(1);
            Vector impl = new Vector(0);
            ext.addElement(new IdentifierToken(idNull));
            if (token == IMPLEMENTS || token == EXTENDS) {
                env.error(pos, "anonymous.extends");
                parseInheritance(ext, impl); // error recovery
            }
            body = parseClassBody(new IdentifierToken(tp, idNull),
                                  M_ANONYMOUS | M_LOCAL, EXPR, null,
                                  ext, impl, type.getWhere());
        }
        if (outerArg == null && body == null) {
            return new NewInstanceExpression(p, type, exprArgs(i));
        }
        return new NewInstanceExpression(p, type, exprArgs(i), outerArg, body);
    }

    /**
     * Parse a primary expression.
     */
    protected Expression parseTerm() throws SyntaxError, IOException {
        switch (token) {
          case CHARVAL: {
            char v = scanner.charValue;
            return new CharExpression(scan(), v);
          }
          case INTVAL: {
            int v = scanner.intValue;
            long q = scan();
            if (v < 0 && radix == 10) env.error(q, "overflow.int.dec");
            return new IntExpression(q, v);
          }
          case LONGVAL: {
            long v = scanner.longValue;
            long q = scan();
            if (v < 0 && radix == 10) env.error(q, "overflow.long.dec");
            return new LongExpression(q, v);
          }
          case FLOATVAL: {
            float v = scanner.floatValue;
            return new FloatExpression(scan(), v);
          }
          case DOUBLEVAL: {
            double v = scanner.doubleValue;
            return new DoubleExpression(scan(), v);
          }
          case STRINGVAL: {
            String v = scanner.stringValue;
            return new StringExpression(scan(), v);
          }
          case IDENT: {
            Identifier v = scanner.idValue;
            long p = scan();
            return (token == LPAREN) ?
                        parseMethodExpression(null, v) : new IdentifierExpression(p, v);
          }

          case TRUE:
            return new BooleanExpression(scan(), true);
          case FALSE:
            return new BooleanExpression(scan(), false);
          case NULL:
            return new NullExpression(scan());

          case THIS: {
            Expression e = new ThisExpression(scan());
            return (token == LPAREN) ? parseMethodExpression(e, idInit) : e;
          }
          case SUPER: {
            Expression e = new SuperExpression(scan());
            return (token == LPAREN) ? parseMethodExpression(e, idInit) : e;
          }

          case VOID:
          case BOOLEAN:
          case BYTE:
          case CHAR:
          case SHORT:
          case INT:
          case LONG:
          case FLOAT:
          case DOUBLE:
            return parseTypeExpression();

          case ADD: {
            long p = scan();
            switch (token) {
              case INTVAL: {
                int v = scanner.intValue;
                long q = scan();
                if (v < 0 && radix == 10) env.error(q, "overflow.int.dec");
                return new IntExpression(q, v);
              }
              case LONGVAL: {
                long v = scanner.longValue;
                long q = scan();
                if (v < 0 && radix == 10) env.error(q, "overflow.long.dec");
                return new LongExpression(q, v);
              }
              case FLOATVAL: {
                float v = scanner.floatValue;
                return new FloatExpression(scan(), v);
              }
              case DOUBLEVAL: {
                double v = scanner.doubleValue;
                return new DoubleExpression(scan(), v);
              }
            }
            return new PositiveExpression(p, parseTerm());
          }
          case SUB: {
            long p = scan();
            switch (token) {
              case INTVAL: {
                int v = -scanner.intValue;
                return new IntExpression(scan(), v);
              }
              case LONGVAL: {
                long v = -scanner.longValue;
                return new LongExpression(scan(), v);
              }
              case FLOATVAL: {
                float v = -scanner.floatValue;
                return new FloatExpression(scan(), v);
              }
              case DOUBLEVAL: {
                double v = -scanner.doubleValue;
                return new DoubleExpression(scan(), v);
              }
            }
            return new NegativeExpression(p, parseTerm());
          }
          case NOT:
            return new NotExpression(scan(), parseTerm());
          case BITNOT:
            return new BitNotExpression(scan(), parseTerm());
          case INC:
            return new PreIncExpression(scan(), parseTerm());
          case DEC:
            return new PreDecExpression(scan(), parseTerm());

          case LPAREN: {
            // bracketed-expr: (expr)
            long p = scan();
            Expression e = parseExpression();
            expect(RPAREN);

            if (e.getOp() == TYPE) {
                // cast-expr: (simple-type) expr
                return new CastExpression(p, e, parseTerm());
            }

            switch (token) {

                // We handle INC and DEC specially.
                // See the discussion in JLS section 15.14.1.
                // (Part of fix for 4044502.)

              case INC:
                  // We know this must be a postfix increment.
                  return new PostIncExpression(scan(), e);

              case DEC:
                  // We know this must be a postfix decrement.
                  return new PostDecExpression(scan(), e);

              case LPAREN:
              case CHARVAL:
              case INTVAL:
              case LONGVAL:
              case FLOATVAL:
              case DOUBLEVAL:
              case STRINGVAL:
              case IDENT:
              case TRUE:
              case FALSE:
              case NOT:
              case BITNOT:
              case THIS:
              case SUPER:
              case NULL:
              case NEW:
                // cast-expr: (expr) expr
                return new CastExpression(p, e, parseTerm());
            }
            return new ExprExpression(p, e);
          }

          case LBRACE: {
            // array initializer: {expr1, expr2, ... exprn}
            long p = scan();
            int i = argIndex;
            if (token != RBRACE) {
                addArgument(parseExpression());
                while (token == COMMA) {
                    scan();
                    if (token == RBRACE) {
                        break;
                    }
                    addArgument(parseExpression());
                }
            }
            expect(RBRACE);
            return new ArrayExpression(p, exprArgs(i));
          }

          case NEW: {
            long p = scan();
            int i = argIndex;

            if (token == LPAREN) {
                scan();
                Expression e = parseExpression();
                expect(RPAREN);
                env.error(p, "not.supported", "new(...)");
                return new NullExpression(p);
            }

            Expression e = parseTypeExpression();

            if (token == LSQBRACKET) {
                while (token == LSQBRACKET) {
                    scan();
                    addArgument((token != RSQBRACKET) ? parseExpression() : null);
                    expect(RSQBRACKET);
                }
                Expression[] dims = exprArgs(i);
                if (token == LBRACE) {
                    return new NewArrayExpression(p, e, dims, parseTerm());
                }
                return new NewArrayExpression(p, e, dims);
            } else {
                return parseNewInstanceExpression(p, null, e);
            }
          }
        }

        // System.err.println("NEAR: " + opNames[token]);
        env.error(scanner.prevPos, "missing.term");
        return new IntExpression(pos, 0);
    }

    /**
     * Parse an expression.
     */
    protected Expression parseExpression() throws SyntaxError, IOException {
        for (Expression e = parseTerm() ; e != null ; e = e.order()) {
            Expression more = parseBinaryExpression(e);
            if (more == null)
                return e;
            e = more;
        }
        // this return is bogus
        return null;
    }

    /**
     * Given a left-hand term, parse an operator and right-hand term.
     */
    protected Expression parseBinaryExpression(Expression e) throws SyntaxError, IOException {
        if (e != null) {
            switch (token) {
              case LSQBRACKET: {
                // index: expr1[expr2]
                long p = scan();
                Expression index = (token != RSQBRACKET) ? parseExpression() : null;
                expect(RSQBRACKET);
                e = new ArrayAccessExpression(p, e, index);
                break;
              }

              case INC:
                e = new PostIncExpression(scan(), e);
                break;
              case DEC:
                e = new PostDecExpression(scan(), e);
                break;
              case FIELD: {
                long p = scan();
                if (token == THIS) {
                    // class C { class N { ... C.this ... } }
                    // class C { class N { N(C c){ ... c.this() ... } } }
                    long q = scan();
                    if (token == LPAREN) {
                        e = new ThisExpression(q, e);
                        e = parseMethodExpression(e, idInit);
                    } else {
                        e = new FieldExpression(p, e, idThis);
                    }
                    break;
                }
                if (token == SUPER) {
                    // class D extends C.N { D(C.N n) { n.super(); } }
                    // Also, 'C.super', as in:
                    // class C extends CS { class N { ... C.super.foo ... } }
                    // class C extends CS { class N { ... C.super.foo() ... } }
                    long q = scan();
                    if (token == LPAREN) {
                        e = new SuperExpression(q, e);
                        e = parseMethodExpression(e, idInit);
                    } else {
                        // We must check elsewhere that this expression
                        // does not stand alone, but qualifies a member name.
                        e = new FieldExpression(p, e, idSuper);
                    }
                    break;
                }
                if (token == NEW) {
                    // new C().new N()
                    scan();
                    if (token != IDENT)
                        expect(IDENT);
                    e = parseNewInstanceExpression(p, e, parseTypeExpression());
                    break;
                }
                if (token == CLASS) {
                    // just class literals, really
                    // Class c = C.class;
                    scan();
                    e = new FieldExpression(p, e, idClass);
                    break;
                }
                Identifier id = scanner.idValue;
                expect(IDENT);
                if (token == LPAREN) {
                    e = parseMethodExpression(e, id);
                } else {
                    e = new FieldExpression(p, e, id);
                }
                break;
              }
              case INSTANCEOF:
                e = new InstanceOfExpression(scan(), e, parseTerm());
                break;
              case ADD:
                e = new AddExpression(scan(), e, parseTerm());
                break;
              case SUB:
                e = new SubtractExpression(scan(), e, parseTerm());
                break;
              case MUL:
                e = new MultiplyExpression(scan(), e, parseTerm());
                break;
              case DIV:
                e = new DivideExpression(scan(), e, parseTerm());
                break;
              case REM:
                e = new RemainderExpression(scan(), e, parseTerm());
                break;
              case LSHIFT:
                e = new ShiftLeftExpression(scan(), e, parseTerm());
                break;
              case RSHIFT:
                e = new ShiftRightExpression(scan(), e, parseTerm());
                break;
              case URSHIFT:
                e = new UnsignedShiftRightExpression(scan(), e, parseTerm());
                break;
              case LT:
                e = new LessExpression(scan(), e, parseTerm());
                break;
              case LE:
                e = new LessOrEqualExpression(scan(), e, parseTerm());
                break;
              case GT:
                e = new GreaterExpression(scan(), e, parseTerm());
                break;
              case GE:
                e = new GreaterOrEqualExpression(scan(), e, parseTerm());
                break;
              case EQ:
                e = new EqualExpression(scan(), e, parseTerm());
                break;
              case NE:
                e = new NotEqualExpression(scan(), e, parseTerm());
                break;
              case BITAND:
                e = new BitAndExpression(scan(), e, parseTerm());
                break;
              case BITXOR:
                e = new BitXorExpression(scan(), e, parseTerm());
                break;
              case BITOR:
                e = new BitOrExpression(scan(), e, parseTerm());
                break;
              case AND:
                e = new AndExpression(scan(), e, parseTerm());
                break;
              case OR:
                e = new OrExpression(scan(), e, parseTerm());
                break;
              case ASSIGN:
                e = new AssignExpression(scan(), e, parseTerm());
                break;
              case ASGMUL:
                e = new AssignMultiplyExpression(scan(), e, parseTerm());
                break;
              case ASGDIV:
                e = new AssignDivideExpression(scan(), e, parseTerm());
                break;
              case ASGREM:
                e = new AssignRemainderExpression(scan(), e, parseTerm());
                break;
              case ASGADD:
                e = new AssignAddExpression(scan(), e, parseTerm());
                break;
              case ASGSUB:
                e = new AssignSubtractExpression(scan(), e, parseTerm());
                break;
              case ASGLSHIFT:
                e = new AssignShiftLeftExpression(scan(), e, parseTerm());
                break;
              case ASGRSHIFT:
                e = new AssignShiftRightExpression(scan(), e, parseTerm());
                break;
              case ASGURSHIFT:
                e = new AssignUnsignedShiftRightExpression(scan(), e, parseTerm());
                break;
              case ASGBITAND:
                e = new AssignBitAndExpression(scan(), e, parseTerm());
                break;
              case ASGBITOR:
                e = new AssignBitOrExpression(scan(), e, parseTerm());
                break;
              case ASGBITXOR:
                e = new AssignBitXorExpression(scan(), e, parseTerm());
                break;
              case QUESTIONMARK: {
                long p = scan();
                Expression second = parseExpression();
                expect(COLON);
                Expression third = parseExpression();

                // The grammar in the JLS does not allow assignment
                // expressions as the third part of a ?: expression.
                // Even though javac has no trouble parsing this,
                // check for this case and signal an error.
                // (fix for bug 4092958)
                if (third instanceof AssignExpression
                    || third instanceof AssignOpExpression) {
                    env.error(third.getWhere(), "assign.in.conditionalexpr");
                }

                e = new ConditionalExpression(p, e, second, third);
                break;
              }

              default:
                return null; // mark end of binary expressions
            }
        }
        return e;           // return more binary expression stuff
    }

    /**
     * Recover after a syntax error in a statement. This involves
     * discarding tokens until EOF or a possible continuation is
     * encountered.
     */
    protected boolean recoverStatement() throws SyntaxError, IOException {
        while (true) {
            switch (token) {
              case EOF:
              case RBRACE:
              case LBRACE:
              case IF:
              case FOR:
              case WHILE:
              case DO:
              case TRY:
              case CATCH:
              case FINALLY:
              case BREAK:
              case CONTINUE:
              case RETURN:
                // begin of a statement, return
                return true;

              case VOID:
              case STATIC:
              case PUBLIC:
              case PRIVATE:
              case SYNCHRONIZED:
              case INTERFACE:
              case CLASS:
              case TRANSIENT:
                // begin of something outside a statement, panic some more
                expect(RBRACE);
                return false;

              case LPAREN:
                match(LPAREN, RPAREN);
                scan();
                break;

              case LSQBRACKET:
                match(LSQBRACKET, RSQBRACKET);
                scan();
                break;

              default:
                // don't know what to do, skip
                scan();
                break;
            }
        }
    }

    /**
     * Parse declaration, called after the type expression
     * has been parsed and the current token is IDENT.
     */
    protected Statement parseDeclaration(long p, int mod, Expression type) throws SyntaxError, IOException {
        int i = argIndex;
        if (token == IDENT) {
            addArgument(new VarDeclarationStatement(pos, parseExpression()));
            while (token == COMMA) {
                scan();
                addArgument(new VarDeclarationStatement(pos, parseExpression()));
            }
        }
        return new DeclarationStatement(p, mod, type, statArgs(i));
    }

    /**
     * Check if an expression is a legal toplevel expression.
     * Only method, inc, dec, and new expression are allowed.
     */
    protected void topLevelExpression(Expression e) {
        switch (e.getOp()) {
          case ASSIGN:
          case ASGMUL:
          case ASGDIV:
          case ASGREM:
          case ASGADD:
          case ASGSUB:
          case ASGLSHIFT:
          case ASGRSHIFT:
          case ASGURSHIFT:
          case ASGBITAND:
          case ASGBITOR:
          case ASGBITXOR:
          case PREINC:
          case PREDEC:
          case POSTINC:
          case POSTDEC:
          case METHOD:
          case NEWINSTANCE:
            return;
        }
        env.error(e.getWhere(), "invalid.expr");
    }

    /**
     * Parse a statement.
     */
    protected Statement parseStatement() throws SyntaxError, IOException {
        switch (token) {
          case SEMICOLON:
            return new CompoundStatement(scan(), new Statement[0]);

          case LBRACE:
              return parseBlockStatement();

          case IF: {
            // if-statement: if (expr) stat
            // if-statement: if (expr) stat else stat
            long p = scan();

            expect(LPAREN);
            Expression c = parseExpression();
            expect(RPAREN);
            Statement t = parseStatement();
            if (token == ELSE) {
                scan();
                return new IfStatement(p, c, t, parseStatement());
            } else {
                return new IfStatement(p, c, t, null);
            }
          }

          case ELSE: {
            // else-statement: else stat
            env.error(scan(), "else.without.if");
            return parseStatement();
          }

          case FOR: {
            // for-statement: for (decl-expr? ; expr? ; expr?) stat
            long p = scan();
            Statement init = null;
            Expression cond = null, inc = null;

            expect(LPAREN);
            if (token != SEMICOLON) {
                long p2 = pos;
                int mod = parseModifiers(M_FINAL);
                Expression e = parseExpression();

                if (token == IDENT) {
                    init = parseDeclaration(p2, mod, e);
                } else {
                    if (mod != 0) {
                        expect(IDENT); // should have been a declaration
                    }
                    topLevelExpression(e);
                    while (token == COMMA) {
                        long p3 = scan();
                        Expression e2 = parseExpression();
                        topLevelExpression(e2);
                        e = new CommaExpression(p3, e, e2);
                    }
                    init = new ExpressionStatement(p2, e);
                }
            }
            expect(SEMICOLON);
            if (token != SEMICOLON) {
                cond = parseExpression();
            }
            expect(SEMICOLON);
            if (token != RPAREN) {
                inc = parseExpression();
                topLevelExpression(inc);
                while (token == COMMA) {
                    long p2 = scan();
                    Expression e2 = parseExpression();
                    topLevelExpression(e2);
                    inc = new CommaExpression(p2, inc, e2);
                }
            }
            expect(RPAREN);
            return new ForStatement(p, init, cond, inc, parseStatement());
          }

          case WHILE: {
            // while-statement: while (expr) stat
            long p = scan();

            expect(LPAREN);
            Expression cond = parseExpression();
            expect(RPAREN);
            return new WhileStatement(p, cond, parseStatement());
          }

          case DO: {
            // do-statement: do stat while (expr)
            long p = scan();

            Statement body = parseStatement();
            expect(WHILE);
            expect(LPAREN);
            Expression cond = parseExpression();
            expect(RPAREN);
            expect(SEMICOLON);
            return new DoStatement(p, body, cond);
          }

          case BREAK: {
            // break-statement: break ;
            long p = scan();
            Identifier label = null;

            if (token == IDENT) {
                label = scanner.idValue;
                scan();
            }
            expect(SEMICOLON);
            return new BreakStatement(p, label);
          }

          case CONTINUE: {
            // continue-statement: continue ;
            long p = scan();
            Identifier label = null;

            if (token == IDENT) {
                label = scanner.idValue;
                scan();
            }
            expect(SEMICOLON);
            return new ContinueStatement(p, label);
          }

          case RETURN: {
            // return-statement: return ;
            // return-statement: return expr ;
            long p = scan();
            Expression e = null;

            if (token != SEMICOLON) {
                e = parseExpression();
            }
            expect(SEMICOLON);
            return new ReturnStatement(p, e);
          }

          case SWITCH: {
            // switch statement: switch ( expr ) stat
            long p = scan();
            int i = argIndex;

            expect(LPAREN);
            Expression e = parseExpression();
            expect(RPAREN);
            expect(LBRACE);

            while ((token != EOF) && (token != RBRACE)) {
                int j = argIndex;
                try {
                    switch (token) {
                      case CASE:
                        // case-statement: case expr:
                        addArgument(new CaseStatement(scan(), parseExpression()));
                        expect(COLON);
                        break;

                      case DEFAULT:
                        // default-statement: default:
                        addArgument(new CaseStatement(scan(), null));
                        expect(COLON);
                        break;

                      default:
                        addArgument(parseStatement());
                        break;
                    }
                } catch (SyntaxError ee) {
                    argIndex = j;
                    if (!recoverStatement()) {
                        throw ee;
                    }
                }
            }
            expect(RBRACE);
            return new SwitchStatement(p, e, statArgs(i));
          }

          case CASE: {
            // case-statement: case expr : stat
            env.error(pos, "case.without.switch");
            while (token == CASE) {
                scan();
                parseExpression();
                expect(COLON);
            }
            return parseStatement();
          }

          case DEFAULT: {
            // default-statement: default : stat
            env.error(pos, "default.without.switch");
            scan();
            expect(COLON);
            return parseStatement();
          }

          case TRY: {
            // try-statement: try stat catch (type-expr ident) stat finally stat
            long p = scan();
            Statement init = null;              // try-object specification
            int i = argIndex;
            boolean catches = false;

            if (false && token == LPAREN) {
                expect(LPAREN);
                long p2 = pos;
                int mod = parseModifiers(M_FINAL);
                Expression e = parseExpression();

                if (token == IDENT) {
                    init = parseDeclaration(p2, mod, e);
                    // leave check for try (T x, y) for semantic phase
                } else {
                    if (mod != 0) {
                        expect(IDENT); // should have been a declaration
                    }
                    init = new ExpressionStatement(p2, e);
                }
                expect(RPAREN);
            }

            Statement s = parseBlockStatement();

            if (init != null) {
                // s = new FinallyStatement(p, init, s, 0);
            }

            while (token == CATCH) {
                long pp = pos;
                expect(CATCH);
                expect(LPAREN);
                int mod = parseModifiers(M_FINAL);
                Expression t = parseExpression();
                IdentifierToken id = scanner.getIdToken();
                expect(IDENT);
                id.modifiers = mod;
                // We only catch Throwable's, so this is no longer required
                // while (token == LSQBRACKET) {
                //    t = new ArrayAccessExpression(scan(), t, null);
                //    expect(RSQBRACKET);
                // }
                expect(RPAREN);
                addArgument(new CatchStatement(pp, t, id, parseBlockStatement()));
                catches = true;
            }

            if (catches)
                s = new TryStatement(p, s, statArgs(i));

            if (token == FINALLY) {
                scan();
                return new FinallyStatement(p, s, parseBlockStatement());
            } else if (catches || init != null) {
                return s;
            } else {
                env.error(pos, "try.without.catch.finally");
                return new TryStatement(p, s, null);
            }
          }

          case CATCH: {
            // catch-statement: catch (expr ident) stat finally stat
            env.error(pos, "catch.without.try");

            Statement s;
            do {
                scan();
                expect(LPAREN);
                parseModifiers(M_FINAL);
                parseExpression();
                expect(IDENT);
                expect(RPAREN);
                s = parseBlockStatement();
            } while (token == CATCH);

            if (token == FINALLY) {
                scan();
                s = parseBlockStatement();
            }
            return s;
          }

          case FINALLY: {
            // finally-statement: finally stat
            env.error(pos, "finally.without.try");
            scan();
            return parseBlockStatement();
          }

          case THROW: {
            // throw-statement: throw expr;
            long p = scan();
            Expression e = parseExpression();
            expect(SEMICOLON);
            return new ThrowStatement(p, e);
          }

          case GOTO: {
            long p = scan();
            expect(IDENT);
            expect(SEMICOLON);
            env.error(p, "not.supported", "goto");
            return new CompoundStatement(p, new Statement[0]);
          }

          case SYNCHRONIZED: {
            // synchronized-statement: synchronized (expr) stat
            long p = scan();
            expect(LPAREN);
            Expression e = parseExpression();
            expect(RPAREN);
            return new SynchronizedStatement(p, e, parseBlockStatement());
          }

          case INTERFACE:
          case CLASS:
            // Inner class.
            return parseLocalClass(0);

          case CONST:
          case ABSTRACT:
          case FINAL:
          case STRICTFP: {
            // a declaration of some sort
            long p = pos;

            // A class which is local to a block is not a member, and so
            // cannot be public, private, protected, or static. It is in
            // effect private to the block, since it cannot be used outside
            // its scope.
            //
            // However, any class (if it has a name) can be declared final,
            // abstract, or strictfp.
            int mod = parseModifiers(M_FINAL | M_ABSTRACT
                                             | M_STRICTFP );

            switch (token) {
              case INTERFACE:
              case CLASS:
                return parseLocalClass(mod);

              case BOOLEAN:
              case BYTE:
              case CHAR:
              case SHORT:
              case INT:
              case LONG:
              case FLOAT:
              case DOUBLE:
              case IDENT: {
                if ((mod & (M_ABSTRACT | M_STRICTFP )) != 0) {
                    mod &= ~ (M_ABSTRACT | M_STRICTFP );
                    expect(CLASS);
                }
                Expression e = parseExpression();
                if (token != IDENT) {
                    expect(IDENT);
                }
                // declaration: final expr expr
                Statement s = parseDeclaration(p, mod, e);
                expect(SEMICOLON);
                return s;
              }

              default:
                env.error(pos, "type.expected");
                throw new SyntaxError();
            }
          }

          case VOID:
          case STATIC:
          case PUBLIC:
          case PRIVATE:
          case TRANSIENT:
            // This is the start of something outside a statement
            env.error(pos, "statement.expected");
            throw new SyntaxError();
        }

        long p = pos;
        Expression e = parseExpression();

        if (token == IDENT) {
            // declaration: expr expr
            Statement s = parseDeclaration(p, 0, e);
            expect(SEMICOLON);
            return s;
        }
        if (token == COLON) {
            // label: id: stat
            scan();
            Statement s = parseStatement();
            s.setLabel(env, e);
            return s;
        }

        // it was just an expression...
        topLevelExpression(e);
        expect(SEMICOLON);
        return new ExpressionStatement(p, e);
    }

    protected Statement parseBlockStatement() throws SyntaxError, IOException {
        // compound statement: { stat1 stat2 ... statn }
        if (token != LBRACE) {
            // We're expecting a block statement.  But we'll probably do the
            // least damage if we try to parse a normal statement instead.
            env.error(scanner.prevPos, "token.expected", opNames[LBRACE]);
            return parseStatement();
        }
        long p = scan();
        int i = argIndex;
        while ((token != EOF) && (token != RBRACE)) {
            int j = argIndex;
            try {
                addArgument(parseStatement());
            } catch (SyntaxError e) {
                argIndex = j;
                if (!recoverStatement()) {
                    throw e;
                }
            }
        }

        expect(RBRACE);
        return new CompoundStatement(p, statArgs(i));
    }


    /**
     * Parse an identifier. ie: a.b.c returns "a.b.c"
     * If star is true then "a.b.*" is allowed.
     * The return value encodes both the identifier and its location.
     */
    protected IdentifierToken parseName(boolean star) throws SyntaxError, IOException {
        IdentifierToken res = scanner.getIdToken();
        expect(IDENT);

        if (token != FIELD) {
            return res;
        }

        StringBuffer buf = new StringBuffer(res.id.toString());

        while (token == FIELD) {
            scan();
            if ((token == MUL) && star) {
                scan();
                buf.append(".*");
                break;
            }

            buf.append('.');
            if (token == IDENT) {
                buf.append(scanner.idValue);
            }
            expect(IDENT);
        }

        res.id = Identifier.lookup(buf.toString());
        return res;
    }
    /**
     * @deprecated
     * @see #parseName
     */
    @Deprecated
    protected Identifier parseIdentifier(boolean star) throws SyntaxError, IOException {
        return parseName(star).id;
    }

    /**
     * Parse a type expression, this results in a Type.
     * The parse includes trailing array brackets.
     */
    protected Type parseType() throws SyntaxError, IOException {
        Type t;

        switch (token) {
          case IDENT:
            t = Type.tClass(parseName(false).id);
            break;
          case VOID:
            scan();
            t = Type.tVoid;
            break;
          case BOOLEAN:
            scan();
            t = Type.tBoolean;
            break;
          case BYTE:
            scan();
            t = Type.tByte;
            break;
          case CHAR:
            scan();
            t = Type.tChar;
            break;
          case SHORT:
            scan();
            t = Type.tShort;
            break;
          case INT:
            scan();
            t = Type.tInt;
            break;
          case FLOAT:
            scan();
            t = Type.tFloat;
            break;
          case LONG:
            scan();
            t = Type.tLong;
            break;
          case DOUBLE:
            scan();
            t = Type.tDouble;
            break;
          default:
            env.error(pos, "type.expected");
            throw new SyntaxError();
        }
        return parseArrayBrackets(t);
    }

    /**
     * Parse the tail of a type expression, which might be array brackets.
     * Return the given type, as possibly modified by the suffix.
     */
    protected Type parseArrayBrackets(Type t) throws SyntaxError, IOException {

        // Parse []'s
        while (token == LSQBRACKET) {
            scan();
            if (token != RSQBRACKET) {
                env.error(pos, "array.dim.in.decl");
                parseExpression();
            }
            expect(RSQBRACKET);
            t = Type.tArray(t);
        }
        return t;
    }

    /*
     * Dealing with argument lists, I'm not using
     * Vector for efficiency.
     */

    private int aCount = 0;
    private Type aTypes[] = new Type[8];
    private IdentifierToken aNames[] = new IdentifierToken[aTypes.length];

    private void addArgument(int mod, Type t, IdentifierToken nm) {
        nm.modifiers = mod;
        if (aCount >= aTypes.length) {
            Type newATypes[] = new Type[aCount * 2];
            System.arraycopy(aTypes, 0, newATypes, 0, aCount);
            aTypes = newATypes;
            IdentifierToken newANames[] = new IdentifierToken[aCount * 2];
            System.arraycopy(aNames, 0, newANames, 0, aCount);
            aNames = newANames;
        }
        aTypes[aCount] = t;
        aNames[aCount++] = nm;
    }

    /**
     * Parse a possibly-empty sequence of modifier keywords.
     * Return the resulting bitmask.
     * Diagnose repeated modifiers, but make no other checks.
     * Only modifiers mentioned in the given bitmask are scanned;
     * an unmatched modifier must be handled by the caller.
     */
    protected int parseModifiers(int mask) throws IOException {
        int mod = 0;
        while (true) {
            if (token==CONST) {
                // const isn't in java, but handle a common C++ usage gently
                env.error(pos, "not.supported", "const");
                scan();
            }
            int nextmod = 0;
            switch (token) {
               case PRIVATE:            nextmod = M_PRIVATE;      break;
               case PUBLIC:             nextmod = M_PUBLIC;       break;
               case PROTECTED:          nextmod = M_PROTECTED;    break;
               case STATIC:             nextmod = M_STATIC;       break;
               case TRANSIENT:          nextmod = M_TRANSIENT;    break;
               case FINAL:              nextmod = M_FINAL;        break;
               case ABSTRACT:           nextmod = M_ABSTRACT;     break;
               case NATIVE:             nextmod = M_NATIVE;       break;
               case VOLATILE:           nextmod = M_VOLATILE;     break;
               case SYNCHRONIZED:       nextmod = M_SYNCHRONIZED; break;
               case STRICTFP:           nextmod = M_STRICTFP;     break;
            }
            if ((nextmod & mask) == 0) {
                break;
            }
            if ((nextmod & mod) != 0) {
                env.error(pos, "repeated.modifier");
            }
            mod |= nextmod;
            scan();
        }
        return mod;
    }

    private ClassDefinition curClass;

    /**
     * Parse a field.
     */
    protected void parseField() throws SyntaxError, IOException {

        // Empty fields are not allowed by the JLS but are accepted by
        // the compiler, and much code has come to rely on this.  It has
        // been decided that the language will be extended to legitimize them.
        if (token == SEMICOLON) {
            // empty field
            scan();
            return;
        }

        // Optional doc comment
        String doc = scanner.docComment;

        // The start of the field
        long p = pos;

        // Parse the modifiers
        int mod = parseModifiers(MM_FIELD | MM_METHOD);

        // Check for static initializer
        // ie: static { ... }
        // or an instance initializer (w/o the static).
        if ((mod == (mod & M_STATIC)) && (token == LBRACE)) {
            // static initializer
            actions.defineField(p, curClass, doc, mod,
                                Type.tMethod(Type.tVoid),
                                new IdentifierToken(idClassInit), null, null,
                                parseStatement());
            return;
        }

        // Check for inner class
        if (token == CLASS || token == INTERFACE) {
            parseNamedClass(mod, CLASS, doc);
            return;
        }

        // Parse the type
        p = pos;
        Type t = parseType();
        IdentifierToken id = null;

        // Check that the type is followed by an Identifier
        // (the name of the method or the first variable),
        // otherwise it is a constructor.
        switch (token) {
          case IDENT:
            id = scanner.getIdToken();
            p = scan();
            break;

          case LPAREN:
            // It is a constructor
            id = new IdentifierToken(idInit);
            if ((mod & M_STRICTFP) != 0)
                env.error(pos, "bad.constructor.modifier");
            break;

          default:
            expect(IDENT);
        }

        // If the next token is a left-bracket then we
        // are dealing with a method or constructor, otherwise it is
        // a list of variables
        if (token == LPAREN) {
            // It is a method or constructor declaration
            scan();
            aCount = 0;

            if (token != RPAREN) {
                // Parse argument type and identifier
                // (arguments (like locals) are allowed to be final)
                int am = parseModifiers(M_FINAL);
                Type at = parseType();
                IdentifierToken an = scanner.getIdToken();
                expect(IDENT);

                // Parse optional array specifier, ie: a[][]
                at = parseArrayBrackets(at);
                addArgument(am, at, an);

                // If the next token is a comma then there are
                // more arguments
                while (token == COMMA) {
                    // Parse argument type and identifier
                    scan();
                    am = parseModifiers(M_FINAL);
                    at = parseType();
                    an = scanner.getIdToken();
                    expect(IDENT);

                    // Parse optional array specifier, ie: a[][]
                    at = parseArrayBrackets(at);
                    addArgument(am, at, an);
                }
            }
            expect(RPAREN);

            // Parse optional array sepecifier, ie: foo()[][]
            t = parseArrayBrackets(t);

            // copy arguments
            Type atypes[] = new Type[aCount];
            System.arraycopy(aTypes, 0, atypes, 0, aCount);

            IdentifierToken anames[] = new IdentifierToken[aCount];
            System.arraycopy(aNames, 0, anames, 0, aCount);

            // Construct the type signature
            t = Type.tMethod(t, atypes);

            // Parse and ignore throws clause
            IdentifierToken exp[] = null;
            if (token == THROWS) {
                Vector v = new Vector();
                scan();
                v.addElement(parseName(false));
                while (token == COMMA) {
                    scan();
                    v.addElement(parseName(false));
                }

                exp = new IdentifierToken[v.size()];
                v.copyInto(exp);
            }

            // Check if it is a method definition or a method declaration
            // ie: foo() {...} or foo();
            switch (token) {
              case LBRACE:      // It's a method definition

                // Set the state of FP strictness for the body of the method
                int oldFPstate = FPstate;
                if ((mod & M_STRICTFP)!=0) {
                    FPstate = M_STRICTFP;
                } else {
                    mod |= FPstate & M_STRICTFP;
                }

                actions.defineField(p, curClass, doc, mod, t, id,
                                    anames, exp, parseStatement());

                FPstate = oldFPstate;

                break;

              case SEMICOLON:
                scan();
                actions.defineField(p, curClass, doc, mod, t, id,
                                    anames, exp, null);
                break;

              default:
                // really expected a statement body here
                if ((mod & (M_NATIVE | M_ABSTRACT)) == 0) {
                    expect(LBRACE);
                } else {
                    expect(SEMICOLON);
                }
            }
            return;
        }

        // It is a list of instance variables
        while (true) {
            p = pos;            // get the current position
            // parse the array brackets (if any)
            // ie: var[][][]
            Type vt = parseArrayBrackets(t);

            // Parse the optional initializer
            Node init = null;
            if (token == ASSIGN) {
                scan();
                init = parseExpression();
            }

            // Define the variable
            actions.defineField(p, curClass, doc, mod, vt, id,
                                null, null, init);

            // If the next token is a comma, then there is more
            if (token != COMMA) {
                expect(SEMICOLON);
                return;
            }
            scan();

            // The next token must be an identifier
            id = scanner.getIdToken();
            expect(IDENT);
        }
    }

    /**
     * Recover after a syntax error in a field. This involves
     * discarding tokens until an EOF or a possible legal
     * continuation is encountered.
     */
    protected void recoverField(ClassDefinition newClass) throws SyntaxError, IOException {
        while (true) {
            switch (token) {
              case EOF:
              case STATIC:
              case FINAL:
              case PUBLIC:
              case PRIVATE:
              case SYNCHRONIZED:
              case TRANSIENT:

              case VOID:
              case BOOLEAN:
              case BYTE:
              case CHAR:
              case SHORT:
              case INT:
              case FLOAT:
              case LONG:
              case DOUBLE:
                // possible begin of a field, continue
                return;

              case LBRACE:
                match(LBRACE, RBRACE);
                scan();
                break;

              case LPAREN:
                match(LPAREN, RPAREN);
                scan();
                break;

              case LSQBRACKET:
                match(LSQBRACKET, RSQBRACKET);
                scan();
                break;

              case RBRACE:
              case INTERFACE:
              case CLASS:
              case IMPORT:
              case PACKAGE:
                // begin of something outside a class, panic more
                actions.endClass(pos, newClass);
                throw new SyntaxError();

              default:
                // don't know what to do, skip
                scan();
                break;
            }
        }
    }

    /**
     * Parse a top-level class or interface declaration.
     */
    protected void parseClass() throws SyntaxError, IOException {
        String doc = scanner.docComment;

        // Parse the modifiers.
        int mod = parseModifiers(MM_CLASS | MM_MEMBER);

        parseNamedClass(mod, PACKAGE, doc);
    }

    // Current strict/default state of floating point.  This is
    // set and reset with a stack discipline around methods and named
    // classes.  Only M_STRICTFP may be set in this word.  try...
    // finally is not needed to protect setting and resetting because
    // there are no error messages based on FPstate.
    private int FPstate = 0;

    /**
     * Parse a block-local class or interface declaration.
     */
    protected Statement parseLocalClass(int mod) throws SyntaxError, IOException {
        long p = pos;
        ClassDefinition body = parseNamedClass(M_LOCAL | mod, STAT, null);
        Statement ds[] = {
            new VarDeclarationStatement(p, new LocalMember(body), null)
        };
        Expression type = new TypeExpression(p, body.getType());
        return new DeclarationStatement(p, 0, type, ds);
    }

    /**
     * Parse a named class or interface declaration,
     * starting at "class" or "interface".
     * @arg ctx Syntactic context of the class, one of {PACKAGE CLASS STAT EXPR}.
     */
    protected ClassDefinition parseNamedClass(int mod, int ctx, String doc) throws SyntaxError, IOException {
        // Parse class/interface
        switch (token) {
          case INTERFACE:
            scan();
            mod |= M_INTERFACE;
            break;

          case CLASS:
            scan();
            break;

          default:
            env.error(pos, "class.expected");
            break;
        }

        int oldFPstate = FPstate;
        if ((mod & M_STRICTFP)!=0) {
            FPstate = M_STRICTFP;
        } else {
            // The & (...) isn't really necessary here because we do maintain
            // the invariant that FPstate has no extra bits set.
            mod |= FPstate & M_STRICTFP;
        }

        // Parse the class name
        IdentifierToken nm = scanner.getIdToken();
        long p = pos;
        expect(IDENT);

        Vector ext = new Vector();
        Vector impl = new Vector();
        parseInheritance(ext, impl);

        ClassDefinition tmp = parseClassBody(nm, mod, ctx, doc, ext, impl, p);

        FPstate = oldFPstate;

        return tmp;
    }

    protected void parseInheritance(Vector ext, Vector impl) throws SyntaxError, IOException {
        // Parse extends clause
        if (token == EXTENDS) {
            scan();
            ext.addElement(parseName(false));
            while (token == COMMA) {
                scan();
                ext.addElement(parseName(false));
            }
        }

        // Parse implements clause
        if (token == IMPLEMENTS) {
            scan();
            impl.addElement(parseName(false));
            while (token == COMMA) {
                scan();
                impl.addElement(parseName(false));
            }
        }
    }

    /**
     * Parse the body of a class or interface declaration,
     * starting at the left brace.
     */
    protected ClassDefinition parseClassBody(IdentifierToken nm, int mod,
                                             int ctx, String doc,
                                             Vector ext, Vector impl, long p
                                             ) throws SyntaxError, IOException {
        // Decide which is the super class
        IdentifierToken sup = null;
        if ((mod & M_INTERFACE) != 0) {
            if (impl.size() > 0) {
                env.error(((IdentifierToken)impl.elementAt(0)).getWhere(),
                          "intf.impl.intf");
            }
            impl = ext;
        } else {
            if (ext.size() > 0) {
                if (ext.size() > 1) {
                    env.error(((IdentifierToken)ext.elementAt(1)).getWhere(),
                              "multiple.inherit");
                }
                sup = (IdentifierToken)ext.elementAt(0);
            }
        }

        ClassDefinition oldClass = curClass;

        // Begin a new class
        IdentifierToken implids[] = new IdentifierToken[impl.size()];
        impl.copyInto(implids);
        ClassDefinition newClass =
            actions.beginClass(p, doc, mod, nm, sup, implids);

        // Parse fields
        expect(LBRACE);
        while ((token != EOF) && (token != RBRACE)) {
            try {
                curClass = newClass;
                parseField();
            } catch (SyntaxError e) {
                recoverField(newClass);
            } finally {
                curClass = oldClass;
            }
        }
        expect(RBRACE);

        // End the class
        actions.endClass(scanner.prevPos, newClass);
        return newClass;
    }

    /**
     * Recover after a syntax error in the file.
     * This involves discarding tokens until an EOF
     * or a possible legal continuation is encountered.
     */
    protected void recoverFile() throws IOException {
        while (true) {
            switch (token) {
              case CLASS:
              case INTERFACE:
                // Start of a new source file statement, continue
                return;

              case LBRACE:
                match(LBRACE, RBRACE);
                scan();
                break;

              case LPAREN:
                match(LPAREN, RPAREN);
                scan();
                break;

              case LSQBRACKET:
                match(LSQBRACKET, RSQBRACKET);
                scan();
                break;

              case EOF:
                return;

              default:
                // Don't know what to do, skip
                scan();
                break;
            }
        }
    }

    /**
     * Parse an Java file.
     */
    public void parseFile() {
        try {
            try {
                if (token == PACKAGE) {
                    // Package statement
                    long p = scan();
                    IdentifierToken id = parseName(false);
                    expect(SEMICOLON);
                    actions.packageDeclaration(p, id);
                }
            } catch (SyntaxError e) {
                recoverFile();
            }
            while (token == IMPORT) {
                try{
                    // Import statement
                    long p = scan();
                    IdentifierToken id = parseName(true);
                    expect(SEMICOLON);
                    if (id.id.getName().equals(idStar)) {
                        id.id = id.id.getQualifier();
                        actions.importPackage(p, id);
                    } else {
                        actions.importClass(p, id);
                    }
                } catch (SyntaxError e) {
                    recoverFile();
                }
            }

            while (token != EOF) {
                try {
                    switch (token) {
                      case FINAL:
                      case PUBLIC:
                      case PRIVATE:
                      case ABSTRACT:
                      case CLASS:
                      case INTERFACE:
                      case STRICTFP:
                        // Start of a class
                        parseClass();
                        break;

                      case SEMICOLON:
                        // Bogus semicolon.
                        // According to the JLS (7.6,19.6), a TypeDeclaration
                        // may consist of a single semicolon, however, this
                        // usage is discouraged (JLS 7.6).  In contrast,
                        // a FieldDeclaration may not be empty, and is flagged
                        // as an error.  See parseField above.
                        scan();
                        break;

                      case EOF:
                        // The end
                        return;

                      default:
                        // Oops
                        env.error(pos, "toplevel.expected");
                        throw new SyntaxError();
                    }
                } catch (SyntaxError e) {
                    recoverFile();
                }
            }
        } catch (IOException e) {
            env.error(pos, "io.exception", env.getSource());
            return;
        }
    }

    /**
     * Usually <code>this.scanner == (Scanner)this</code>.
     * However, a delegate scanner can produce tokens for this parser,
     * in which case <code>(Scanner)this</code> is unused,
     * except for <code>this.token</code> and <code>this.pos</code>
     * instance variables which are filled from the real scanner
     * by <code>this.scan()</code> and the constructor.
     */
    protected Scanner scanner;

    // Design Note: We ought to disinherit Parser from Scanner.
    // We also should split out the interface ParserActions from
    // Parser, and make BatchParser implement ParserActions,
    // not extend Parser.  This would split scanning, parsing,
    // and class building into distinct responsibility areas.
    // (Perhaps tree building could be virtualized too.)

    public long scan() throws IOException {
        if (scanner != this && scanner != null) {
            long result = scanner.scan();
            ((Scanner)this).token = scanner.token;
            ((Scanner)this).pos = scanner.pos;
            return result;
        }
        return super.scan();
    }

    public void match(int open, int close) throws IOException {
        if (scanner != this) {
            scanner.match(open, close);
            ((Scanner)this).token = scanner.token;
            ((Scanner)this).pos = scanner.pos;
            return;
        }
        super.match(open, close);
    }
}
