Antlr lexer匹配意外规则

Antlr lexer匹配意外规则,antlr,grammar,antlr4,Antlr,Grammar,Antlr4,我正在学习一些基本的Antlr,并尝试编写语法来生成todo项: Meeting at 12pm for 20 minutes 我遇到的问题是,根据使用的上下文,三个lexer规则尤其“不匹配”: HOUR: [0-9]|'1'[0-9]|'2'[0-3]; MINUTE: [0-5][0-9]; NONZERO_NUMBER: [1-9][0-9]*; 在某些情况下,我希望12匹配HOUR规则,而在其他情况下,我希望它匹配MINUTE,等等,但解析器规则似乎无法影响词法器的上下文敏感性 例

我正在学习一些基本的Antlr,并尝试编写语法来生成todo项:

Meeting at 12pm for 20 minutes
我遇到的问题是,根据使用的上下文,三个lexer规则尤其“不匹配”:

HOUR: [0-9]|'1'[0-9]|'2'[0-3];
MINUTE: [0-5][0-9];
NONZERO_NUMBER: [1-9][0-9]*;
在某些情况下,我希望
12
匹配
HOUR
规则,而在其他情况下,我希望它匹配
MINUTE
,等等,但解析器规则似乎无法影响词法器的上下文敏感性

例如,上面的字符串(
readbooks…
)不进行解析,因为当
12
作为
HOUR
匹配时,
20
也是如此,而解析器期望
非零编号
因此失败

line 1:20 mismatched input '20' expecting NONZERO_NUMBER
如果我故意将持续时间值更改为而不匹配
小时
规则,则可以:

Meeting at 12pm for 120 minutes // Note 120 minutes doesn't match HOUR or MINUTE
在尝试其他/更早的规则之前,有没有办法“说服”词法分析器尝试匹配预期的标记(如为解析器定义的)

以下是我的完整语法:

旁注:我意识到还有其他奇怪之处,比如事件名称只能是一个单词,但我一次只解决一个问题


试图在lexer中完成解析器的工作通常是错误的。如果lexer只识别整数,那么解析器将不会对如何解释数字产生任何问题。您可以在动作或谓词中拒绝8:63这样的时间

在尝试其他/更早的规则之前,有没有办法“说服”词法分析器尝试匹配预期的标记(如为解析器定义的)

不,您无法说服lexer匹配期望的标记,因为lexer没有任何期望(形式上,它在常规语法上运行,而解析器在上下文无关语法上运行)。lexer和解析器独立运行*,理论上,您可以先运行lexer而不使用任何解析器,然后在lexer输出上启动解析器


*在ANTLR 3中有一个例外,我无法确定ANTLR 4是否也是如此——ANTLR 3解析器和lexer共享一个
org.ANTLR.runtime.RecognizerSharedState
实例。然而,使用它来影响lexer如何匹配标记仍然是有风险的,因为您无法直接控制lexer何时标记特定的输入(即,它可以根据一些解析器规则进行前瞻,并在您在解析器中访问输入并尝试影响它之前标记输入)

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;