在ANTLR 4中向导入语法的访问者委派一些评估

时间:2015-01-13 10:35:28

标签: antlr antlr4

我目前正在尝试实现多个不同的语法,这些语法共享一些概念。

让我们说他们看起来像这样 - 这与我的实际语法无关:

语法pathBase;

extension
  : 'txt'                     #txtExt
  | 'tar'                     #tarExt
  | 'gz'                      #gzExt
  | extension '.' extension   #compositeExt
  ;

并说有一些特定于os的路径语法。 一个用于Windows:

grammar win;
import base;

path: DRIVE ('\' NAME)+ ('.' extension)?;

还有一个用于linux:

grammar linux;
import base;

path: ('/' NAME)+ ('.' extension)?;

现在我有两个不同的语法,它们有两个不同的解析器(WinParser和LinuxParser),它们与extension具有完全独立的上下文。由于我想避免重复代码,我现在创建一个PathBaseBaseVisitor,它对这个基本语法中定义的所有规则作出反应:

visitTxtExtvisitTarExtvisitGzExtvisitCompositeExt

他们都只接受PathBaseParser.*Context个对象。

这意味着当我为winlinux实施我的访问者时,其仅提供WinParser.*ContextLinuxParser.*Context(不是PathBaseParser中的上下文的子类),我似乎无法通过在给定的ExtensionContext上调用PathBaseBaseVisitor来实现我刚刚实现的visit()

有人知道如何解决这个问题吗?

我似乎唯一想到的就是在上下文中调用getText()并用PathBaseParser重新解析它,但这对我来说似乎很脏。

1 个答案:

答案 0 :(得分:1)

要处理多种语法变体,正如您似乎要尝试的那样,您的目标应该是构造一个语法,该语法导入定义变体的规则子集。也就是说,在您的示例中,“base”应该是您的主要语法,导入的语法应该包含“path”规则。没有其他实用的方法可以避免遇到的继承问题。

可以肯定的是,如果变体的差异很大或者可能变得很大(例如Python 2 - > Python 3),维护相互依赖的语法的努力将很快超过感知的好处。相反,如果很小,您可以使用谓词来处理差异

path : { os().isWindows() }? DRIVE ('\' NAME)+ ('.' extension)?
     | { os().isLinux() }?   DRIVE ('/' NAME)+ ('.' extension)?
     | ...
     ;