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

ANTLR4 AST vistor and node return Type: should I have more than one visitor?

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

帮助我学习 - 我想出了一种愚蠢的语言来解析。它有 'senators'

的列表

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

这些填充了一个 universe(在 ArrayList() 中),您以后可以用它来做事

...还有一些 'actions' 比如

~printRhouse打印出众议院(即打印出宇宙,按政党分组)

ANTLR 为我生成了一个基本访问者,它是一个参数化的 class - 所以我用一个 Class 作为 T 提供了 subclass - 这个 class 在他们看来似乎是访问者中的所有方法return。

Antlr 生成类似

的东西
public class SenatorBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements SenatorVisitor<T> {

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

public class InitialParseVisitor extends SenatorBaseVisitor<SenatorASTContainer> {

我发现自己写了一个 'container' class(在本例中为 SenatorASTContainer),而不是树方法可以捕获的任何东西 return - 在本例中定义新参议员的声明,或 'actions' 如 'printhouse'。这感觉很糟糕,因为这个 class 变得非常混乱和多功能,因为它必须处理树中的每种类型的节点。

我是不是想错了? - 我是否应该有 n 个助行器,每个助行器都有一个更单一用途的 return 类型,并且都设计用于做一件事。这些中的每一个都会通过选择不访问它们来忽略不同类型的节点。

然后将 AST 遍历 n 次,每次使用不同的 walker 来嗅探不同的东西,最后根据多次运行的输出将最终程序组合在一起。

如果不是,通常一种 walker 类型就足够了,那么当我有不同类型的节点时,我应该如何考虑方法的 return 类型?

与您的问题相关,Antlr 至少支持两种主要访问者策略:(1) return class 本质上用作累加器和 (2) 具有节点类型的解析树注释具体 属性 classes.

对于注释策略,扩展 ParseTreeProperty 以创建特定于上下文节点类型的 属性 classes。使用方法见class中的注释。

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

在 return class 策略倾向于过度使用单个 class 的情况下,注释策略倾向于大量使用较小的 classes样板。这是一个 code generator 可能有助于此 'problem.'

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

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

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