我想匹配表单::
的输入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匹配。
如何修复上述情况?
答案 0 :(得分:4)
ANTLR4 根据词法规则的编写顺序匹配词法规则。
'michael'
与规则COMMITHASH : [a-z0-9]+ ;
之前出现的规则AUTHORNAME
匹配,因此您遇到错误。
我可以考虑以下选项来解决您面临的问题:
您可以在ANTLR中使用'mode'
功能:在ANTLR 4中,一次激活一个词法分析器模式,该模式规则中最长的non-fragment lexer rule
将确定创建哪个令牌。您的语法仅包含默认模式,因此所有词法分析器规则都是活动的,因此“michael”与COMMITHASH
匹配,因为匹配的令牌长度与COMMITHASH
和AUTHORNAME
相同但是COMMITHASH
出现在AUTHORNAME
语法之前。
您可以通过改变它们在语法中出现的方式来改变词法规则。假设您的COMMITHASH
规则始终具有与之匹配的数字。按以下方式将AUTHORNAME
放在COMMITHASH
之前:
grammar commit;
...
AUTHORNAME : [a-zA-Z]+;
COMMITHASH : [a-z0-9]+;
...
注意:我强烈认为你的词法分析器规则不清晰。您确定COMMITHASH
规则应该是[a-z0-9]+;
这意味着'abhdks'
这样的令牌也会与您的COMMITHASH
规则匹配。但这完全是一个不同的问题。