ANTLR如何决定应用哪个词法分析器规则?最长的匹配词法分析器规则获胜?

时间:2017-08-02 01:43:34

标签: compiler-construction antlr antlr4 lexer

输入内容:

enter image description here

语法:

grammar test;

p : EOF;

Char : [a-z];

fragment Tab : '\t';
fragment Space : ' ';
T1 : (Tab|Space)+ ->skip;

T2 : '#' T1+ Char+;

匹配结果如下:

[@0,0:6='#   abc',<T2>,1:0]    <<<<<<<< PLACE 1
[@1,7:6='<EOF>',<EOF>,1:7]
line 1:0 extraneous input '#   abc' expecting <EOF>

请忽略最后一行中的错误。我想知道为什么在 PLACE 1 匹配的令牌是T2

在语法文件中,T2词法分析器> T1词法分析器后 。所以我希望首先应用T1规则。那么为什么不跳过# abc中的空格?

ANTLR是否使用一些贪婪的策略来匹配当前字符流和最长的词法分析器规则?

3 个答案:

答案 0 :(得分:5)

按以下顺序适用三条规则:

  1. 最长的比赛首先获胜。
  2. 规则匹配隐式标记(如语法中的#)。
  3. 最后,如果是平局(按比赛长度),匹配规则中最早列出的规则将获胜。
  4. 经过大量的凌晨搜索,我再次从Sam Harwell的一篇冗长的引文中找到了大部分这些材料,其中他还阐述了贪婪的运营商的影响。我记得第一次看到它并在我的TDAR副本中勾画笔记,但没有参考。

      

    ANTLR 4词法分子通常以最长匹配胜利行为进行操作,而不考虑替代词出现在语法中的顺序。如果两个词法分析器规则匹配相同的最长输入序列,则只有这些规则的相对顺序进行比较才能确定如何分配令牌类型。

         

    一旦词法分析器到达非贪婪的可选项或闭包,规则中的行为就会发生变化。从该时刻开始到规则结束,该规则中的所有备选方案都将被视为有序,而具有最低备选方案的路径将获胜。这种看似奇怪的行为实际上是由于我们在底层ATN表示中订购替代方式而导致的非贪婪处理。当词法分析器处于此模式并到达块(ESC |。)时,排序约束要求它尽可能使用ESC。

    &#34;隐含令牌&#34;规则来自here

答案 1 :(得分:1)

回应...

<块引用>

ANTLR 是否使用某种贪婪策略来匹配当前字符流与最长词法分析器规则?

...我将引用 ANTLR4 的 Wildcard Operator and Nongreedy Subrules 文档。

<块引用>

以下是词法分析器选择标记规则的方式:

  1. 主要目标是匹配识别最多输入字符的词法分析器规则。
INT : [0-9]+ ;
DOT : '.' ; // match period
FLOAT : [0-9]+ '.' ; // match FLOAT upon '34.' not INT then DOT
  1. 如果多个词法分析器规则与相同的输入序列匹配,则优先级会转到语法文件中第一个出现的规则。
DOC : '/**' .*? '*/' ; // both rules match /** foo */, resolve to DOC
CMT : '/*' .*? '*/' ;
  1. 非贪婪子规则匹配仍然允许周围词汇规则匹配的最少字符数。
/** Match anything except \n inside of double angle brackets */
STRING : '<<' ~'\n'*? '>>' ; // Input '<<foo>>>>' matches STRING then END
END    : '>>' ;
  1. 在穿过词法规则中的非贪婪子规则后,此后的所有决策都是“第一场比赛获胜”。

例如,规则右侧(语法片段)ab 中的文字 .*? ('a'|'ab') 是死代码,永远无法匹配。如果输入是 ab,则第一个选项 'a' 匹配第一个字符,因此成功。 ('a'|'ab') 本身在规则的右侧正确匹配输入 ab 的第二个选项。这种怪癖源于一个非贪婪的设计决策,它太复杂了,无法在这里讨论。

如果您了解规则 1、2 和 3,您可能会没事。第四条规则是深奥的。

仅根据上面引用的信息,我看不到隐式令牌规则适用于何处的明确答案。当我找到更多信息时,我会更新这个答案。

我鼓励您也查看 TomServo's answer,它更多地讨论了隐式令牌规则。

(另外:在我看来,上面引用的内容如果合并到 the lexer rules docs 中可能会更容易被发现和理解。)

答案 2 :(得分:0)

我认为这是因为ANTLR首先在词法分析阶段看到#字符,所以它将沿着T2规则。幸运的是,T2匹配。如果ANTLR首先看到,那么它将遵循T1规则。