/* This visitor/visit class redefines the visit/visit methods for each AST 
   node (e.g. inPlusExp, etc) so that the AST is visited in a 
   left-to-right depth-first fashion.
   This class also provides in and out method hooks (e.g. inPlusExp, outPlusExp,
   etc.) so that concrete visitors/switches that extend this class 
   only need to implement in and out methods and do not need to worry about
   traversing the AST.
*/

package ast.visitor;
import ast.node.*;
import java.util.*;

public class DepthFirstVisitor extends Visitor
{
    public void defaultIn(Node node)
    {
        // Do nothing
    }

    public void defaultOut(Node node)
    {
        // Do nothing
    }


    public void inProgram(Program node)
    {
        defaultIn(node);
    }

    public void outProgram(Program node)
    {
        defaultOut(node);
    }

    @Override
    public void visitProgram(Program node)
    {
        inProgram(node);
        if(node.getStmts() != null)
        {
            node.getStmts().accept(this);
        }
        outProgram(node);
    }


    public void inStatementList(StatementList node)
    {
        defaultIn(node);
    }

    public void outStatementList(StatementList node)
    {
        defaultOut(node);
    }

    @Override
    public void visitStatementList(StatementList node)
    {
        inStatementList(node);
        {
            List<IStatement> copy = new ArrayList<IStatement>(node.getStatements());
            for(IStatement e : copy)
            {
                e.accept(this);
            }
        }
        outStatementList(node);
    }


    public void inPrintStatement(PrintStatement node)
    {
        defaultIn(node);
    }

    public void outPrintStatement(PrintStatement node)
    {
        defaultOut(node);
    }

    @Override
    public void visitPrintStatement(PrintStatement node)
    {
        inPrintStatement(node);
        if(node.getExp() != null)
        {
            node.getExp().accept(this);
        }
        outPrintStatement(node);
    }


    public void inIntegerExp(IntegerExp node)
    {
        defaultIn(node);
    }

    public void outIntegerExp(IntegerExp node)
    {
        defaultOut(node);
    }

    @Override
    public void visitIntegerExp(IntegerExp node)
    {
        inIntegerExp(node);
        outIntegerExp(node);
    }

    public void inMinusExp(MinusExp node)
    {
        defaultIn(node);
    }

    public void outMinusExp(MinusExp node)
    {
        defaultOut(node);
    }

    @Override
    public void visitMinusExp(MinusExp node)
    {
        inMinusExp(node);
        if(node.getLExp() != null)
        {
            node.getLExp().accept(this);
        }
        if(node.getRExp() != null)
        {
            node.getRExp().accept(this);
        }
        outMinusExp(node);
    }

    public void inMulExp(MulExp node)
    {
        defaultIn(node);
    }

    public void outMulExp(MulExp node)
    {
        defaultOut(node);
    }

    @Override
    public void visitMulExp(MulExp node)
    {
        inMulExp(node);
        if(node.getLExp() != null)
        {
            node.getLExp().accept(this);
        }
        if(node.getRExp() != null)
        {
            node.getRExp().accept(this);
        }
        outMulExp(node);
    }

    public void inPlusExp(PlusExp node)
    {
        defaultIn(node);
    }

    public void outPlusExp(PlusExp node)
    {
        defaultOut(node);
    }

    @Override
    public void visitPlusExp(PlusExp node)
    {
        inPlusExp(node);
        if(node.getLExp() != null)
        {
            node.getLExp().accept(this);
        }
        if(node.getRExp() != null)
        {
            node.getRExp().accept(this);
        }
        outPlusExp(node);
    }
}
