ANTLR4 - 在令牌之间选择空格

时间:2016-07-03 06:29:45

标签: parsing antlr4

我有以下语法:

grammar Hello;

prog:   stat+ EOF;

stat:   DELIMITER_OPEN expr DELIMITER_CLOSE;
expr:   NOTES COMMA value=VAR_VALUE #delim_body;

VAR_VALUE:  ANBang*;
NOTES:  WS* 'notes' WS*;
COMMA:  ',';
DELIMITER_OPEN: '<<!';
DELIMITER_CLOSE:    '!>>';

fragment ANBang:    AlphaNum | Bang;
fragment AlphaNum:  [a-zA-Z0-9];
fragment Bang:  '!';

WS    : [ \t\r\n]+ -> skip ;

解析以下作品:

<<! notes, Test !>>

并且变量值为&#34; Test&#34;但是,当我消除DELIMITER_OPEN和NOTES之间的空格时,解析器失败:

<<!notes, Test !>>
  

第1行:3个不匹配的输入&#39;注释&#39;期待NOTES

1 个答案:

答案 0 :(得分:2)

这是另一个错误订购词法规则的案例。

当词法分析器扫描下一个标记时,它首先尝试查找与最长标记匹配的规则。如果多个规则匹配,则会通过按定义顺序选择 first 来消除歧义。

<<! notes, Test !>>将被标记为:
DELIMITER_OPEN NOTES COMMA VAR_VALUE WS DELIMITER_CLOSE

这是因为NOTES规则可以匹配以下内容:

<<! notes, Test !>>
   \____/

哪个包含空白。如果你删除它:

<<!notes, Test !>>

然后NOTESVAR_VALUE规则都可以匹配文字notes,并且VAR_VALUE在语法中定义为 first ,所以它优先。标记化是:
DELIMITER_OPEN VAR_VALUE COMMA VAR_VALUE WS DELIMITER_CLOSE
并且它与您的expr规则不符。

更改此规则以解决问题:

NOTES:  'notes';
VAR_VALUE:  ANBang+;

WS*添加到其他规则并没有多大意义,因为跳过了WS。并且将令牌声明为具有可能的零宽度*也没有意义,因此请改用+。最后,重新排序规则,以便最具体的规则匹配拳头。

这样,notes成为语法中的关键字。如果您不希望它成为关键字,请完全删除NOTES规则,并将VAR_VALUE规则与谓词一起使用。或者,您可以使用词法分析器模式。