You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

ANTLR解析器无法识别完整指令行,匹配首个单词后停止

问题分析

你的解析器报错核心原因是混淆了ANTLR的词法规则与解析器规则,同时错误地将多token组成的语法结构定义为词法规则,导致解析器无法正确识别带操作数的指令:

  1. ANTLR规定:大写开头的是词法规则(仅匹配单个token的字符序列),小写开头的是解析器规则(组合多个词法token形成语法结构)。
  2. 原语法中LabelOperandOperands被错误定义为词法规则,但它们是由多个token组成的语法结构(比如LabelWord+:),无法被词法分析器正确处理。
  3. 由于Operand作为词法规则永远不会被触发(优先级低于更早定义的RegisterWord等规则),解析器无法匹配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;
关键修改说明
  1. 规则类型修正
    • Label改为解析器规则label,匹配Word+:的token组合。
    • OperandOperands改为解析器规则operandoperands,用来组合不同类型的词法token作为指令操作数。
  2. 优化行规则
    • 修改line规则为label? instruction? Comment?,允许仅包含标签和注释的空指令行(适配你的测试输入第一行)。
  3. 简化换行处理
    • 由于Nl已设置为skipprogram规则直接用line*即可,无需保留Nl?
测试验证

修正后,你的测试输入:

Start: ;comment line
    HLT
    INR A
    JMP Loop
Loop:
END

会被正确解析:

  • INR AMnemonic(INR) + operands(operand(Register(A)))
  • JMP LoopMnemonic(JMP) + operands(operand(Word(Loop)))
  • 所有报错将消失。

内容的提问来源于stack exchange,提问作者Jaimin Vashi

火山引擎 最新活动