3

我想匹配表单的输入::

commit a1b2c3
Author: Michael <michael@test.com>

commit d3g4
Author: David <david@test.com> 

这是我写的语法:

grammar commit;

file : commitinfo+;

commitinfo : commitdesc authordesc;
commitdesc : 'commit' COMMITHASH NEWLINE;
authordesc : 'Author:' AUTHORNAME '<' EMAIL '>' NEWLINE;

COMMITHASH : [a-z0-9]+;
AUTHORNAME : [a-zA-Z]+;
EMAIL      : [a-zA-Z0-9.@]+;
NEWLINE    : '\r'?'\n';
WHITESPACE : [ \t]->skip;

上述解析器的问题在于,对于上述输入,它完全匹配。但是当输入变为:

commit c1d2
Author: michael <michael@test.com>

它会引发如下错误:

第 2:8 行不匹配的输入“michael”需要 AUTHORNAME。

当我打印标记时,字符串“michael”似乎与标记 COMMITHASH 而不是 AUTHORNAME 匹配。

如何解决上述情况?

4

1 回答 1

4

ANTLR4根据它们被写入的顺序匹配词法分析器规则。

'michael'COMMITHASH : [a-z0-9]+ ;与出现在规则之前的规则匹配AUTHORNAME,因此您遇到错误。

我可以考虑以下选项来解决您面临的问题:

  • 您可以在 ANTLR 中使用该'mode'功能:在 ANTLR 4 中,一次激活一个词法分析器模式,non-fragment lexer rule该模式规则中最长的一个将确定创建哪个令牌。您的语法仅包含默认模式,因此所有词法分析器规则都处于活动状态,因此 'michael' 匹配到COMMITHASH,因为匹配的标记长度相同COMMITHASHAUTHORNAMECOMMITHASH出现AUTHORNAME在语法中。

  • 你可以通过改变它们在语法中出现的方式来改变你的词汇规则。假设您的COMMITHASH规则总是有一个与之匹配的数字。按以下方式放在AUTHORNAME前面:COMMITHASH

    grammar commit;
    ...
    
    AUTHORNAME : [a-zA-Z]+;
    COMMITHASH : [a-z0-9]+;
    ...
    

注意:我强烈认为您的词法分析器规则写得不清晰。你确定你的COMMITHASH规则应该是[a-z0-9]+;这意味着一个令牌'abhdks'也会被你的COMMITHASH规则匹配。但这完全是一个不同的问题。

于 2013-07-18T19:36:10.933 回答