ANTLR解析器无法识别完整指令行,匹配首个单词后停止
问题分析
你的解析器报错核心原因是混淆了ANTLR的词法规则与解析器规则,同时错误地将多token组成的语法结构定义为词法规则,导致解析器无法正确识别带操作数的指令:
- ANTLR规定:大写开头的是词法规则(仅匹配单个token的字符序列),小写开头的是解析器规则(组合多个词法token形成语法结构)。
- 原语法中
Label、Operand、Operands被错误定义为词法规则,但它们是由多个token组成的语法结构(比如Label是Word+:),无法被词法分析器正确处理。 - 由于
Operand作为词法规则永远不会被触发(优先级低于更早定义的Register、Word等规则),解析器无法匹配Mnemonic后的操作数,将操作数视为多余输入。
修正后的语法
grammar Assembly8085; fragment Digit: [0-9]; fragment HexDigit: [0-9a-fA-F]; fragment Letter: [a-zA-Z_]; // 词法规则(大写开头) Nl: [\n]+ -> skip; Comment: ';' ~[\n]* -> channel(HIDDEN); Ws: [ \t]+ -> skip; Comma: Ws? ',' Ws?; Memory: HexDigit HexDigit HexDigit HexDigit 'H'; Decimal: Digit+; Hexadecimal: HexDigit+ 'H'; Mnemonic: 'MVI' | 'INR' | 'JMP' | 'HLT'; Register: 'A' | 'B' | 'C' | 'D' | 'E' | 'H' | 'L' ; Directive: 'ORG' | 'DB' | 'DS' | 'EQU' | 'END'; Word: Letter (Letter | Digit)*; // 解析器规则(小写开头) program: line* EOF; line: label? instruction? Comment?; instruction: (Mnemonic operands?) | Directive; label: Word ':'; operands: operand (Comma operand)*; operand : Register | Decimal | Hexadecimal | Memory | Word;
关键修改说明
- 规则类型修正:
- 将
Label改为解析器规则label,匹配Word+:的token组合。 - 将
Operand、Operands改为解析器规则operand、operands,用来组合不同类型的词法token作为指令操作数。
- 将
- 优化行规则:
- 修改
line规则为label? instruction? Comment?,允许仅包含标签和注释的空指令行(适配你的测试输入第一行)。
- 修改
- 简化换行处理:
- 由于
Nl已设置为skip,program规则直接用line*即可,无需保留Nl?。
- 由于
测试验证
修正后,你的测试输入:
Start: ;comment line HLT INR A JMP Loop Loop: END
会被正确解析:
INR A→Mnemonic(INR)+operands(operand(Register(A)))JMP Loop→Mnemonic(JMP)+operands(operand(Word(Loop)))- 所有报错将消失。
内容的提问来源于stack exchange,提问作者Jaimin Vashi




