添加main_symbol选项后ANTLR解析器出现意外匹配失败问题
问题成因
这个问题是ANTLR词法分析的优先级规则导致的,核心逻辑如下:
- ANTLR的词法分析器会优先匹配最长的可识别字符串;
- 相同长度的匹配项中,语法规则里直接写的字符串字面量对应的隐式词法规则,优先级高于所有你显式定义的词法规则(比如你文法里的
LETTER、WS等规则)。
你原来的文法中,main_symbol的字面量只有ж、жо,对应的隐式规则只会匹配ж开头的内容,输入1、2里headword部分的м、а、р等字符没有对应的隐式规则,会被正常识别为LETTER,所以headword规则可以正常匹配。
当你在main_symbol里新增м选项后,相当于新增了一条优先级高于LETTER的隐式词法规则,专门匹配单个字符м。此时输入1、2中headword的首字符м会被词法分析器优先识别为м对应的隐式记号,而不是LETTER。但你的headword规则要求第一个元素必须是LETTER,匹配逻辑直接失败,导致原本正常的输入无法解析。
解决方案
可以通过以下两种方式修复该问题:
方案1:将headword定义为独立词法规则
把headword的匹配逻辑从语法规则移到词法规则,放在所有规则最前面,保证它的优先级最高,会优先匹配连续的headword字符串,不会被拆成单个字符的隐式记号:
grammar Hello; // 放在最前面,优先级最高 HEADWORD : LETTER (LETTER | STRESS_MARK | '-')* ; entry : HEADWORD WS definition EOF ; definition : main_symbol WS index_number index_letter ; main_symbol : 'жо' | 'ж' | 'м' ; // 其余原有规则不变 index_number : '1' ; index_letter : 'a' | 'b' | 'c' | 'd' | 'e' | 'f' ; WS : [ \t] ; LETTER : [а-яА-ЯёЁ] ; STRESS_MARK : [\u0300\u0301] ;
方案2:语义层校验main_symbol取值
不在语法规则里写单个字母的字面量,改成匹配LETTER后在语义阶段判断取值是否合法:
main_symbol : 'жо' | LETTER {List.of("ж", "м").contains($LETTER.text)}? ;
内容的提问来源于stack exchange,提问作者Sergey Slepov
相关产品推荐
相关产品推荐

