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

将一些评估委托给ANTLR 4中导入语法的访问者,antlr,antlr4,Antlr,Antlr4,我目前正在尝试实现多个不同的语法,它们共享一些概念 假设它们看起来像这样-这与我的实际语法无关: 语法路径库 extension : 'txt' #txtExt | 'tar' #tarExt | 'gz' #gzExt | extension '.' extension #compositeExt ; 假设有一些特定于操作系统的路径语法。 一个用于

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

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

语法路径库

extension
  : 'txt'                     #txtExt
  | 'tar'                     #tarExt
  | 'gz'                      #gzExt
  | extension '.' extension   #compositeExt
  ;
假设有一些特定于操作系统的路径语法。 一个用于windows:

grammar win;
import base;

path: DRIVE ('\' NAME)+ ('.' extension)?;
一个用于linux:

grammar linux;
import base;

path: ('/' NAME)+ ('.' extension)?;
现在我有了两个不同的语法,它们有两个不同的解析器(WinParser和LinuxParser),它们的
扩展
的上下文完全不同。由于我希望避免代码重复,现在我创建了一个
PathBaseVisitor
,它对此基本语法中定义的所有规则作出反应:

visitxtext
visittrext
visitGzExt
visitCompositeExt

它们都只接受
PathBaseParser.*上下文
对象

这意味着当我为
win
linux
实现访问者时,它们只提供
WinParser.*上下文
LinuxParser.*上下文
(它们不是
PathBaseParser
中上下文的子类),我似乎无法使用我刚才通过在给定的ExtensionContext上调用
visit()
实现的
PathBaseVisitor

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


我唯一想到的是在上下文中调用
getText()
,然后使用
PathBaseParser
对其进行重新分析,但这对我来说似乎有点脏。

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

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

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

当然,在我的用例中,这是不可能的,因为在编译基本语法之后,模块应该能够扩展语法。但我想你的结论是正确的,没有其他办法。我想,我最终会重新分析语法中的“扩展”等价物:)