所有ANTLR访问者方法的通用返回类型

所有ANTLR访问者方法的通用返回类型,antlr,visitor,visitor-pattern,Antlr,Visitor,Visitor Pattern,我正在用ANTLR为一个旧的专有报告规范编写一个解析器,目前我正在尝试实现一个生成的解析树的访问者,扩展自动生成的抽象visito类 我对ANTLR和visitor模式都没有什么经验,但如果我理解正确,visitor应该在整个数据结构上封装一个操作(在本例中是解析树),从而在每个Visit*方法之间共享相同的返回类型。 以Terence Parr的权威ANTLR 4参考书为例,要访问由解析算术表达式序列的语法生成的解析树,选择int返回类型感觉很自然,因为树的每个节点实际上都是算术运算的一部分,

我正在用ANTLR为一个旧的专有报告规范编写一个解析器,目前我正在尝试实现一个生成的解析树的访问者,扩展自动生成的抽象visito类

我对ANTLR和visitor模式都没有什么经验,但如果我理解正确,visitor应该在整个数据结构上封装一个操作(在本例中是解析树),从而在每个Visit*方法之间共享相同的返回类型。 以Terence Parr的权威ANTLR 4参考书为例,要访问由解析算术表达式序列的语法生成的解析树,选择int返回类型感觉很自然,因为树的每个节点实际上都是算术运算的一部分,算术运算会产生计算器的最终结果

考虑到我目前的情况,我没有一个通用的类型:我的语法解析整个文档,它实际上被分为不同的部分,具有不同的职责变量声明、打印选项、行的实际文本等,我无法在访问如此多不同节点的结果之间找到一个通用的类型,当然除了目标之外。 我试图想出一些可能的解决办法:

我首先尝试使用对象作为对象实现无状态访问者 常见类型,但所需类型转换的数量听起来像 对我来说是个大红旗。我在考虑使用JSON,但我认为 问题仍然存在,这可能会在系统中增加一些额外的开销 序列化过程

我也在考虑把访客分成更小的部分 具有特定目的的访问者可以获得所有变量,获得所有 行等,但对于每个访问者,使用此解决方案,我将 只实现自动生成方法的一小部分 接口,因为它旨在支持整个树的访问, 因为每个访问操作可能只关注一个 特定子树。这正常吗

另一种可能是重新设计数据结构,以便 它可以用于树的每个级别,或者更好地定义泛型 稍后可用于构建数据的节点的规范 结构这个解决方案听起来不错,但我认为很难实现 应用于此域

最后一个选择是切换到有状态的访问者,这 将一个或多个构建器封装到所需的不同截面中 每个Visit*方法都可以用来构建数据结构 一步一步。这个解决方案似乎是干净可行的,但我有 难以考虑如何确定每次访问的结果范围 需要时在父作用域中执行操作


什么解决方案通常用于访问复杂的ANTLR解析树?

ANTLR4解析树通常由于递归而复杂,例如。 我将定义ParsedDocumentModel类,其属性将随着项目的发展而添加或修改,这是正常的,没有任何程序是一成不变的

假设您的语法在Parser.g4文件中被称为Parser,下面是示例C代码:

public class ParsedDocumentModel {
    public string Title { get; set; }
    //other properties ...
}
public class ParserVisitor : ParserBaseVisitor<ParsedDocumentModel>
{
    public override ParsedDocumentModel VisitNounz(NounzContext context)
    {
        var res = "unknown";
        var s = context.GetText();
        if (s == "products")
            res = "<<products>>"; //for example

        var model = new ParsedDocumentModel();
        model.Title = res;  //add more info...
        return model;
    }
}

是的,生成的访问者类将所有访问者方法的返回类型设置为公共类型。因此,如果您正在使用visitor类构建一个自底向上的AST,那么您必须在类型格上选择一个类,该类包含您实际可以返回的所有可能的类型(通常默认为object)和大量类型转换。另一种考虑的方法是生成的侦听器,其中每个解析节点都有一个特定的类型和属性,您可以在Exit方法上自下而上地对这些类型和属性进行评估。或者,您可以编写自己的访问者类,每个方法有不同的返回类型。关于类型转换,我很遗憾听到这是一个常见的解决方案:我知道单元测试应该涵盖所有可能的类型相关问题,但我仍然认为这是一种可能导致bug的代码气味。关于实现我自己的访问者,我已经考虑过了,但是当使用常规的Visit方法时,它并没有什么用处,它必须返回object来抽象出要调用的实际Visit*方法的选择。由于访问者模式将与常规方法一起使用,因此仍然需要强制转换……选项2是我已经使用过多次的选项。我会说这很正常。若一个访问者实际上只实现了一堆公开的访问方法,比如说50个中的2个,这不是问题吗?我同意你们的观点,实现从解析树生成更高级别的模型是个好主意;这正是我想做的。我的问题是关于我想要构建的访问者,该访问者可以在树上行走并生成我的模型。。。