view tools/AstPrinter.d @ 176:dc9bf56b7ace

Can now use & as a unary operator and take an AddressOf
author Anders Johnsen <skabet@gmail.com>
date Thu, 24 Jul 2008 23:03:18 +0200
parents 01c2c49775ef
children 4e1a7265d620
line wrap: on
line source

module tools.AstPrinter;

import tango.io.Stdout;

import ast.Module,
       ast.Decl,
       ast.Stmt,
       ast.Exp;

import basic.SourceManager,
       basic.Attribute;

class AstPrinter
{
    const char[] tabType = "    "; // 4 spaces

    this(SourceManager sm)
    {

        this.sm = sm;
    }

    void print(Module m)
    {
        printBeginLine("module ");
        print(m.moduleName);
        printEndLine(";");
        printEndLine();
        foreach(decl ; m.decls)
        {
            printDecl(decl);
        }
        printEndLine();
    }

    void printDecl(Decl decl, bool printAtt = true)
    {
        switch(decl.declType)
        {
            case DeclType.FuncDecl:
                auto funcDecl = cast(FuncDecl)decl;
                printBeginLine();
                if (printAtt) printAttribute(decl.att);
                if (funcDecl.identifier.get != "this")
                {
                    printIdentifier(funcDecl.returnType);
                    space;
                }
                printIdentifier(funcDecl.identifier);
                printFuncArgs(funcDecl);
                printOpenBrace();
                foreach(stmt ; funcDecl.statements)
                    printStatement(stmt);
                printCloseBrace();
                break;

            case DeclType.VarDecl:
                auto varDecl = cast(VarDecl)decl;
                printBeginLine();
                if(printAtt) printAttribute(decl.att);
                printExp(varDecl.varType);
                space;
                printExp(varDecl.identifier);
                if(varDecl.init)
                {
                    print(" = ");
                    printExp(varDecl.init);
                }
                printEndLine(";");
                break;

            case DeclType.StructDecl:
                auto structDecl = cast(StructDecl)decl;
                if(printAtt) printAttribute(decl.att);
                printBeginLine("struct ");
                printIdentifier(structDecl.identifier);
                printEndLine;
                printOpenBrace;
                foreach( var ; structDecl.decls)
                    printDecl(var);
                printCloseBrace;
                break;

            case DeclType.ClassDecl:
                auto classDecl = cast(ClassDecl)decl;
                if(printAtt) printAttribute(decl.att);
                printBeginLine("class ");
                printIdentifier(classDecl.identifier);
                foreach(i, iden ; classDecl.baseClasses )
                {
                    print(i ? " : " : ", ");
                    printIdentifier(iden);
                }
                printEndLine;
                printOpenBrace;
                foreach( var ; classDecl.decls)
                    printDecl(var);
                printCloseBrace;
                break;

            case DeclType.InterfaceDecl:
                auto interfaceDecl = cast(InterfaceDecl)decl;
                if(printAtt) printAttribute(decl.att);
                printBeginLine("interface ");
                printIdentifier(interfaceDecl.identifier);
                foreach(i, iden ; interfaceDecl.baseClasses )
                {
                    print(i ? " : " : ", ");
                    printIdentifier(iden);
                }
                printEndLine;
                printOpenBrace;
                foreach( var ; interfaceDecl.decls)
                    printDecl(var);
                printCloseBrace;
                break;

            case DeclType.ImportDecl:
                auto i = cast(ImportDecl)decl;
                if(printAtt) printAttribute(decl.att);
                printBeginLine("import ");
                printEndLine(i.get);
                break;
        }
//        printEndLine();
    }

    void printStatement(Stmt stmt)
    {
        switch(stmt.stmtType)
        {
            case StmtType.Return:
                auto ret = cast(ReturnStmt)stmt;
                printBeginLine("return");
                if(ret.exp)
                {
                    space;
                    printExp(ret.exp);
                }
                printEndLine(";");
                break;
            case StmtType.Decl:
                auto declStmt = cast(DeclStmt)stmt;
                printDecl(declStmt.decl, false);
                break;
            case StmtType.Exp:
                auto expStmt = cast(ExpStmt)stmt;
                printBeginLine();
                printExp(expStmt.exp);
                printEndLine(";");
                break;

        }
    }

