将一些评估委托给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)?
| ...
;
当然,在我的用例中,这是不可能的,因为在编译基本语法之后,模块应该能够扩展语法。但我想你的结论是正确的,没有其他办法。我想,我最终会重新分析语法中的“扩展”等价物:)