ANTLR4:输入不匹配

ANTLR4:输入不匹配,antlr4,Antlr4,我想匹配表单的输入:: commit a1b2c3 Author: Michael <michael@test.com> commit d3g4 Author: David <david@test.com> 提交a1b2c3 作者:迈克尔 提交d3g4 作者:大卫 以下是我写的语法: grammar commit; file : commitinfo+; commitinfo : commitdesc authordesc; commitdesc : 'com

我想匹配表单的输入::

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

commit d3g4
Author: David <david@test.com> 
提交a1b2c3
作者:迈克尔
提交d3g4
作者:大卫
以下是我写的语法:

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;
语法提交;
文件:commitinfo+;
committenfo:commitdesc authordesc;
commitdesc:“commit”COMMITHASH NEWLINE;
authordesc:'Author:'AUTHORNAME'换行符;
委员会:[a-z0-9]+;
作者名称:[a-zA-Z]+;
电子邮件:[a-zA-Z0-9@]+;
换行符:'\r'?'\n';
空白:[\t]->跳过;
上述解析器的问题在于,对于上述输入,它完全匹配。但当输入更改为:

commit c1d2
Author: michael <michael@test.com>
commit c1d2
作者:迈克尔
它会抛出如下错误:

第2行:8不匹配的输入“michael”应为AUTHORNAME

当我打印令牌时,字符串“michael”似乎由令牌COMMITHASH而不是AUTHORNAME匹配


如何修复上述情况?

ANTLR4根据编写的顺序匹配lexer规则

'michael'
被规则
COMMITHASH:[a-z0-9]+匹配出现在规则
AUTHORNAME
之前,因此您出现了错误

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

  • 您可以在ANTLR中使用
    'mode'
    功能:在ANTLR 4中,一次激活一个lexer模式,该模式规则中最长的
    非片段lexer规则将确定创建了哪个令牌。您的语法仅包括默认模式,因此所有词法规则都处于活动状态,因此“michael”将匹配到
    COMMITHASH
    ,因为匹配的标记长度与
    COMMITHASH
    AUTHORNAME
    相同,但
    COMMITHASH
    在语法中出现在
    AUTHORNAME
    之前

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

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

注意:我强烈地感觉到你的lexer规则写得不清晰。您确定您的
COMMITHASH
规则应该是
[a-z0-9]+
这意味着像
'abhdks'
这样的令牌也将被您的
COMMITHASH
规则匹配。但这是一个完全不同的问题