    void printExp(Exp exp)
    {
        switch(exp.expType)
        {
            case ExpType.Binary:
                auto binaryExp = cast(BinaryExp)exp;
                print("(");
                printExp(binaryExp.left);
                print(" " ~ binaryExp.getOp[binaryExp.op] ~ " ");
                printExp(binaryExp.right);
                print(")");
                break;
            case ExpType.IntegerLit:
                auto integetLit = cast(IntegerLit)exp;
                print(integetLit.get);
                break;
            case ExpType.Negate:
                auto negateExp = cast(NegateExp)exp;
                print("-");
                printExp(negateExp.exp);
                break;
            case ExpType.Deref:
                auto derefExp = cast(DerefExp)exp;
                print("*");
                printExp(derefExp.exp);
                break;
            case ExpType.AssignExp:
                auto assignExp = cast(AssignExp)exp;
                printExp(assignExp.identifier);
                print(" ");
                print(assignExp.getOp[assignExp.op]);
                print(" ");
                printExp(assignExp.exp);
                break;
            case ExpType.MemberReference:
                auto mrExp = cast(MemberReference)exp;
                printExp(mrExp.target);
                print(".");
                printIdentifier(mrExp.child);
                break;
            case ExpType.Identifier:
                auto iden = cast(Identifier)exp;
                printIdentifier(iden);
                break;
            case ExpType.IdentifierTypeExp:
                auto iden = cast(Identifier)exp;
                printIdentifier(iden);
                break;
            case ExpType.PointerTypeExp:
                auto iden = cast(PointerTypeExp)exp;
                printExp(iden.pointerOf);
                print("*");
                break;
            case ExpType.CallExp:
                auto callExp = cast(CallExp)exp;
                printExp(callExp.exp);
                print("(");
                foreach(i, e; callExp.args)
                {
                    printExp(e);
                    if(i+1 < callExp.args.length)
                        print(", ");
                }
                print(")");
                break;
            case ExpType.CastExp:
                auto castExp = cast(CastExp)exp;
                print("cast");
                print("(");
                printExp(castExp.castType);
                print(")");
                printExp(castExp.exp);
                break;
            case ExpType.NewExp:
                auto newExp = cast(NewExp)exp;
                print("new ");
                if(newExp.a_args.length)
                {
                    foreach( i, a ; newExp.a_args )
                    {
                        print(i ? ", " : "(");
                        printExp(a);
                    }
                    print(")");
                }
                printExp(newExp.newType);
                print("(");
                foreach( i, c ; newExp.c_args )
                {
                    print(i ? ", " : "");
                    printExp(c);
                }
                print(")");
                break;
        }
        
    }

    void printFuncArgs(FuncDecl decl)
    {
        print("(");
     
        foreach(i, d; decl.funcArgs)
        {
            printIdentifier(d.varType);
            if(i == 0 && decl.sret)
                print("*");
            space;
            printIdentifier(d.identifier);
            if(i+1 < decl.funcArgs.length)
                print(",");
        }

        printEndLine(")");
    }

    void printIdentifier(Identifier identifier)
    {
        print(identifier.get);
    }

    void printOpenBrace()
    {
        printEndLine(tabIndex~"{");
        tabIndex ~= tabType;
    }

    void printCloseBrace()
    {
        tabIndex = tabIndex[0 .. $-tabType.length];
        printEndLine(tabIndex~"}");
    }

    void printAttribute(Attribute a)
    {
        switch(a.getExtern)
        {
            case Extern.C:
                print("extern(C) ");
                break;
            case Extern.CPlusPlus:
                print("extern(C++) ");
                break;
            case Extern.D:
                break;
        }
        switch(a.getProtection)
        {
            case Protection.Public:
                print("public ");
                break;
            case Protection.Private:
                print("private ");
                break;
            case Protection.Package:
                print("package ");
                break;
            case Protection.Protected:
                print("protected ");
                break;
            case Protection.Export:
                print("export ");
                break;
        }
        if ( a.getStatic )
            print("static ");
        if ( a.getFinal )
            print("final ");
        if ( a.getConst )
            print("const ");
        if ( a.getAbstract )
            print("abstract ");
        if ( a.getOverride )
            print("override ");
        if ( a.getDeprecated )
            print("deprecated ");
        if ( a.getAuto )
            print("auto ");
    }

    void printBeginLine(char[] line = "")
    {
        Stdout(tabIndex~line);
    }

    void printEndLine(char[] line = "")
    {
        Stdout(line).newline;
    }

    void print(char[] line)
    {
        Stdout(line);
    }

    void space()
    {
        print(" ");
    }
private:
    SourceManager sm;
    char[] tabIndex;
}