将一些评估委托给 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
来响应此基本语法中定义的所有规则:
visitTxtExt
、visitTarExt
、visitGzExt
、visitCompositeExt
他们都只接受PathBaseParser.*Context
个对象。
这意味着当我为 win
和 linux
实现我的访问者时,它们只提供 WinParser.*Context
和 LinuxParser.*Context
(它们不是 [=24 中上下文的子类) =]),我似乎无法使用我刚刚通过在给定的 ExtensionContext 上调用 visit()
实现的 PathBaseBaseVisitor
。
有人知道如何解决这个问题吗?
我似乎想出的唯一一件事就是在上下文中调用 getText()
并用 PathBaseParser
重新解析它,但这对我来说似乎很脏。
要处理多个语法变体,正如您似乎正在尝试做的那样,您的目标应该是构建一个单一语法,该语法导入定义变体的规则子集。也就是说,在您的示例中,'base' 应该是您的主要语法,导入的语法应该包含 'path' 规则。没有其他实用的方法可以避免您遇到的继承问题。
可以肯定的是,如果变体之间的差异很大或可能会变大(例如 Python 2 -> Python 3),维护相互依赖的语法的努力将很快超过感知好处。相反,如果很小,可以使用谓词来处理差异
path : { os().isWindows() }? DRIVE ('\' NAME)+ ('.' extension)?
| { os().isLinux() }? DRIVE ('/' NAME)+ ('.' extension)?
| ...
;
我目前正在尝试实现多个共享某些概念的不同语法。
假设它们看起来像这样——这与我的实际语法无关:
语法路径基础;
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
来响应此基本语法中定义的所有规则:
visitTxtExt
、visitTarExt
、visitGzExt
、visitCompositeExt
他们都只接受PathBaseParser.*Context
个对象。
这意味着当我为 win
和 linux
实现我的访问者时,它们只提供 WinParser.*Context
和 LinuxParser.*Context
(它们不是 [=24 中上下文的子类) =]),我似乎无法使用我刚刚通过在给定的 ExtensionContext 上调用 visit()
实现的 PathBaseBaseVisitor
。
有人知道如何解决这个问题吗?
我似乎想出的唯一一件事就是在上下文中调用 getText()
并用 PathBaseParser
重新解析它,但这对我来说似乎很脏。
要处理多个语法变体,正如您似乎正在尝试做的那样,您的目标应该是构建一个单一语法,该语法导入定义变体的规则子集。也就是说,在您的示例中,'base' 应该是您的主要语法,导入的语法应该包含 'path' 规则。没有其他实用的方法可以避免您遇到的继承问题。
可以肯定的是,如果变体之间的差异很大或可能会变大(例如 Python 2 -> Python 3),维护相互依赖的语法的努力将很快超过感知好处。相反,如果很小,可以使用谓词来处理差异
path : { os().isWindows() }? DRIVE ('\' NAME)+ ('.' extension)?
| { os().isLinux() }? DRIVE ('/' NAME)+ ('.' extension)?
| ...
;