使用antlr 4实现多种类型的日期识别

Multiple types of date recognition using antlr 4

我想解析以下类型的日期:

这是我的语法:

date: formal_date|explicit_date|EOF;

formal_date:
     INT SEPARATOR month SEPARATOR INT
    | INT SEPARATOR month SEPARATOR INT4
    | INT SEPARATOR INT SEPARATOR INT4;

explicit_date:
         INT TH OF month
     ;

month : JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC ;

number : FLOAT | INT | INT4 ;

// lexer rules

FLOAT : DIGIT+ '.' DIGIT+ ;

INT4 : DIGIT DIGIT DIGIT DIGIT;
INT : DIGIT+;

JAN : [Jj][Aa][Nn] ;
FEB : [Ff][Ee][Bb] ;
MAR : [Mm][Aa][Rr] ;
APR : [Aa][Pp][Rr] ;
MAY : [Mm][Aa][Yy] ;
JUN : [Jj][Uu][Nn] ;
JUL : [Jj][Uu][Ll] ;
AUG : [Aa][Uu][Gg] ;
SEP : [Ss][Ee][Pp] ;
OCT : [Oo][Cc][Tt] ;
NOV : [Nn][Oo][Vv] ;
DEC : [Dd][Ee][Cc] ;

SEPARATOR : [/\\-] ;

ON : [Oo][Nn] ;
TH : [Tt][Hh] ;
OF : [Oo][Ff] ;

fragment DIGIT : [0-9];

这些是 antlr 的输出:

Parsing: 15/apr/2016
Tree: (date (formal_date 15 / (month apr) / 2016))

Parsing: 15th of apr
Tree: (date (explicit_date 15 th of (month apr)))

但是如果我将 birthday on 15th of apr 这样的句子传递给 antlr,它会解析错误的树:

Parsing : birthday on 15th of apr
Tree: (date th on 15 th of apr)

那么有什么办法可以解决这个问题吗?例如跳过 birthday 中的 th

这是按您希望的方式工作的语法(抱歉,我写评论时没有时间写答案)

grammar testDate;

date: formal_date|explicit_date|EOF;

formal_date:
     INT SEPARATOR month SEPARATOR INT
    | INT SEPARATOR month SEPARATOR INT4
    | INT SEPARATOR INT SEPARATOR INT4;

explicit_date:
         INT TH OF month
     ;

month : JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC ;

number : FLOAT | INT | INT4 ;

// lexer rules

FLOAT : DIGIT+ '.' DIGIT+ ;

INT4 : DIGIT DIGIT DIGIT DIGIT;
INT : DIGIT+;

JAN : [Jj][Aa][Nn] ;
FEB : [Ff][Ee][Bb] ;
MAR : [Mm][Aa][Rr] ;
APR : [Aa][Pp][Rr] ;
MAY : [Mm][Aa][Yy] ;
JUN : [Jj][Uu][Nn] ;
JUL : [Jj][Uu][Ll] ;
AUG : [Aa][Uu][Gg] ;
SEP : [Ss][Ee][Pp] ;
OCT : [Oo][Cc][Tt] ;
NOV : [Nn][Oo][Vv] ;
DEC : [Dd][Ee][Cc] ;

SEPARATOR : [/\\-] ;

//ON : [Oo][Nn];
TH : [Tt][Hh]' ' ;
ND : [Nn][Dd]' ' ;
RD : [Rr][Dd]' ' ;
OF : [Oo][Ff]' ';

fragment REST : [A-Za-z \n\t\r];
REST_L : REST+? -> skip;

fragment DIGIT : [0-9];

当然可能会缺少一些东西,这取决于你想如何扩展和扩展。很少解释

  • lexer 规则 REST_L 最后有 +? 用于匹配,这是 非贪婪运算符
  • token ON 被删除(注释掉),因为你没有在 任何解析器规则
  • 为令牌 th,nd,rd,of 添加了一个 space - 这只是我有时用来获取所需内容的一个技巧。 (实现这一点的正确方法是使用词法分析器模式,当我们知道它是日期的一部分时我们将使用模式,而当它不是日期的一部分时我们将使用模式)

因此,对于输入 birthday on 15th of apr,您会得到以下解析树: