Antlr4 ANTLR:模式贪婪性和替代排序

Antlr4 ANTLR:模式贪婪性和替代排序,antlr4,Antlr4,我试图了解在ANTLR规则中,当几个选项匹配时,哪个选项更受欢迎。根据,lexer规则中的备选方案是无序的,除非在非贪婪模式之后(*?,+?,??)。例如,此语法: lexer grammar Test; X : 'z'*? (FOO | FOOBAR); fragment FOO: 'foo'; BAR: 'bar'; fragment FOOBAR: 'foobar'; 给定的输入“foobar”匹配两个标记:X“foo”和BAR“BAR”,因为X中的替代项是有序的。如果我们删除'z'*

我试图了解在ANTLR规则中,当几个选项匹配时,哪个选项更受欢迎。根据,lexer规则中的备选方案是无序的,除非在非贪婪模式之后(
*?
+?
??
)。例如,此语法:

lexer grammar Test;

X : 'z'*? (FOO | FOOBAR);
fragment FOO: 'foo';
BAR: 'bar';
fragment FOOBAR: 'foobar';
给定的输入“foobar”匹配两个标记:
X
“foo”和
BAR
“BAR”,因为
X
中的替代项是有序的。如果我们删除
'z'*?
或甚至将其更改为贪婪的
'z'*
,替代项将再次无序,唯一匹配的标记是
X
“foobar”

但是,如果我将规则更改为解析器规则:

grammar Test;

x : 'z'*? (foo | foobar);
foo: 'foo';
bar: 'bar';
foobar: 'foobar';
'z'
的贪婪似乎一点也不重要。给定输入“foobar”,规则
x
遵循第二个选项并使用整个输入,生成树
(x(foobar“foobar”)

问题是:是否有明确的文档说明lexer和parser规则是如何使用输入的,以及在可能有几种情况下它们更喜欢哪种匹配?

是否有关于lexer和parser如何处理规则的明确文档 使用输入,并且在可能有多个输入时,他们更喜欢哪种匹配

最终文档(除阅读源代码外):

1) Sam Harwell(作者)在stackoverflow中的评论

2) 特伦斯·帕尔写给ANTLR4的书

对于您的案例,可以在Terence Parr的书中找到解析规则的完整解释:

第15.6章通配符运算符和非reedy子规则->非reedy Lexer子规则

在通过词汇表中的非reedy子规则之后 从那时起,所有的决策都是“第一场比赛获胜” 例如,规则右侧的备选“ab”?('a'|'ab')是 死代码,永远无法匹配。如果输入为ab,则第一个 备选方案“a”与第一个字符匹配,因此成功。 规则右侧的('a'|'ab')本身与 输入ab的第二种选择。这种怪癖源于非reedy 设计决策太复杂了,不能在这里讨论

对于这样一个完整的语法:

grammar TestGrammar;
test:XXX  EOF;
WS: [ \t\f]+ -> channel(1);
CRLF: '\r'? '\n' -> channel(1);
XXX : 'z'*? (FOO | FOOBAR) {System.out.println(getText());};

fragment FOO: 'foo';
fragment BAR: 'bar';
fragment FOOBAR: 'foobar';
对于像
zfoo
这样的输入。它由
XXX
规则标记,lexer操作输出证实了这一点。用于输入
zfoobar
。前4个字符
zfoo
仍然由规则
XXX
标记,由于上面提到的“第一场比赛获胜”规则,剩下
bar
作为未识别的标记

对于非贪婪解析器子规则:

非reedy解析器子规则

非reedy子规则和通配符也可以使用 在解析器中进行“模糊解析”非常有用,其目标是 从输入文件中提取信息,而无需指定 完整语法。与nongreedy lexer决策相反,解析器 始终做出正确的决策。解析器永远不会产生错误 最终导致有效输入失败的决策 解析。这里是中心思想:nongreedy解析器子规则匹配 保留成功解析的最短令牌序列 一个有效的输入句子

这不会对子规则施加排序