将一些评估委托给 ANTLR 4 中导入语法的访问者

Delegate some evaluation to the visitor of the imported grammar in ANTLR 4

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

假设它们看起来像这样——这与我的实际语法无关:

语法路径基础;

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(它们不是 [=24 中上下文的子类) =]),我似乎无法使用我刚刚通过在给定的 ExtensionContext 上调用 visit() 实现的 PathBaseBaseVisitor

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

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

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

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

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