Irony: Tutorial on evaluating AST nodes?
Asked Answered
S

1

7

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.

Subtlety answered 14/2, 2011 at 8:6 Comment(0)
U
0

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

Maybe this link helps you.

Unconditioned answered 14/2, 2011 at 8:30 Comment(2)
Sorry, neither of those links are very helpful... pretty sure Irony already employs the visitor pattern, and mgrammar != irony.Subtlety
@Mark, if you dont want to use if-else at the TagBlockNode.EvaluateNode, i think that your grammar should create a new AstNode from the value of the tag and override the method or maybe iterate trough the TagBlockNode child calling ToString() ?¿?.Unconditioned

© 2022 - 2024 — McMap. All rights reserved.