如何在Bison中限制错误恢复仅在行首Token异常时触发
仅在行首Token错误时启用Bison错误恢复的实现方法
问题场景
我们有一套基于行的语法,只允许两种行格式:
start1 1 start2 1 2
start1后面必须紧跟一个数字start2后面必须紧跟两个数字- 行首是
start1或start2以外的单词,一律判定为非法输入
目前用Bison写的语法规则如下:
line: START1 number NEWLINE | START2 number number NEWLINE | error alnums NEWLINE alnums: ALNUM | ALNUM alnums number: ALNUM { parse_number(); }
现在遇到的问题:
- 行首是非法单词(比如
foobar 1)时,解析器会忽略整行完成错误恢复,这符合预期 - 但合法行首后出现格式错误(比如
start1 1 2 3)时,解析器也会自动错误恢复,这不符合需求
我们需要实现:只有行首单词无效时允许错误恢复,其他场景禁止自动丢弃Token,直接报错
解决方案
核心思路是拆分语法结构,让错误恢复规则只匹配「行首非法」的场景,避免被合法行首后的错误触发。
1. 拆分规则,明确行首合法性
把行的结构拆分为「合法行」和「非法行」两个独立分支,只给非法行添加错误恢复逻辑:
%token START1 START2 ALNUM NEWLINE %% input: /* 空 */ | input line ; line: valid_line | invalid_line ; // 合法行:严格匹配格式,错误时不做自动恢复 valid_line: START1 number NEWLINE | START2 number number NEWLINE ; // 非法行首:仅这里启用错误恢复,吃掉整行(可在这里输出自定义错误信息) invalid_line: error NEWLINE ; number: ALNUM { parse_number(); } ;
2. 保留精准错误信息的优化版
如果需要通过alnums匹配非法行首后的内容,输出更具体的错误信息,可以调整invalid_line规则:
invalid_line: error alnums NEWLINE { // 比如输出:"行首非法标记,后续内容:xxx" } ; alnums: ALNUM | ALNUM alnums ;
为什么这样有效?
Bison的错误恢复规则是按匹配优先级触发的:当解析器遇到错误时,会优先尝试匹配最贴合当前状态的错误规则。通过拆分合法行和非法行的分支,确保只有行首不是START1/START2时,才会触发错误恢复;而合法行首后的格式错误,因为没有对应的错误恢复规则,会直接终止解析或抛出错误,不会自动丢弃Token。
内容的提问来源于stack exchange,提问作者Szabolcs
相关产品推荐
相关产品推荐

