我正在重新学习一些基本的Antlr并尝试编写语法来生成待办事项:
Meeting at 12pm for 20 minutes
我遇到的问题是,特别是三个词法分析器规则“不匹配”取决于它们使用的上下文:
HOUR: [0-9]|'1'[0-9]|'2'[0-3];
MINUTE: [0-5][0-9];
NONZERO_NUMBER: [1-9][0-9]*;
在某些情况下,我希望 12
匹配 HOUR
规则,有时我希望它匹配 MINUTE
等,但解析器规则似乎无法影响词法分析器对上下文敏感 .
例如,上面的字符串( Read Books...
)不解析,因为 12
匹配为 HOUR
, 20
也是如此,并且解析器期望 NONZERO_NUMBER
因此失败 .
line 1:20 mismatched input '20' expecting NONZERO_NUMBER
如果我将持续时间值更改为 intentionally not 匹配 HOUR
规则,则可以:
Meeting at 12pm for 120 minutes // Note 120 minutes doesn't match HOUR or MINUTE
在尝试其他/早期规则之前,有没有办法让词法分析器尝试匹配预期的令牌(如解析器所定义)?
为清晰起见,这是我的完整语法:
旁注:我意识到还有其他奇怪的事情,比如一个事件名称只能是一个单词,但我一次只能处理一个问题 .
grammar Sprint;
event: eventName timePhrase? durationPhrase?;
durationPhrase: 'for' duration;
timePhrase: 'at' time;
duration: (NONZERO_NUMBER MINUTE_STR) | (NONZERO_NUMBER HOUR_STR);
time: ((HOUR ':' MINUTE) | (HOUR)) AMPM?;
eventName: WORD;
MINUTE_STR: 'minute'('s')?;
HOUR_STR: 'hour'('s')?;
HOUR: [0-9]|'1'[0-9]|'2'[0-3];
MINUTE: [0-5][0-9];
NONZERO_NUMBER: [1-9][0-9]*;
AMPM: ('A'|'a'|'P'|'p')('M'|'m');
WORD: ('a'..'z' | 'A'..'Z')+;
WS: (' '|[\n\t\r]) -> skip;
2 回答
尝试在词法分析器中完成解析器的工作通常是错误的 . 如果词法分析器只识别整数,那么解析器就可以解决如何解释数字的问题 . 您可以在动作或谓词中拒绝8:63等时间 .
不,你无法说服lexer匹配预期的令牌,因为词法分析器没有任何期望(正式地,它在常规语法上运行,而解析器在无上下文语法上运行) . 词法分析器和解析器独立运行*,理论上你可以在没有任何解析器的情况下首先运行词法分析器,然后在词法分析器输出上启动解析器 .
*在ANTLR 3中有一个例外,我无法确定ANTLR 4是否也是如此 - ANTLR 3解析器和词法分析器共享一个
org.antlr.runtime.RecognizerSharedState
实例 . 然而,使用它来影响词法分析器与标记匹配的方式仍然存在风险,因为你没有直接控制词法分析器何时标记特定输入(即,由于某些解析器规则它可以做一个先行,并在你得到之前标记化输入在解析器中并试图影响它) .