【问题标题】:ANTLR4 lexer rules don't work as expectedANTLR4 词法分析器规则无法按预期工作
【发布时间】:2017-12-24 16:48:27
【问题描述】:

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

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

“hello”和“ever”字面量仅用于调试。

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

例如: 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';

有人可以帮忙吗???

谢谢!!

【问题讨论】:

标签: antlr4


【解决方案1】:

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

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

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

timeYear
 : TimeDate TimeDate?
 ;

【讨论】:

    猜你喜欢
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    相关资源
    最近更新 更多