Irony: Tutorial on evaluating AST nodes?

4.4k views Asked by At

I've defined a simple grammar in Irony, and generated a nice compact AST.

Now I'm trying to figure out how to evaluate it. Problem is, I can't find any tutorials on how to do this.

I've defined just 2 AST nodes:

class TagListNode : AstNode
{
    public override void Init(ParsingContext context, ParseTreeNode treeNode)
    {
        base.Init(context, treeNode);
        AsString = "TagList";
        foreach (var node in treeNode.ChildNodes)
            AddChild(null, node);
    }

    public override void EvaluateNode(Irony.Interpreter.EvaluationContext context, AstMode mode)
    {
        foreach (var node in ChildNodes)
            node.EvaluateNode(context, AstMode.Read);
    }
}

class TagBlockNode : AstNode
{
    public AstNode Content;

    public override void Init(ParsingContext context,ParseTreeNode treeNode)
    {
        base.Init(context, treeNode);
        AsString = treeNode.ChildNodes[0].FindTokenAndGetText();
        Content = AddChild(null, treeNode.ChildNodes[1]);
    }

    public override void EvaluateNode(EvaluationContext context, AstMode mode)
    {
        context.Write(string.Format("<{0}>", AsString));
        Content.EvaluateNode(context, AstMode.Read);
        context.Write(string.Format("</{0}>", AsString));
    }
}

This will generate the following output:

 <html><head><title></title></head><body><h1></h1><p></p><p></p></body></html>3.14159265358979

Whereas the output I want is:

<html>
    <head>
        <title>page title</title>
    </head>
    <body>
        <h1>header</h1>
        <p>paragraph 1</p>
        <p>3.14159265358979</p>
    </body>
</html> 

I don't think I'm supposed to be using Context.Write(). The samples show pushing stuff onto context.Data and popping them off... but I'm not quite sure how that works.

I'm guessing pi gets tacked on at the end because it's automatically pushed onto context.Data and then one element is popped off at the end?? I'm not really sure.

Some pointers or a link to a tutorial would be nice.

Also, how am I supposed to handle the different node types? Each "Tag" can have 4 different types of content: another tag, a string literal, a variable, or a number. Should I be writing things like if(node is StringLiteral) .... in the EvaluateNode method or what?


I've found this one but they just loop over the AST and don't take advantage of EvaluateNode.

And then this one which replaces a single value in the data stack...but doesn't really explain how this gets outputted or anything.


To be clear, I specifically want to know how to override the EvaluateNode methods in Irony.Ast.AstNode to do what I want.


Okay, I've traced that tidbit at the end to this line:

    if (EvaluationContext.HasLastResult)
      EvaluationContext.Write(EvaluationContext.LastResult + Environment.NewLine);

Which is included in the default evaluation routine....perhaps it works well for a calculator app, but not so much in mine. Trying to figure out how to bypass the script interpreter now, but then I don't know how to set the globals.

1

There are 1 answers

2
Morvader On

The best way to iterate through an AST structure is to implement the visitor pattern.

Maybe this link helps you.