我正在重新学习一些基本的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
如果我将持续时间值更改为有意不匹配HOUR
规则,就可以了:
Meeting at 12pm for 120 minutes // Note 120 minutes doesn't match HOUR or MINUTE
在尝试其他/较早的规则之前,是否有任何方法可以“说服”词法分析器来尝试匹配 expected 标记(为解析器定义)?
为清楚起见,这是我的完整语法:
旁注:我意识到还有其他奇怪之处,例如事件名称只能是一个单词,但是我一次要解决一个问题。
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;
答案 0 :(得分:3)
尝试在词法分析器中执行解析器的工作通常是一个错误。如果词法分析器仅识别整数,则解析器将毫无问题地整理出如何解释数字。您可以在动作或谓词中拒绝类似8:63的时间。
答案 1 :(得分:0)
在尝试其他/较早的规则之前,是否有任何方法可以“说服”词法分析器来尝试匹配 expected 标记(为解析器定义)?
不,您不能说服lexer匹配期望的令牌,因为lexer没有任何期望(通常,它对常规语法进行操作,而解析器对上下文无关的语法进行操作)。词法分析器和解析器独立运行 * ,理论上您可以先运行词法分析器而无需任何解析器,然后再在词法分析器输出上启动解析器。
*在ANTLR 3中有一个例外,我也找不到对ANTLR 4是否适用-ANTLR 3解析器和词法分析器共享一个org.antlr.runtime.RecognizerSharedState
实例。但是,使用此方法影响词法分析器与令牌的匹配方式仍会存在风险,因为您无法直接控制词法分析器何时对特定输入进行标记化(即,由于某些解析器规则,它可以进行前瞻性处理,并在获得输入之前对输入进行标记化并在解析器中对其进行尝试,并尝试对其进行影响。)