我在弄清楚如何解析语法中的日期时遇到了问题。
问题在于它与String共享它的定义,但是根据Antlr 4文档,它应该遵循优先级,通过查看声明的顺序。
这是我的语法:
grammar formula;
/* entry point */
parse: expr EOF;
expr
: value # argumentArithmeticExpr
| l=expr operator=('*'|'/'|'%') r=expr # multdivArithmeticExpr // TODO: test the % operator
| l=expr operator=('+'|'-') r=expr # addsubtArithmeticExpr
| '-' expr # minusArithmeticExpr
| FUNCTION_NAME '(' (expr ( ',' expr )* ) ? ')'# functionExpr
| '(' expr ')' # parensArithmeticExpr
;
value
: number
| variable
| date
| string
| bool;
/* Atomes */
bool
: BOOL
;
variable
: '[' (~(']') | ' ')* ']'
;
date
: DQUOTE date_format DQUOTE
| QUOTE date_format QUOTE
;
date_format
: year=INT '-' month=INT '-' day=INT (hour=INT ':' minutes=INT ':' seconds=INT)?
;
string
: STRING_LITERAL
;
number
: ('+'|'-')? NUMERIC_LITERAL
;
/* lexemes de base */
QUOTE : '\'';
DQUOTE : '"';
MINUS : '-';
COLON : ':';
DOT : '.';
PIPE : '|';
BOOL : T R U E | F A L S E;
FUNCTION_NAME: IDENTIFIER ;
IDENTIFIER
: [a-zA-Z_] [a-zA-Z_0-9]* // TODO: do we more chars in this set?
;
NUMERIC_LITERAL
: DIGIT+ ( '.' DIGIT* )? ( E [-+]? DIGIT+ )? // ex: 0.05e3
| '.' DIGIT+ ( E [-+]? DIGIT+ )? // ex: .05e3
;
INT: DIGIT+;
STRING_LITERAL
: '\'' ( ~'\'' | '\'\'' )* '\''
| '"' ( ~'"' | '""' )* '"'
;
WS: [ \t\n]+ -> skip;
UNEXPECTED_CHAR: . ;
fragment DIGIT: [0-9];
fragment A:('a'|'A');
fragment B:('b'|'B');
fragment C:('c'|'C');
fragment D:('d'|'D');
fragment E:('e'|'E');
fragment F:('f'|'F');
fragment G:('g'|'G');
fragment H:('h'|'H');
fragment I:('i'|'I');
fragment J:('j'|'J');
fragment K:('k'|'K');
fragment L:('l'|'L');
fragment M:('m'|'M');
fragment N:('n'|'N');
fragment O:('o'|'O');
fragment P:('p'|'P');
fragment Q:('q'|'Q');
fragment R:('r'|'R');
fragment S:('s'|'S');
fragment T:('t'|'T');
fragment U:('u'|'U');
fragment V:('v'|'V');
fragment W:('w'|'W');
fragment X:('x'|'X');
fragment Y:('y'|'Y');
fragment Z:('z'|'Z');
这里的重要部分是:
value
: number
| variable
| date
| string
| bool;
date
: DQUOTE date_format DQUOTE
| QUOTE date_format QUOTE
;
date_format
: year=INT '-' month=INT '-' day=INT (hour=INT ':' minutes=INT ':' seconds=INT)?
;
我的语法需要这些东西:
"a quoted string"
- >给出string
"2015-03 TOTOTo"
- >提供string
,因为日期格式不匹配。"2015-03-15"
- >提供date
,因为它与DQUOTE INT '-' INT '-' INT DQUOTE
我(试过?)确保解析器尝试匹配之前的日期尝试匹配字符串:value: ...| date | string| ...
。
但是当我使用grun
实用程序(以及我的单元测试...)时,我可以看到它将日期归类为字符串,就好像它从不打扰检查日期格式一样。
你能告诉我为什么会这样吗? 我怀疑我的语法规则的顺序是否存在,但是我尝试了一些排列而没有得到任何东西。
答案 0 :(得分:1)
问题源于在任何解析器规则被有效考虑之前未能理解词法分析器运行完成。
这意味着,STRING_LITERAL
词法分析器规则将使用所有字符串,包含日期,并仅输出STRING_LITERAL
个令牌。解析器甚至从不考虑date
和相关的解析器子规则。
也许最小的解决方案是将STRING_LITERAL
词法分析器规则修改为
STRING_LITERAL
: { notDateString() }?
( QUOTE .*? QUOTE
| DQUOTE .*? DQUOTE
)
;
notDateString
谓词需要本机代码才能在日期格式和其他字符串之间执行必要的消歧。
另一种方法是将STRING_LITERAL
规则完全提升为解析器。可行,但有点混乱取决于是否需要在“真实”字符串中保留空格。
顺便说一句,您可能希望在标准系列的单元测试中添加token stream dump。