ANTLR语法规则匹配异常:如何为图编号识别设置边界?
解决ANTLR图编号识别的边界问题
核心思路
要打破ANTLR最长输入匹配的影响,必须明确图编号的合法字符范围,通过语法规则严格限制编号的结束边界,避免把后续非编号字符误纳入匹配范围。
具体实现方案
1. 精准定义合法图编号规则
先明确图编号的组成逻辑:
- 主编号:纯数字(0-9)
- 子索引:仅支持三种形式——
数字+字母(如1A)、数字+.+数字(如1.1)、数字+.+字母(如3.A)
基于此在Lexer中定义Token规则:
FIGURE_LABEL: DIGIT+ ( (DOT (DIGIT | LETTER)) | LETTER )?; fragment DIGIT: [0-9]; fragment LETTER: [A-Za-z]; fragment DOT: '.';
2. 针对不同场景限制匹配边界
场景1:处理Figure 6.Regulation(编号后直接跟标题无空格)
问题根源是Lexer把6.R当成了合法编号,需要通过语义谓词区分“子索引的点”和“标题前的点”:
FIGURE_LABEL: DIGIT+ ( // 如果点后不是字母,保留点作为编号一部分 (DOT {_input.LA(1) != [A-Za-z]}?) | // 子索引场景:点后必须是数字或字母 (DOT (DIGIT | LETTER)) | // 子索引场景:数字后直接跟字母 LETTER )?;
该规则会在点后是标题起始字母时,自动终止编号匹配,仅把6.识别为编号。
场景2:处理See in Figure 2.1, 86Formula(多编号+编号后接文本)
把图引用的识别逻辑从Lexer转移到Parser,通过上下文判断边界:
// Parser规则 parser grammar FigureParser; options { tokenVocab=FigureLexer; } figureReference: 'Figure' figureLabel ('.'? caption)? | 'See in Figure' figureLabel (COMMA figureLabel)* (','? restOfText)?; figureLabel: DIGIT+ ( (DOT DIGIT) | (DOT LETTER) | LETTER )?; caption: LETTER+; restOfText: ~[,.]+; // Lexer规则 lexer grammar FigureLexer; DIGIT: [0-9]+; LETTER: [A-Za-z]+; DOT: '.'; COMMA: ','; WS: [ \t\n\r]+ -> skip; OTHER: . -> skip;
这种方式会把86识别为独立编号,Formula被归到后续文本中,避免86F被误判为编号。
关键注意事项
- 必须提前明确所有合法的图编号格式,确保规则覆盖所有子索引形式,同时排除标题相关字符。
- 优先用Parser处理上下文相关场景,比单纯依赖Lexer的Token匹配更灵活。
- 测试时要覆盖所有边缘情况:纯数字编号、带点的子索引、带字母的子索引、编号后直接跟标题、多编号分隔等。
内容的提问来源于stack exchange,提问作者Korpusova Svetlana
相关产品推荐
相关产品推荐

