Parsing 条件词法分析器
我有以下ANTLR语法Parsing 条件词法分析器,parsing,antlr,antlr4,grammar,lexer,Parsing,Antlr,Antlr4,Grammar,Lexer,我有以下ANTLR语法 relation : IDENTIFIER EQUAL relative_date ; relative_date : K_NOW (PLUS | MINUS) NUMERIC_LITERAL TIME_UNIT ; IDENTIFIER : //'"' (~'"' | '""')* '"' '`' (~'`' | '``')* '`' | '[' ~']'* ']' | [a-zA-Z_] [a-zA
relation
: IDENTIFIER EQUAL relative_date
;
relative_date
: K_NOW (PLUS | MINUS) NUMERIC_LITERAL TIME_UNIT
;
IDENTIFIER
: //'"' (~'"' | '""')* '"'
'`' (~'`' | '``')* '`'
| '[' ~']'* ']'
| [a-zA-Z_] [a-zA-Z_.0-9]*
;
TIME_UNIT
: ('h'|'m'|'s'|'d'|'w'|'M'|'y'|'q')
;
PLUS : '+';
MINUS : '-';
EQUAL: '=';
K_NOW : N O W;
NUMERIC_LITERAL
: [0-9]+ ;
如果我将时间单位
放在标识符
解析器之前
有效something=now-5d
不起作用,开始出现故障d=now-5d
,并表示需要d
标识符
时间单位
放在标识符
解析器之后
在第二个something=now-5d
时失败,并表示需要时间单位d
在第二次d=now-5d
时失败,并表示需要时间单位d
有人能帮我改变语法,使之在两种情况下都适用吗?例如,当它是相对日期时,使用
时间单位
lexer,否则标识符
lexer您可以将数字时间单位
更改为一个lexer规则持续时间
,并自己解析持续时间
relative_date
: K_NOW (PLUS | MINUS) DURATION
;
DURATION
: [0-9]+ SPACE* ('h'|'m'|'s'|'d'|'w'|'M'|'y'|'q')
;
SPACE
: [ \u000B\t\r\n]
;
ANTLR的lexer试图匹配尽可能多的字符。当两个或多个lexer规则匹配相同数量的字符时,第一个定义的规则“获胜” 因此,输入的
d
既匹配时间单位
又匹配标识符
,但由于首先定义了标识符
,因此它获胜。换句话说:规则时间单位
永远不会匹配
解决方案,将时间单位
置于标识符
之前:
TIME_UNIT
: ('h'|'m'|'s'|'d'|'w'|'M'|'y'|'q')
;
K_NOW
: N O W
;
IDENTIFIER
: //'"' (~'"' | '""')* '"'
'`' (~'`' | '``')* '`'
| '[' ~']'* ']'
| [a-zA-Z_] [a-zA-Z_.0-9]*
;
relation
: identifier EQUAL relative_date
;
(请注意,K_NOW
还需要放在标识符之前
!)
但是,现在输入的d
、h
、m
等将永远不会成为标识符,因为它们现在将始终成为时间单位
。你不能改变这一点,这就是ANTLR的lexer的工作原理。您可以在解析器中这样处理:
identifier
: IDENTIFIER
| TIME_UNIT
;
TIME_UNIT
: ('h'|'m'|'s'|'d'|'w'|'M'|'y'|'q')
;
IDENTIFIER
: //'"' (~'"' | '""')* '"'
'`' (~'`' | '``')* '`'
| '[' ~']'* ']'
| [a-zA-Z_] [a-zA-Z_.0-9]*
;
然后在解析器规则中使用规则标识符
,而不是标识符
:
TIME_UNIT
: ('h'|'m'|'s'|'d'|'w'|'M'|'y'|'q')
;
K_NOW
: N O W
;
IDENTIFIER
: //'"' (~'"' | '""')* '"'
'`' (~'`' | '``')* '`'
| '[' ~']'* ']'
| [a-zA-Z_] [a-zA-Z_.0-9]*
;
relation
: identifier EQUAL relative_date
;
这将导致123456789 hi
标记为123456789 h
(持续时间)和i
(标识符)。很可能不是Richa想要的…@BartKiers事实上不,这对我来说很有效。我在I
处得到了一个错误节点,看起来很正常。我有什么事吗missing@Richa您可能还没有重新生成lexer和解析器。就如我刚才解释的那样。检查此代码:否则会有更多您尚未显示的冲突规则。无论如何,我不会同意这里描述的建议。是的@BartKiers你是对的。我没有将整个语法文件粘贴到这里,只是为了避免问题中的噪音,我正在努力解决的部分。@Richa我对K\u NOW
标记做了一个小编辑。非常感谢。我将尝试在我的代码中实现这一点