我正试图了解当几个选项匹配时,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和解析器规则如何使用输入的明确文档,以及当可能有几种匹配时,它们更喜欢哪种匹配
有关于lexer和解析器规则的明确文档吗消费输入,当可能有几种匹配时,他们更喜欢哪种匹配?
最终文档(除了阅读源代码):
1) Sam Harwell(作者)在stackoverflow 中的评论
2) Terence Parr为ANTLR4 撰写的书
对于您的情况,解析规则的完整解释可以在Terence Parr的书中找到:
第15.6章通配符算子和非自由子规则->非自由Lexer子规则
在词汇中穿过一个不合理的子规则之后从那时起,所有的决策都是"第一场比赛获胜"例如,规则右侧的备选"ab"。*?('a'|'ab')是死代码,永远无法匹配。如果输入为ab,则第一个备选方案"a"与第一个字符匹配,因此成功。规则右侧的('a'|'ab')本身与输入ab的第二种选择。这个怪癖源于一个非芦苇设计决策太复杂了,不能在这里讨论。
因此,对于这样一个完整的语法:
grammar TestGrammar;
test:XXX EOF;
WS: [ tf]+ -> 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
成为未识别的标记。
对于非贪婪解析器子规则:
Nonreedy Parser子规则
非自由子规则和通配符也是在解析器中进行"模糊解析"非常有用,目标是从输入文件中提取信息,而无需指定完整的语法。与非自由的lexer决策相反,解析器始终做出全局正确的决策。解析器从不生成最终导致有效输入在以后解析。中心思想是:非自由解析器子规则匹配保留成功解析的最短令牌序列一个有效的输入句子。
这并没有把命令强加给子规则。