ANTLR AST 访问者表示 returns 不同的数据类型
ANTLR AST visitor that returns different data types
我完成了将 ANTLR CST 转换为 AST 并创建了一个特定的 Visitor<T>
接口,允许我访问我所有的 AST 节点,但我遇到的主要问题是一些访问应该 return 不同的数据类型,我不知道该怎么做。
例如,对于简单的算术运算,我想从各自的访问方法中 return 加倍;但其他字符串操作则需要各自的节点return一个字符串。
由于我的访问方法都需要一个泛型类型 T
,我尝试制作一个名为 Result
的 class 和两个子 classes DoubleResult
和 StringResult
这样我的访客在访问期间可以 return 字符串或双精度,但它看起来很糟糕并且充满了转换和类型检查。
有没有更好的方法来做这样的事情?
这是一个示例代码:
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,您需要在其中识别预期的 return 类型,并且必须 return 类型:
有几种方法可以解决您的问题。 (它肯定会出现在动态类型语言中)。
对于我为教程编写的简单语言,我只是定义了一个 Value
class,它可以包含我允许的任何动态类型。我有每个类型的 getters/setters 以及每个类型的 is*()
方法。我的表达式 Visitor 刚刚 returned 这个动态类型。
注意:在执行之前,我使用了一个语义验证监听器,它使用了一种基于堆栈的方法,当我退出一个表达式,验证这些值的类型兼容性,然后将结果类型压入堆栈(文字和变量只是将它们的类型压入堆栈)。我遇到的任何问题都会在执行前推送一条错误消息。这样我就知道,在执行类型中,我总是有正确的类型。 (同样可以在运行时完成;这只是我选择的解决方案。)
实现这一点的另一种可能很方便的方法,因为您在使用 Visitors 时可以控制树导航,所以没有什么可以说您必须有一个用于完整树的 Visitor。您可以有多个访问者(每个访问者都有自己的类型),并选择使用哪个访问者来访问您的子节点。例如,我使用 returned NULL
类型的访问者访问了语句节点,但使用 returned 我的动态 Value
类型的访问者访问了所有表达式节点。
您没有任何理由不能拥有任意数量的不同类型的访客。 Visitor 无状态的情况并不少见,因此您可以在访问每个子级的适当类型之间来回切换来重新使用它们。 (当然,这是假设,从父节点,您可以确定应该使用哪种访问者类型来访问每个子节点。)
小问题...ANTLR4 生成解析树(不是 AST)
我完成了将 ANTLR CST 转换为 AST 并创建了一个特定的 Visitor<T>
接口,允许我访问我所有的 AST 节点,但我遇到的主要问题是一些访问应该 return 不同的数据类型,我不知道该怎么做。
例如,对于简单的算术运算,我想从各自的访问方法中 return 加倍;但其他字符串操作则需要各自的节点return一个字符串。
由于我的访问方法都需要一个泛型类型 T
,我尝试制作一个名为 Result
的 class 和两个子 classes DoubleResult
和 StringResult
这样我的访客在访问期间可以 return 字符串或双精度,但它看起来很糟糕并且充满了转换和类型检查。
有没有更好的方法来做这样的事情?
这是一个示例代码:
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,您需要在其中识别预期的 return 类型,并且必须 return 类型:
有几种方法可以解决您的问题。 (它肯定会出现在动态类型语言中)。
对于我为教程编写的简单语言,我只是定义了一个 Value
class,它可以包含我允许的任何动态类型。我有每个类型的 getters/setters 以及每个类型的 is*()
方法。我的表达式 Visitor 刚刚 returned 这个动态类型。
注意:在执行之前,我使用了一个语义验证监听器,它使用了一种基于堆栈的方法,当我退出一个表达式,验证这些值的类型兼容性,然后将结果类型压入堆栈(文字和变量只是将它们的类型压入堆栈)。我遇到的任何问题都会在执行前推送一条错误消息。这样我就知道,在执行类型中,我总是有正确的类型。 (同样可以在运行时完成;这只是我选择的解决方案。)
实现这一点的另一种可能很方便的方法,因为您在使用 Visitors 时可以控制树导航,所以没有什么可以说您必须有一个用于完整树的 Visitor。您可以有多个访问者(每个访问者都有自己的类型),并选择使用哪个访问者来访问您的子节点。例如,我使用 returned NULL
类型的访问者访问了语句节点,但使用 returned 我的动态 Value
类型的访问者访问了所有表达式节点。
您没有任何理由不能拥有任意数量的不同类型的访客。 Visitor 无状态的情况并不少见,因此您可以在访问每个子级的适当类型之间来回切换来重新使用它们。 (当然,这是假设,从父节点,您可以确定应该使用哪种访问者类型来访问每个子节点。)
小问题...ANTLR4 生成解析树(不是 AST)