2130 lines · 68.8 KB · Java
RawDownload
/* * 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 */ publicclass 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);

Lines 1–500 of 2130.