c# - 如何使用访客解析 ANTRL 语法树以提供自定义对象
问题描述
我目前面临这个问题:我正在使用 ANTLR 使用 ANTLR 提供的语法解析 terraform 文件,并希望为语法树的每个分支创建自定义对象。例如 :
我想采用 subTree 提供者并制作一个包含以下属性的对象 TerraformProvider :
- 提供者名称:字符串
- 例如包含值的字典 (region -> us-east-1 )
对于这样的目的,我创建了一个 TerraformVisitor 类:
using Antlr4.Runtime.Misc;
using ANTLRch1.tmptest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ANTLRch1.terraformObjects;
using Antlr4.Runtime.Tree;
namespace ANTLRch1
{
public class TerraformVisitor: terraformBaseVisitor<string>
{
public List<TerraformProvider> Providers = new List<TerraformProvider>();
public override string VisitChildren([NotNull] IRuleNode node)
{
props.Add(node.GetText(), node.GetText());
return base.VisitChildren(node);
}
public override string VisitProvider([NotNull] terraformParser.ProviderContext context)
{
string id = context.GetText();
string value = context.PROVIDER().GetText();
props.Add(id, value);
var x = base.VisitChildren(context);
Console.WriteLine(props);
return base.VisitProvider(context);
}
public override string VisitResource([NotNull] terraformParser.ResourceContext context)
{
string id = context.GetText();
return base.VisitResource(context);
}
public override string VisitVariable([NotNull] terraformParser.VariableContext context)
{
string id = context.GetText();
string value = context.VARIABLE().GetText();
return base.VisitVariable(context);
}
public override string VisitFile_([NotNull] terraformParser.File_Context context)
{
return base.VisitFile_(context);
}
public override string VisitBlockbody([NotNull] terraformParser.BlockbodyContext context)
{
string id = context.GetText();
return base.VisitBlockbody(context);
}
public override string VisitArgument([NotNull] terraformParser.ArgumentContext context)
{
var c = context.GetType();
string id = context.GetText();
return base.VisitArgument(context);
}
public override string VisitIdentifier([NotNull] terraformParser.IdentifierContext context)
{
string id = context.GetText();
return base.VisitIdentifier(context);
}
public override string VisitVal([NotNull] terraformParser.ValContext context)
{
string id = context.GetText();
return base.VisitVal(context);
}
public override string VisitResourcetype([NotNull] terraformParser.ResourcetypeContext context)
{
string id = context.GetText();
return base.VisitResourcetype(context);
}
}
}
但我不确定如何处理对象的创建,因为例如变量与提供者等具有共同的元素。
非常感谢您的帮助 谢谢
解决方案
您可以跟踪当前正在创建的对象类型,但随后您需要检查类型并有条件地处理每个节点。
一种想法是使用多个访问者。您不必为所有树处理使用同一个访问者。
对于您的示例,也许您创建了一个TerraformVisitor
处理高级构造的 a,然后您可以(使用您的示例) aProviderVisitor
处理 Provider 节点的子节点,以及 aVariableVisitor
处理 Variable 节点的子节点。
这种方法将保持混乱,并允许您处理不同访问者的不同上下文。
注意:这适用于访问者,因为您可以控制访问哪些孩子以及使用哪些访问者访问他们。对于Listeners,整个树都会和Listener一起走(你可以用Listener来走子树,但它会走整个子树)
推荐阅读
- python - 如何在linux中安装csv格式?
- c# - 如何在我的代码中正确实现 Polly 以避免冻结
- android - 没有 Xamarin debug.keystore
- python - 在python中将UTC时间转换为本地时区
- android - 在 Android (Ionic) 上运行时的 net::ERR_CLEARTEXT_NOT_PERMITTED
- sonarqube - 有什么方法可以使用声纳忽略 XML 中的行吗?
- python-3.x - Rasa Form Action - 插槽被相同的数据填充两次
- sql - Grid Gain web 控制台找不到 JDBC 驱动程序。?
- android - 必须是以下之一:RecyclerView.HORIZONTAL、RecyclerView.VERTICAL
- java - 无法打开上传到 firebase 的 pdf 文件