私はIronyで単純な文法を定義し、素晴らしいコンパクトな AST を生成しました。
現在、評価をどうするか検討中です。問題は、これを行う方法に関するチュートリアルが見つからないことです。
定義した AST ノードは 2 つだけです。
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
自動的にプッシュされ、最後に1つの要素がポップオフされるため、最後に追加されると思いますcontext.Data
か?? よくわかりません。
いくつかのポインタまたはチュートリアルへのリンクがあればいいでしょう。
また、さまざまなノード タイプをどのように処理すればよいですか? 各「タグ」には、別のタグ、文字列リテラル、変数、数値の 4 種類のコンテンツを含めることができます。if(node is StringLiteral) ....
メソッドのようなものを書く必要がありますEvaluateNode
か?
私はこれを見つけましたが、AST をループするだけで、EvaluateNode
.
そして、これはデータ スタック内の単一の値を置き換えるものです...しかし、これがどのように出力されるかなどは実際には説明されていません。
明確にするために、EvaluateNode
メソッドをオーバーライドして自分のIrony.Ast.AstNode
やりたいことを実行する方法を知りたいと思っています。
わかりました、私はこの行の最後にその一口をたどりました:
if (EvaluationContext.HasLastResult)
EvaluationContext.Write(EvaluationContext.LastResult + Environment.NewLine);
これはデフォルトの評価ルーチンに含まれています....おそらく電卓アプリではうまく機能しますが、私のものではあまり機能しません。現在、スクリプト インタープリターをバイパスする方法を見つけようとしていますが、グローバルを設定する方法がわかりません。