使用antlr 4实现多种类型的日期识别
Multiple types of date recognition using antlr 4
我想解析以下类型的日期:
- 15/apr/2016
- 4 月 15 日
这是我的语法:
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
,您会得到以下解析树:
我想解析以下类型的日期:
- 15/apr/2016
- 4 月 15 日
这是我的语法:
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
,您会得到以下解析树: