我在Irony中定义了一个简单的语法,并生成了一个不错的紧凑 AST。
现在我想弄清楚如何评估它。问题是,我找不到任何关于如何做到这一点的教程。
我只定义了 2 个 AST 节点:
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));
}
}
这将生成以下输出:
<html><head><title></title></head><body><h1></h1><p></p><p></p></body></html>3.14159265358979
而我想要的输出是:
<html>
<head>
<title>page title</title>
</head>
<body>
<h1>header</h1>
<p>paragraph 1</p>
<p>3.14159265358979</p>
</body>
</html>
我不认为我应该使用Context.Write()
. 样本显示将东西推入context.Data
并弹出它们......但我不太确定它是如何工作的。
我猜pi
最后会被添加,因为它会自动推送到context.Data
最后一个元素会弹出?我不太确定。
一些指针或指向教程的链接会很好。
另外,我应该如何处理不同的节点类型?每个“标签”可以有 4 种不同类型的内容:另一个标签、字符串文字、变量或数字。我应该if(node is StringLiteral) ....
在EvaluateNode
方法中写东西还是什么?
我找到了这个,但他们只是遍历 AST 而没有利用EvaluateNode
.
然后这个替换数据堆栈中的单个值......但并没有真正解释它是如何输出的或任何东西。
需要明确的是,我特别想知道如何重写EvaluateNode
方法Irony.Ast.AstNode
来做我想做的事。
好的,我已经追踪到这一行末尾的那个花絮:
if (EvaluationContext.HasLastResult)
EvaluationContext.Write(EvaluationContext.LastResult + Environment.NewLine);
它包含在默认评估例程中......也许它适用于计算器应用程序,但在我的应用程序中并不多。现在试图弄清楚如何绕过脚本解释器,但后来我不知道如何设置全局变量。