Antlr4 ANTLR:模式贪婪性和替代排序
我试图了解在ANTLR规则中,当几个选项匹配时,哪个选项更受欢迎。根据,lexer规则中的备选方案是无序的,除非在非贪婪模式之后(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'*
*?
,+?
,??
)。例如,此语法:
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解析器子规则匹配
保留成功解析的最短令牌序列
一个有效的输入句子
这不会对子规则施加排序