public void print(int l)
        {
            print(l, "Parenthesis");
            super.print(l + 1);
        }
    }

    public class AstLambdaX extends AstExpression
    {
        AstSchemaText m_schemaText;
        AstExpression m_expression;

        public AstLambdaX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public void print(int l)
        {
            print(l, "Lambda");
            m_schemaText.print(l + 1);
            m_expression.print(l + 1);
        }

        public void populateTypeTable(AstSymbolTable stable)
        {
            m_stable = stable;
            m_schemaText.populateTypeTable(m_stable);
            m_expression.populateTypeTable(m_stable);
        }

        public void populateSymbolTable()
        {
            m_schemaText.populateSymbolTable();
            m_expression.populateSymbolTable();
        }

        public AstType getType()
        {
            m_schemaText.checkType();
            List decls = m_schemaText.m_declaration.m_decls;
            AstType ttype = new AstType(AstType.TYPE_TUPLE);
            int i;
            for (i = 0; i < decls.size(); i++)
                {
                if (decls.get(i) instanceof AstBasicDeclaration1)
                    {
                    AstBasicDeclaration1 dec = (AstBasicDeclaration1) decls.get(i);
                    List names = dec.m_declarationNameList.m_declarationNameList;
                    int j;
                    for (j = 0; j < names.size(); j++)
                        {
                        AstDeclarationName name = (AstDeclarationName) names.get(j);
                        AstType nt = m_stable.getType(name.getName());
                        ttype.m_tupleTypes.add(nt);
                        }
                    }
                }
            AstType et = m_expression.getType();
            if (et.isUndefined())
                {
                return new AstType();
                }
            ttype.m_tupleTypes.add(et);
            AstType type = new AstType(AstType.TYPE_SET);
            type.m_setType = ttype;
            return type;
        }
    }

    public class AstMuX extends AstExpression
    {
        AstSchemaText m_schemaText;
        AstExpression m_expression;

        public AstMuX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }
    }

    public class AstLetX extends AstExpression
    {
        List m_letDefinitions = new ArrayList();
        AstExpression m_expression;

        public AstLetX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }
    }

    /*
     * This class is a merging of a variable (V), Schema Reference (S), and
     * class (C).
     * This is done because sometimes it is not possible to know at the time of
     * parsing whether something is either of the three.
     *
     * Word -> VSC
     * Word, Decoration -> VS
     * Word, ActualParameters -> VSC
     * Word, RenameList -> SC
     * Word, ActualParameters, RenameList -> SC
     * Word, Decoration, ActualParameters -> VS
     * Word, Decoration, RenameList -> S
     * Word, Decoration, ActualParameters, RenameList -> S
     */
    public class AstVSCX extends AstExpression
    {
        // The Word will be stored in the token in the base class.
        AstDecorations m_decorations;
        AstActualParameters m_actualParameters;
        AstRenameList m_renameList;

        public AstVSCX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public void print(int l)
        {
            print(l, "VSC");
            print(l + 1, m_token.m_value);
            if (m_decorations != null)
                {
                m_decorations.print(l + 1);
                }
            if (m_actualParameters != null)
                {
                m_actualParameters.print(l + 1);
                }
            if (m_renameList != null)
                {
                m_renameList.print(l + 1);
                }
        }

        public AstType getType()
        {
            AstType type = m_stable.getTypeDef(getName());
            if (type == null)
                {
                type = m_stable.getType(getName());
                if (type == null)
                    {
                    reportTypeError(getName() + " is undefined",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                if (type.isUndefined())
                    {
                    reportTypeError(getName() + " is undefined",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                }
            return type;
        }

        public String getName()
        {
            if (m_decorations == null)
                {
                return m_token.m_value;
                }
            return m_token.m_value + m_decorations.getName();
        }
    }

    public class AstSetExpressionX extends AstExpression
    {
        public AstSetExpressionX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }
    }

    public class AstSetExpressionX1 extends AstSetExpressionX
    {
        List m_expressions = new ArrayList();

        public AstSetExpressionX1(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public void print(int l)
        {
            int i;
            print(l, "SetExpression");
            for (i = 0; i < m_expressions.size(); i++)
                {
                ((AstExpression) m_expressions.get(i)).print(l + 1);
                }
        }

        public void populateTypeTable(AstSymbolTable stable)
        {
            m_stable = stable;
            int i;
            for (i = 0; i < m_expressions.size(); i++)
                {
                ((AstBase) m_expressions.get(i)).populateTypeTable(m_stable);
                }
        }

        public void populateSymbolTable()
        {
            int i;
            for (i = 0; i < m_expressions.size(); i++)
                {
                ((AstBase) m_expressions.get(i)).populateSymbolTable();
                }
        }

        public AstType getType()
        {
            AstType type;
            int i;
            boolean wasUndefined = false;
//ttp
/*
             * if (m_expressions.size() > 1)
             * {
             * AstType ttype = new AstType();
             * ttype.m_type = AstType.TYPE_TUPLE;
             * for (i=0; i<m_expressions.size(); i++)
             * {
             * type = ((AstBase)m_expressions.get(i)).getType();
             * ttype.m_tupleTypes.add(type);
             * if (type.isUndefined()) wasUndefined = true;
             * }
             * if (wasUndefined) return new AstType();
             * type = new AstType(AstType.TYPE_SET);
             * type.m_setType = ttype;
             * }
             * else if (m_expressions.size() == 1)
             */
            if (m_expressions.size() != 0)
                {
                type = new AstType(AstType.TYPE_SET);
                type.m_setType = ((AstBase) m_expressions.get(0)).getType();
                if (type.m_setType.isUndefined())
                    {
                    return new AstType();
                    }
                }
            else
                {
                type = new AstType(AstType.TYPE_SET);
                type.m_setType = new AstType(AstType.TYPE_EMPTY);
                if (type.m_setType.isUndefined())
                    {
                    return new AstType();
                    }
                }
            return type;
        }
    }

    public class AstSetExpressionX2 extends AstSetExpressionX
    {
        AstSchemaText m_schemaText;
        AstExpression m_expression;

        public AstSetExpressionX2(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public void print(int l)
        {
            print(l, "SetExpression");
            if (m_schemaText != null)
                {
                m_schemaText.print(l + 1);
                }
            m_expression.print(l + 1);
        }

        public void populateTypeTable(AstSymbolTable stable)
        {
            m_stable = new AstSymbolTable(stable);
            stable.addKid(m_stable);
            if (m_schemaText != null)
                {
                m_schemaText.populateTypeTable(m_stable);
                }
            if (m_expression != null)
                {
                m_expression.populateTypeTable(m_stable);
                }
        }

        public void populateSymbolTable()
        {
            if (m_schemaText != null)
                {
                m_schemaText.populateSymbolTable();
                }
            if (m_expression != null)
                {
                m_expression.populateSymbolTable();
                }
        }

        public AstType getType()
        {
            if (m_schemaText != null)
                {
                m_schemaText.checkType();
                }
            if (m_expression == null)
                {
                return m_schemaText.getType();
                }
            AstType type = new AstType(AstType.TYPE_SET);
            type.m_setType = m_expression.getType();
            if (type.m_setType.isUndefined())
                {
                return new AstType();
                }
            return type;
        }
    }

    public class AstSetExpressionX3 extends AstSetExpressionX
    {
        public AstSetExpressionX3(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public void print(int l)
        {
            print(l, "SetExpression - " + m_token.m_value);
        }

        public AstType getType()
        {
            AstType type = new AstType();
            if (m_token.m_id == TozeTokenizer.TOKEN_NAT)
                {
                return m_stable.getTypeDef(m_token.m_value);
                }
            else if (m_token.m_id == TozeTokenizer.TOKEN_NATONE)
                {
                return m_stable.getTypeDef(m_token.m_value);
                }
            else if (m_token.m_id == TozeTokenizer.TOKEN_INTEGER)
                {
                return m_stable.getTypeDef(m_token.m_value);
                }
            else if (m_token.m_id == TozeTokenizer.TOKEN_REAL)
                {
                return m_stable.getTypeDef(m_token.m_value);
                }
            else if (m_token.m_id == TozeTokenizer.TOKEN_BOOL)
                {
                return m_stable.getTypeDef(m_token.m_value);
                }
            return m_stable.getTypeDef(m_token.m_value);
        }
    }

    public class AstSequenceX extends AstExpression
    {
        List m_expressions = new ArrayList();

        public AstSequenceX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public void print(int l)
        {
            print(l, "Sequence");
        }

        public void populateTypeTable(AstSymbolTable stable)
        {
            m_stable = stable;
            int i;
            for (i = 0; i < m_expressions.size(); i++)
                {
                ((AstBase) m_expressions.get(i)).populateTypeTable(m_stable);
                }
        }

        public void populateSymbolTable()
        {
            int i;
            for (i = 0; i < m_expressions.size(); i++)
                {
                ((AstBase) m_expressions.get(i)).populateSymbolTable();
                }
        }

        public AstType getType()
        {
            int i;
            boolean wasUndefined = false;
            AstType type = new AstType(AstType.TYPE_SEQUENCE);
            if (m_expressions.size() == 0)
                {
                type.m_setType = new AstType(AstType.TYPE_EMPTY);
                return type;
                }

            AstType stype = ((AstBase) m_expressions.get(0)).getType();
            if (stype.isUndefined())
                {
                return new AstType();
                }

            for (i = 1; i < m_expressions.size(); i++)
                {
                AstType ttype = ((AstBase) m_expressions.get(i)).getType();
                if (ttype.isUndefined())
                    {
                    wasUndefined = true;
                    }
                else
                    {
                    if (!ttype.isEqual(stype))
                        {
                        reportTypeError("All expressions of a sequence must be of the same type",
                                        m_token,
                                        specObject,
                                        property
                        );
                        }
                    }
                }

            if (wasUndefined)
                {
                return new AstType();
                }

            AstType rtype = new AstType(AstType.TYPE_SEQUENCE);
            rtype.m_setType = new AstType(AstType.TYPE_TUPLE);
            rtype.m_setType.newTuple(new AstType(AstType.TYPE_NATURAL1),
                                     stype
            );
            rtype.m_setType.m_tupleIsSeq = true;
            return rtype;
        }
    }

    public class AstBuiltInFunctionX extends AstUnaryOpX
    {
        public AstBuiltInFunctionX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public AstType getType()
        {
            AstType type = m_expression.getType();

            if (type.isUndefined())
                {
                return new AstType();
                }

            if (m_token.m_id == TozeTokenizer.TOKEN_DOM)
                {
                if (type.getType() != AstType.TYPE_SET)
                    {
                    reportTypeError("The argument to the function 'dom' must be a set of tuples",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                if (type.getSetType().getType() != AstType.TYPE_TUPLE)
                    {
                    reportTypeError("The argument to the function 'dom' must be a set of tuples",
                                    m_token,
                                    specObject, property
                    );
                    return new AstType();
                    }
                if (type.getSetType().m_tupleTypes.size() != 2)
                    {
                    reportTypeError("The argument to the function 'dom' must be a tuple of size 2",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                AstType rtype = new AstType(AstType.TYPE_SET);
                rtype.m_setType = (AstType) type.getSetType().m_tupleTypes.get(0);
                return rtype;
                }

            if (m_token.m_id == TozeTokenizer.TOKEN_RAN)
                {
                if (type.getType() != AstType.TYPE_SET)
                    {
                    reportTypeError("The argument to the function 'ran' must be a set of tuples",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                if (type.getSetType().getType() != AstType.TYPE_TUPLE)
                    {
                    reportTypeError("The argument to the function 'ran' must be a set of tuples",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                if (type.getSetType().m_tupleTypes.size() != 2)
                    {
                    reportTypeError("The argument to the function 'ran' must be a tuple of size 2",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                AstType rtype = new AstType(AstType.TYPE_SET);
                rtype.m_setType = (AstType) type.getSetType().m_tupleTypes.get(1);
                return rtype;
                }

            if (m_token.m_id == TozeTokenizer.TOKEN_REV)
                {
                if (type.getType() != AstType.TYPE_SEQUENCE)
                    {
                    reportTypeError("The argument to the function 'rev' must be a sequence",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                return type;
                }

            if (m_token.m_id == TozeTokenizer.TOKEN_HEAD)
                {
                if (type.getType() != AstType.TYPE_SEQUENCE)
                    {
                    reportTypeError("The argument to the function 'head' must be a sequence",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                return (AstType) type.getSetType().m_tupleTypes.get(1);
//            return type.m_setType;
                }

            if (m_token.m_id == TozeTokenizer.TOKEN_LAST)
                {
                if (type.getType() != AstType.TYPE_SEQUENCE)
                    {
                    reportTypeError("The argument to the function 'last' must be a sequence",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                return (AstType) type.getSetType().m_tupleTypes.get(1);
//            return type.m_setType;
                }

            if (m_token.m_id == TozeTokenizer.TOKEN_TAIL)
                {
                if (type.getType() != AstType.TYPE_SEQUENCE)
                    {
                    reportTypeError("The argument to the function 'tail' must be a sequence",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                return type;
                }

            if (m_token.m_id == TozeTokenizer.TOKEN_FRONT)
                {
                if (type.getType() != AstType.TYPE_SEQUENCE)
                    {
                    reportTypeError("The argument to the function 'front' must be a sequence",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                return type;
                }

            if ((m_token.m_id == TozeTokenizer.TOKEN_FIRST)
                    || (m_token.m_id == TozeTokenizer.TOKEN_SECOND))
                {
                if ((type.getType() != AstType.TYPE_TUPLE)
                        || (type.m_tupleTypes.size() != 2))
                    {
                    reportTypeError("The argument to " + m_token.m_value + " must be a tuple of size 2",
                                    m_token,
                                    specObject,
                                    property
                    );
                    return new AstType();
                    }
                if (m_token.m_id == TozeTokenizer.TOKEN_FIRST)
                    {
                    return (AstType) type.m_tupleTypes.get(0);
                    }
                return (AstType) type.m_tupleTypes.get(1);
                }

            if (m_token.m_id == TozeTokenizer.TOKEN_HASH)
                {
                if (!type.isSet() && !type.isSequence())
                    {
                    reportTypeError("Argument to '#' must be either a set or a sequence",
                                    m_token,
                                    specObject,
                                    property
                    );
                    }
                return new AstType(AstType.TYPE_NATURAL);
                }

            return new AstType();
        }
    }

    public class AstFunctionX extends AstExpression
    {
        AstExpression m_fexpression;
        AstExpression m_pexpression;

        public AstFunctionX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public void populateTypeTable(AstSymbolTable stable)
        {
            m_stable = stable;
            m_fexpression.populateTypeTable(m_stable);
            m_pexpression.populateTypeTable(m_stable);
        }

        public void populateSymbolTable()
        {
            m_fexpression.populateSymbolTable();
            m_pexpression.populateSymbolTable();
        }

        public AstType getType()
        {
            AstType ftype = m_fexpression.getType();
            AstType ptype = m_pexpression.getType();

            if ((ftype.isUndefined())
                    || (ptype.isUndefined()))
                {
                return new AstType();
                }

            /*
             * Check the special case where it looks like an expression function
             * but it is really where a single element of a sequence is being
             * referenced.
             */

            if (ftype.getType() == AstType.TYPE_SEQUENCE)
                {
                if (!ptype.isANumber())
                    {
                    reportTypeError("Subscript to a sequence must be a number",
                                    m_token,
                                    specObject,
                                    property
                    );
                    }
                return (AstType) ftype.getSetType().m_tupleTypes.get(1);
                }

            if ((ftype.getType() != AstType.TYPE_SET)
                    && (ftype.getType() != AstType.TYPE_SEQUENCE))
                {
                reportTypeError("Expression used as a function must evaluate to a set of a tuple",
                                m_token,
                                specObject,
                                property
                );
                return new AstType();
                }
            if (ftype.getSetType().getType() != AstType.TYPE_TUPLE)
                {
                reportTypeError("Expression used as a function must evaluate to a tuple",
                                m_token,
                                specObject,
                                property
                );
                return new AstType();
                }
            if (ftype.getSetType().m_tupleTypes.size() < 2)
                {
                reportTypeError("The tuple must be a binary relation",
                                m_token,
                                specObject,
                                property
                );
                return new AstType();
                }

            //if (ptype.getType() == AstType.TYPE_TUPLE)
            if (ptype.isTuple())
                {
                if ((ptype.m_tupleTypes.size() + 1) != ftype.m_setType.m_tupleTypes.size())
                    {
                    reportTypeError("Number of parameters for the function do not match definition.",
                                    m_token,
                                    specObject,
                                    property
                    );
                    }
                int i;
                for (i = 0; i < ptype.m_tupleTypes.size(); i++)
                    {
                    AstType t1 = (AstType) ptype.m_tupleTypes.get(i);
                    AstType t2 = (AstType) ftype.m_setType.m_tupleTypes.get(i);
                    if (!t1.isCompatible(t2))
                        {
                        reportTypeError("Parameter " + (i + 1) + " does not match definition.",
                                        m_token,
                                        specObject,
                                        property
                        );
                        }
                    }
                }
            else
                {
                if (!ptype.isEqual((AstType) ftype.getSetType().m_tupleTypes.get(0)))
                    {
                    reportTypeError("Parameter types do not match function parameters",
                                    m_token,
                                    specObject,
                                    property
                    );
                    }
                }

            List vtmp = ftype.getSetType().m_tupleTypes;
            return (AstType) vtmp.get(vtmp.size() - 1);
        }
    }

    public class AstPredicateX extends AstExpression
    {
        AstPredicate m_predicate;

        public AstPredicateX(SpecObject specObject, String property)
        {
            super(specObject, property);
        }

        public void populateTypeTable(AstSymbolTable stable)
        {
            m_stable = stable;
            m_predicate.populateTypeTable(stable);
        }

        public void populateSymbolTable()
        {
            m_predicate.populateSymbolTable();
        }

        public AstType getType()
        {
            boolean bad = false;
            return new AstType(AstType.TYPE_BOOL);
        }
    }

    /*
     * Infix, Postfix, Prefix
     */
    public class AstPrefixGenericName extends AstBase
    {
        AstDecorations m_decoration;

        public void print(int l)
        {
            print(l, "PrefixGenericName = " + m_token.m_value);
            if (m_decoration != null)
                {
                m_decoration.print(l + 1);
                }
        }
    }

    public class AstInfixGenericName extends AstBase
    {
        AstDecorations m_decoration;

        public void print(int l)
        {
            print(l, "InfixGenericName = " + getName());
            if (m_decoration != null)
                {
                m_decoration.print(l + 1);
                }
        }

        public String getName()
        {
            return m_token.m_value;
        }
    }

    public class AstInfixFunctionName extends AstBase
    {
        AstDecorations m_decoration;

        public void print(int l)
        {
            print(l, m_token.m_value);
            if (m_decoration != null)
                {
                m_decoration.print(l + 1);
                }
        }
    }

    public class AstInfixRelationName extends AstBase
    {
        AstDecorations m_decoration;

        public void print(int l)
        {
            print(l, "InfixRelationName = " + m_token.m_value);
            if (m_decoration != null)
                {
                m_decoration.print(l + 1);
                }
        }
    }

    public class AstPrefixRelationName extends AstBase
    {
        public void print(int l)
        {
            print(l, "PrefixRelationName = " + getName());
        }

        public String getName()
        {
            return m_token.m_value;
        }
    }

    public class AstPostfixFunctionName extends AstBase
    {
        AstDecorations m_decoration;

        public void print(int l)
        {
            print(l, "PrefixFunctionName = " + m_token.m_value);
            m_decoration.print(l + 1);
        }