如何创建一个解析日期的antlr4语法

时间:2016-02-26 12:17:21

标签: antlr4

我想使用以下ANTLR4语法解析一些日期格式。

grammar Variables;
//varTable : tableNameFormat dateFormat? ;
//tableNameFormat: (ID SEPERATOR);
dateFormat : YEAR UNDERSCORE MONTH UNDERSCORE TODAY
       | YEAR
       ;
YEAR : DIGIT DIGIT DIGIT DIGIT;                         // 4-digits YYYY
MONTH : DIGIT DIGIT;                                    // 2-digits MM
TODAY : DIGIT DIGIT ;                                     // 2-digits DD
UNDERSCORE: ('_' | '-' );
fragment
DIGIT : [0-9] ;
ID : [a-zA-Z][a-zA-Z0-9]? ;
WS  : [ \t\r\n]+ -> skip ;

这个语法应该很容易解析“2016-01-01”,但是输入不匹配。请帮忙

3 个答案:

答案 0 :(得分:1)

对于这样的任务,正则表达式是更好的解决方案。但如果你把它作为一个研究项目,那么它就是......

重要的是要意识到词法规则的顺序至关重要。输入将通过这些规则进行测试,并将使用第一个适用的规则。应该从最具体的规则编写规则以避免冲突。例如,如果您的语法具有变量名称和一些关键字,则应首先使用关键字,否则它们将被标记为变量。

有很多方法可以解决这个问题,但最好的方法是一个名为DATE的词法规则:NUM NUM NUM NUM' - 'NUM NUM' - 'NUM NUM;你有它们的月和日规则不会工作,因为它们是暧昧的。 lexer如何判断两个数字输入是月还是日?

答案 1 :(得分:1)

就我而言,它有效。我正在使用输入获得正确的parsetree:2016-01-01

grammar date;

dateFormat : year UNDERSCORE month UNDERSCORE today
       | year
       ;

year : DIGIT DIGIT DIGIT DIGIT
     ;

month : DIGIT DIGIT
      ;

today : DIGIT DIGIT 
      ;

UNDERSCORE: ('_' | '-' );
DIGIT : [0-9] ;

但我会使用month之类的(0 [1-9] | 1 [0-2]),因为只有12个月。

答案 2 :(得分:0)

我以前从未在Antlr上工作过,但是当我在GitHub上查看是否有人已经做了我想要的工作时。找到了这个库。

这是一个用于从String解析日期的库。

https://github.com/masasdani/nangka

将此项目添加为您项目的依赖项

   <dependency>
        <groupId>com.masasdani</groupId>
        <artifactId>nangka</artifactId>
        <version>0.0.6</version>
    </dependency>

样品用量:

  String exprEn = "a month later, 20-11-90";
    Nangka nangka = new Nangka();
    DateUnit dateUnit = nangka.parse(exprEn);
    for(Date date : dateUnit.getRelatedDates()){
        System.out.println(date);
    }

希望这可以帮助像我这样正在搜索的人。