Dienstag, 11. August 2015

Previsit a datastructure

Recently I had to write a small and relatively simple compiler and came across a problem. For the function prologue the stack pointer should be decreased by 4 * number of local variables. Compilers work with a datastructure so called "Abstract Syntax Tree". The important part is that it was realized with the Visitor design pattern. I was looking for a simple solution to know the number of local variables in the moment I want to decrease the stack pointer. I couldn't think of non-complex code and came across this elegant and simple solution:

Here we have the normal Visitor:
public interface ASTVisitor {

    public void visit(FunctionDefinitionExpression e);
    public void visit(DeclarationStatement s);
    // ...

}
All subtypes implement the accept method for the Visitor:
public class PrimaryExpression extends Expression {

    // ...
 
    @Override
    public void accept(ASTVisitor v) {
        v.visit(this);
    }

}
Here we have the implemention and the main logic:
public class ASTVisitorImpl implements ASTVisitor {

    @Override
    public void visit(FunctionDefinitionExpression e) {

        int n = 0;

        // here we will use our custom PreVisitor
        // and override our desired method
        funcDefinition.accept(new PreVisitor() {
         
            @Override
            public void visit(DeclarationStatement decl) {

                // add here your logic e.g.
                n++;
    
            }
         });

    }
}
That's our simple PreVisitor:
public class PreVisitor implements ASTVisitor {

    @Override
    public void visit(DeclarationStatement declarationStatement) {
    }

    @Override
    public void visit(BinaryExpression binaryExpression) {
        binaryExpression.elem1.accept(this);
        binaryExpression.elem2.accept(this);
    }

    // ...

}

So the solution was simply to create another subtype of the the same ASTVisitor interface and implement there all methods and just the logic to traverse the whole datastructure (Abstract Syntax Tree). At the moment you want to have a specific information without continuing at this point, you call the PreVisitor and override the desired method - et voilà you have an elegant solution!

Keine Kommentare:

Kommentar veröffentlichen