ANTLR4词法分析器规则不能按预期工作

时间:2014-12-18 08:18:27

标签: antlr4

我想写一个关于月份和年份的词法规则,规则是(带正则表达式):

"hello"[0-9]{1,2}"ever"([0-9]{2}([0-9]{2})?)?

“你好”和“永远”的文字只是用于调试。

就是说,一个月的一个或两个数字,一年的两个或四个数字。更重要的是,年份部分可以绕过。

如下:  2015年8月 - > hello08ever2015或hello8ever2015或hello8ever15或hello8ever或hello08ever;  2015年10月 - > hello10ever2015或hello10ever15或hello10ever;

我的词法分析器规则如下(ANTLR4):

grammar Hello;
r  : 'hello' TimeDate 'ever' TimeYear? ;        

TimeDate : Digit Digit?;

TimeYear : TwoDigit TwoDigit?;

TwoDigit : Digit Digit;

Digit : [0-9] ;             

WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines

但似乎没有用。 这是我测试的一些日志:

C:\antlr\workspace\demo>java org.antlr.v4.runtime.misc.TestRig Hello r -tree -gui
hello20ever2014
^Z
(r hello 20 ever 2014)

C:\antlr\workspace\demo>grun Hello r -tree -gui

C:\antlr\workspace\demo>java org.antlr.v4.runtime.misc.TestRig Hello r -tree -gui
hello2ever20
^Z
(r hello 2 ever)

C:\antlr\workspace\demo>grun Hello r -tree -gui

C:\antlr\workspace\demo>java org.antlr.v4.runtime.misc.TestRig Hello r -tree -gui
hello20ever14
^Z
(r hello 20 ever)

C:\antlr\workspace\demo>grun Hello r -tree -gui

C:\antlr\workspace\demo>java org.antlr.v4.runtime.misc.TestRig Hello r -tree -gui
hello2ever2014
^Z
(r hello 2 ever 2014)

输入:hello2ever20,它无法识别年份'20'; 输入:hello20ever14,它无法识别年份'14';

任何人都可以帮忙吗???

谢谢!

1 个答案:

答案 0 :(得分:3)

你必须意识到ANTLR的词法分析器规则是根据它们在语法文件中的位置进行匹配的。词法分析者不会"听"解析器可能需要在解析器规则中的某个位置。词法分析器尝试匹配尽可能多的字符,当2(或更多)规则匹配相同数量的字符时,首先定义的规则将获胜。

在您的情况下,这意味着15始终会被标记为TimeDate,而不会TimeYear,因为这两个规则都匹配15,但TimeDate是首先定义。 2015将被标记为TimeYear,因为没有其他规则匹配4位数。

解决方案是将TimeYear更改为解析器规则:

timeYear
 : TimeDate TimeDate?
 ;