antlr4 - Antlr4 相邻令牌优先级
问题描述
我在构建复杂的语法时遇到了问题。一个宠物语法来说明它如下:
grammar test;
start: (r1 | r2 | .)*
r1: A B
r2: B C
// A B C are tokens
当出现以下输入时:
ABC
解析树如下所示:
start
| \
r1 C
| \
A B
但我真正想要的是它看起来像这样:
start
| \
A r2
| \
B C
我已经尝试重新排序规则并添加<assoc=right>
,但除了删除规则之外似乎没有任何效果r1
,这是不正确的,因为我期望AB
并且BC
是有效的输入。我错过了什么?
编辑
上面的问题描述似乎过于简化了实际问题,所以我将提供更多细节:
r3: rA r4 // prefers rA(classB classC) over (rA classB)classC
r4: classB? classC // also used elsewhere other than r3
rA: // rules to build A subtree, ends with classB? in 'some' cases
classB: B1 | B2 | ... | Bm
classC: C1 | C2 | ... | Cn
我发现以下“类型”有效:
r3: rA Bx classC | ...
但以下没有:
r3: <assoc=right> rA r4 | ... // still builds (rA classB)classC
我想知道是否有一种方法可以正确构建树,同时能够利用r4
及其相关代码(并且避免为所有实例添加另外 m 行B
)?
PS。rA
是昂贵的,所以像上面那样扩展B
令牌r3
会给狗带来性能。
解决方案
我在这里看到的问题是您告诉解析器生成您不想要的解析树。如果你不想要它,那么不要指定应该产生它的语法。
与 Mike Cargal 提出的类似,我认为真正的解决方案是更明确地指定您希望在最后看到的内容。这里有一些效果很好的东西(使用你最初的问题描述和 MikeC 的测试输入):
parser grammar testparser;
options {
tokenVocab = testlexer;
}
start: (A r2 | r1 | .)*? EOF;
r1: A B;
r2: B C;
lexer grammar testlexer;
A: 'A';
B: 'B';
C: 'C';
WHITE_SPACE: [ \u000B\t\r\n] -> skip ;
OTHER: .;
通过输入AB!C2
,我得到了这个解析三:
省略C
此更改为:
主要变化是您通过添加r2 alt 并将其放在首位来专门化规则以BC
在他们自己的子解析树中进行匹配。A
笔记
将该单曲A
移至 r2 规则将打破这一点,因为然后您告诉解析器创建一个包含其中的子树ABC
(您不想要的)。
推荐阅读
- json - 在匹配空手道响应时将变量传递给 json 文件
- wpf - WPF DataGrid 单元格选择
- artificial-intelligence - 给出元素属于特定类别的概率的神经网络
- android - 如何改进 Google 移动视觉 API 文本识别?
- vuejs2 - currentUser 没有使用 Vuex 设置
- sql - 如何理解 PosgreSQL 中的 to_number 格式
- robocopy - 从 robocopy 中排除目标文件/目录?
- regex - MD5 或 SHA256 的 Bash 正则表达式不起作用
- php - 在 AJAX 中执行 SQL 准备语句
- android - 应用程序不断崩溃(不明白) | 安卓工作室 | 科特林