Antlr 词法分析器匹配意外规则
Antlr lexer matching unintended rule
我正在重新学习一些基本的 Antlr 并尝试编写语法来生成待办事项:
Meeting at 12pm for 20 minutes
我遇到的问题是三个词法分析器规则特别 "mismatched" 取决于它们使用的上下文:
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
在尝试 other/earlier 规则之前,"convince" 词法分析器是否可以尝试匹配 预期的 标记(为解析器定义)?
为清楚起见,这是我的完整语法:
旁注:我意识到还有其他奇怪的地方,比如事件名称只能是一个单词,但我一次处理一个问题。
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;
试图在词法分析器中完成解析器的工作通常是错误的。如果词法分析器只识别整数,那么解析器将毫无问题地找出如何解释数字。您可以在动作或谓词中拒绝像 8:63 这样的时间。
Is there any way to "convince" the lexer to try to match the expected token (as defined for the parser) before trying other/earlier rules?
不,您无法说服词法分析器匹配预期的标记,因为词法分析器没有任何预期(形式上,它对常规文法进行操作,而解析器对上下文无关文法进行操作)。词法分析器和解析器独立运行*,理论上你可以先运行词法分析器而不用任何分析器,然后才在词法分析器输出上启动分析器。
* 在 ANTLR 3 中有一个例外,我无法确定这是否也适用于 ANTLR 4 - ANTLR 3 解析器和词法分析器共享一个 org.antlr.runtime.RecognizerSharedState
实例。然而,使用它来影响词法分析器如何匹配标记仍然是有风险的,因为您无法直接控制词法分析器何时标记特定输入(即它可以根据某些解析器规则进行前瞻并在您获得之前标记输入在解析器中加入它并尝试影响它)。
我正在重新学习一些基本的 Antlr 并尝试编写语法来生成待办事项:
Meeting at 12pm for 20 minutes
我遇到的问题是三个词法分析器规则特别 "mismatched" 取决于它们使用的上下文:
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
在尝试 other/earlier 规则之前,"convince" 词法分析器是否可以尝试匹配 预期的 标记(为解析器定义)?
为清楚起见,这是我的完整语法:
旁注:我意识到还有其他奇怪的地方,比如事件名称只能是一个单词,但我一次处理一个问题。
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;
试图在词法分析器中完成解析器的工作通常是错误的。如果词法分析器只识别整数,那么解析器将毫无问题地找出如何解释数字。您可以在动作或谓词中拒绝像 8:63 这样的时间。
Is there any way to "convince" the lexer to try to match the expected token (as defined for the parser) before trying other/earlier rules?
不,您无法说服词法分析器匹配预期的标记,因为词法分析器没有任何预期(形式上,它对常规文法进行操作,而解析器对上下文无关文法进行操作)。词法分析器和解析器独立运行*,理论上你可以先运行词法分析器而不用任何分析器,然后才在词法分析器输出上启动分析器。
* 在 ANTLR 3 中有一个例外,我无法确定这是否也适用于 ANTLR 4 - ANTLR 3 解析器和词法分析器共享一个 org.antlr.runtime.RecognizerSharedState
实例。然而,使用它来影响词法分析器如何匹配标记仍然是有风险的,因为您无法直接控制词法分析器何时标记特定输入(即它可以根据某些解析器规则进行前瞻并在您获得之前标记输入在解析器中加入它并尝试影响它)。