如何用ANTLR4解析‘Leg 1: Jun 25’?语法报错求助
ANTLR4解析失败问题解决
问题场景
刚入门ANTLR4,编写自定义语法解析输入文本Leg 1: Jun 25,语法规则如下:
fragment DIGIT : [0-9]; fragment MONTH : [A-Z][a-z][a-z]; DATE : MONTH ' ' DIGIT+; LEG_NUMBER : DIGIT+; leg : 'Leg ' LEG_NUMBER ': ' DATE;
解析时报错:
line 1:0 mismatched input 'Leg 1' expecting 'Leg '
问题原因
核心原因是词法规则的贪婪匹配特性:
你的MONTH规则定义为[A-Z][a-z][a-z],会匹配任何首字母大写、后两个字母小写的三字母单词——包括输入中的Leg。而DATE规则是MONTH ' ' DIGIT+,因此整个Leg 1会被词法分析器识别为一个DATE token,而非拆分为'Leg '和LEG_NUMBER。
语法规则leg期望以'Leg ' token开头,但实际输入的Leg 1被识别为DATE token,因此出现匹配错误。
解决方法
方法1:限制MONTH为实际月份缩写
将通用的MONTH规则替换为具体的月份缩写列表,避免匹配到非月份的三字母单词:
fragment DIGIT : [0-9]; // 仅匹配实际月份缩写 fragment MONTH : 'Jan' | 'Feb' | 'Mar' | 'Apr' | 'May' | 'Jun' | 'Jul' | 'Aug' | 'Sep' | 'Oct' | 'Nov' | 'Dec'; DATE : MONTH ' ' DIGIT+; LEG_NUMBER : DIGIT+; leg : 'Leg ' LEG_NUMBER ': ' DATE;
方法2:添加空格忽略规则(更健壮)
额外定义WS规则跳过空格、制表符等空白字符,同时调整语法规则去掉字面量中的空格,让解析器自动处理任意数量的空白:
fragment DIGIT : [0-9]; fragment MONTH : 'Jan' | 'Feb' | 'Mar' | 'Apr' | 'May' | 'Jun' | 'Jul' | 'Aug' | 'Sep' | 'Oct' | 'Nov' | 'Dec'; DATE : MONTH WS DIGIT+; LEG_NUMBER : DIGIT+; // 忽略所有空白字符 WS : [ \t\r\n]+ -> skip; leg : 'Leg' LEG_NUMBER ':' DATE;
这样修改后,输入Leg 1: Jun 25就能被正确解析,Leg会被识别为字面量,1匹配LEG_NUMBER,Jun 25匹配DATE。
内容的提问来源于stack exchange,提问作者Baptiste Pernet
相关产品推荐
相关产品推荐

