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

问题描述

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

我对ANTLR(我最近才学到的)和一般访客模式都没有什么经验,但是如果我正确理解,访客应该封装 一个单个操作在整个数据结构(在本例中为解析树)上,因此在每个Visit*()方法之间共享相同的返回类型。 以Terence Parr的《权威ANTLR 4参考书》中的示例为例,参观由语法解析的一系列算术表达式序列生成的语法树,选择int返回类型是很自然的,因为树实际上是算术运算的一部分,它有助于计算器获得最终结果。

考虑到我目前的情况,我没有一个普通的类型:我的语法分析整个文档,实际上整个文档被划分为不同的部分,具有不同的职责(变量声明,打印选项,行的实际文本等)。 ),那么除了object之外,在如此众多不同节点的访问结果之间我找不到共同的类型。 我试图考虑一些可能的解决方案:

  1. 我首先尝试使用object来实现无状态访问者 普通类型,但所需的类型转换数量听起来像 我的大红旗。我当时正在考虑使用JSON,但我认为 问题仍然存在,可能会增加 序列化过程。

  2. 我也在考虑将访客分成更小的 具有特定目的的访问者(获取所有变量,获取所有 行等),但是对于每个访问者,我都会采用这种解决方案 仅实现自动生成方法的一小部分 接口(因为它旨在支持整个树的访问), 因为每个访问操作可能只会专注于 特定的子树。正常吗?

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

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

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

解决方法

ANTLR4解析树由于递归而通常很复杂,例如 我将定义ParsedDocumentModel类,该类的属性会随着项目的发展而增加或修改(这是正常的,没有程序是固定的)。

假设您的语法在文件Parser.g4中称为“解析器”,下面是示例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;
    }
}