ANTLR:模式贪婪和替代排序

时间:2016-04-20 10:34:29

标签: antlr4

我试图了解ANTLR规则中的哪些替代方案在多个匹配时更喜欢。根据{{​​3}},词法分析规则中的替代方案是无序的,除非在非贪婪模式(*?+???之后。例如,这个语法:

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';
<{1}}上的贪婪似乎并不重要。给定输入&#34; foobar&#34;,规则'z'遵循第二种选择并消耗整个输入,生成树x

问题是:是否有关于词法分析器和解析器规则如何消耗输入以及在可能的情况下他们喜欢哪些匹配的权威文档?

1 个答案:

答案 0 :(得分:1)

  

是否有关于词法分析器和解析器规则的权威文档   消费输入和哪些匹配他们喜欢什么?

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

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

2)Terence Parr的ANTLR4书

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

  

第15.6章通配符操作符和Nongreedy子规则 - &gt; Nongreedy Lexer子规则

     

在词汇中穿过一个非同意的子规则之后   规则,从此开始的所有决策都是“第一场比赛获胜”   例如,规则右侧的替代'ab'。*? ('a'|'ab')是   死代码,永远无法匹配。如果输入是ab,则第一个   替代方案,'a',匹配第一个字符,因此成功。   ('a'|'ab')在规则的右侧单独匹配   输入ab的第二种选择。这种怪癖来自于一种不同寻常的行为   设计决定过于复杂,不能进入这里。

所以对于像这样的完整语法:

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规则标记,而词法分析器动作输出确认了这一点。输入zfoobar。由于上面提到的“首次匹配获胜”规则,前{4}个字符zfoo仍然被XXX标记为bar,因为无法识别的令牌为

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

  

Nongreedy Parser Subrules

     

Nongreedy子规则和通配符也是   在解析器中有用,可以进行“模糊解析”   从输入文件中提取信息,而不必指定   完整的语法。与nongreedy lexer决策制作,解析器相反   始终做出全球正确的决定。解析器永远不会成为   决定最终导致有效输入在以后失败   解析。这是一个中心思想:nongreedy解析器子规则匹配   保存成功解析的最短令牌序列   一个有效的输入句子。

这不会对子规则进行排序。