ANTLR4 AST vistor和节点返回类型:我应该有多个访问者吗?

时间:2015-04-28 20:15:21

标签: antlr4

我正在尝试学习ANTLR(使用v4),我正在使用访问者来引导antlr生成的AST。

帮助我学习 - 我想出了一种愚蠢的语言来解析。它有'参议员'的名单

FirstName LastName (party)例如BA Baracus (R)

这些填充了一个Universe(在ArrayList()中),您可以稍后使用

进行操作

......还有一些'行动',比如

~printRhouse打印出代表院(即打印出宇宙,按派对分组)

ANTLR为我生成了一个基本访问者,它是一个参数化的类 - 所以我将一个Class子类化为T - 这个类似乎是访问者返回的所有方法。

Antlr生成类似

的内容
public class SenatorBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements SenatorVisitor<T> {

然后我想出了这样的具体实现。

public class InitialParseVisitor extends SenatorBaseVisitor<SenatorASTContainer> {

我发现自己编写了一个'容器'类(在这种情况下为SenatorASTContainer),而不是捕获树方法可以返回的任何内容 - 在这种情况下定义新参议员的语句,或者像'printhouse'这样的'动作' ”。这感觉很糟糕,因为这个类变得非常杂乱和多功能,因为它必须处理树中的每种类型的节点。

我是否以错误的方式思考这个问题? - 我应该有n个步行者,每个步行者都有更多的单一目的返回类型,而且都设计为做一件事。通过选择不访问它们,每个节点都会忽略不同类型的节点。

然后,人们会在AST上走n次,每次都有一个不同的助行器,嗅探不同的东西,最后将多个运行的输出组合成最终的程序。

如果没有,并且一个walker类型通常就足够了,那么当我有不同类型的节点时,我应该如何考虑方法的返回类型?

2 个答案:

答案 0 :(得分:3)

拥有多个访问者并不能解决问题:实际上,每个具有非平凡语法的规则都将获得自己的访问者(和结果节点)。生成的代码难以维护。

我认为最常见的方法是使用SenatorASTContainer作为所有生成的AST节点的超类:

FirstNameLastNameParty可能是StringNode extends SenatorASTContainer,一行的类型为Senator extends SenatorASTContainer。然而,Senator的访问者必须将较低节点的结果转换为StringNode(访问者只会返回通用SenatorASTContainer)。

答案 1 :(得分:1)

与您的问题相关,Antlr支持至少两个主要访问者策略:(1)返回类主要用作累加器;(2)具有节点类型特定属性类的解析树注释。

对于注释策略,请扩展ParseTreeProperty以创建特定于上下文节点类型的属性类。请参阅该类中的注释以了解如何使用。

通常,遍历解析树一次或多次以创建,分析和修改属性数据。走最后一次产生输出。这是使用注释策略方法的example project

如果返回类策略倾向于严重过度使用单个类,则注释策略倾向于使用相当多的样板来扩散小类。这是code generator可能有助于解决这个问题。&#39;