【问题标题】:Antlr4 - Best way to switch between Listener and Visitor modes?Antlr4 - 在侦听器和访客模式之间切换的最佳方式?
【发布时间】:2017-12-13 18:31:42
【问题描述】:

我目前正在规划语言解释器的结构,我意识到我不喜欢专门使用访问者或侦听器树遍历方法的想法。

由于这两种遍历树的方法都有其优点,理想情况下,我想混合使用这两种方法:

  • 在遍历任意语言块定义(函数/类定义、类似结构/枚举的定义)时使用侦听器最有意义,尤其是当它们可以嵌套时。
  • 访问者似乎很自然地适合诸如表达式评估之类的情况,在这种情况下,上下文更加可预测,并且结果值可以返回到链上。

在两种遍历方法之间切换最“正确”的方法是什么?

到目前为止,我的想法如下:

为解析树的一部分从监听器切换到访问器

说,当监听器到达节点“Foo”时,我想使用访问者更明确地处理它的子节点。我能想到的一种方法是:

  • 解析 Tree walker 调用 enterFoo(ctx)
    • 创建一个 myFooVisitor 的实例
    • 显式访问儿童、存储结果等
    • 设置ctx.children = [](或等效项)
  • enterFoo() 返回时,解析树遍历器会看到该节点没有更多子节点,因此不会不必要地遍历 Foo 的所有子节点

为解析树的一部分从访问者切换到监听者

这对我来说更明显。由于在使用访问者时树的遍历是明确控制的,因此切换似乎很简单。

  • visitFoo() 被调用
    • 创建一个新的解析树遍历器和 myFooListener 的实例
    • 照常使用侦听器启动walker。

【问题讨论】:

    标签: parsing antlr4


    【解决方案1】:

    您似乎已经知道听众和访问者是模式的地方,有点说您可以切换。这是错误的。

    侦听器和访问者都是允许您对规则遍历进行操作的类。侦听器通过在解析过程中“输入”或“离开”规则时从解析器调用来完成此操作。不涉及解析树。

    然而,访问者使用解析树遍历每个节点并为它们调用方法。您可以覆盖这些方法中的任何一个来执行任何相关的工作。这与评估结果无关。你可以独立使用它。

    ANTLR4 为您的每个规则(在侦听器和访问者中)生成方法主体,这使您可以轻松地只实现您感兴趣的那些规则。

    既然您知道在解析期间使用侦听器,而在解析之后使用访问者,那么显然您不能在它们之间切换。事实上,切换并没有多大帮助,因为这两个类的作用基本相同(为遇到的规则调用方法)。

    如果您的问题实际上包含您想要实现的什么,而不是如何,我可能会为您提供更多信息。

    【讨论】:

    • 啊,我并不是要暗示我认为听众和访问者是“模式”。我想我的问题是:当使用调用监听器方法的 walker 时,是否有机制让 walker 停止遍历子节点?原因是,如果我已经使用访问者自己提取了信息,那么步行者就没有理由继续调用子侦听器方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 1970-01-01
    • 2016-09-23
    • 2011-06-09
    • 2013-11-07
    • 1970-01-01
    相关资源
    最近更新 更多