繁体   English   中英

返回不同数据类型的 ANTLR AST 访问者

[英]ANTLR AST visitor that returns different data types

我完成了将 ANTLR CST 转换为 AST 并创建了一个特定的Visitor<T>接口,该接口允许我访问我的所有 AST 节点,但我遇到的主要问题是某些访问应该返回不同的数据类型,我是不知道如何 go 关于这个。 例如,对于简单的算术运算,我想从它们各自的访问方法中返回一个 double; 但其他字符串操作将需要它们各自的节点返回一个字符串。 由于我的访问方法都需要一个泛型类型T ,我尝试制作一个名为Result的 class 和两个子类DoubleResultStringResult ,以便我的访问者在访问期间可以返回一个字符串或双精度数,但它看起来很糟糕并且充满了强制转换和类型检查。 有没有更好的方法来做这样的事情?

这是一个示例代码:

public class ExpressionVisitor implements Visitor<Result> {
    ...
    public Result visit(BinaryExpression node) {
        // here the node's left or right can be StringResults
        // So i'd have to do instance and type checks
    }

    public Result visit(StringExpression node) {
        // here i'd return a StringResult specifically
    }
}

编辑:目标是能够进行字符串运算,例如 python 例如2*"hello"

但是二进制表达式访问方法必须检查哪个操作数是字符串(左或右),然后大多数其他访问方法将需要相应地检查和处理 DoubleResult 或 StringResult 类型。 有没有更清洁的方法来实现同样的目标?

正如您毫无疑问地发现的那样,ANTLR 为您生成的访问者 class 是通用 class ,您需要在其中识别预期的返回类型,并且必须返回该类型:

有几种方法可以解决您的问题。 (它肯定出现在动态类型语言中)。

对于我为教程编写的简单语言,我刚刚定义了一个Value class ,它可以包含我允许的任何动态类型。 我有每种类型的 getter/setter 以及每种类型的is*()方法。 我的表达式 Visitor 刚刚返回了这个动态类型。

注意:在执行之前,我使用了语义验证侦听器,它使用基于堆栈的方法,当我退出表达式时,我从堆栈中弹出表达式类型(当我访问子项时已将其推入堆栈),验证了类型兼容性这些值,然后将结果类型压入堆栈(文字和变量只是将它们的类型压入堆栈)。 我遇到的任何问题都会在执行之前推送错误消息。 这样我就知道,在执行类型中,我总是有正确的类型。 (同样可以在运行时完成;这只是我选择的解决方案。)

实现这一点的另一种可能方便的方法是,由于您在使用访问者时可以控制树导航,因此没有什么可以说您必须有一个访问者用于整个树。 您可以有多个访问者(每个访问者都有自己的类型),并选择使用哪个访问者来访问您的子节点。 例如,我访问了返回NULL类型的访问者的语句节点,但访问了返回我的动态Value类型的访问者的所有表达式节点。

没有真正的理由你不能拥有尽可能多的访客,每个访客都有不同的类型。 访问者无国籍的情况并不少见,因此您可以重复使用它们在适当的类型之间来回跳跃来访问每个孩子。 (当然,这假设您可以从父节点确定您应该使用哪种访问者类型来访问每个子节点。)

Minor nit... ANTLR4 生成解析树(不是 AST)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM