如何解决LALR语法下Bison错误恢复后误判后续输入的问题?
解决Bison错误恢复后后续输入持续报错的问题
你的问题出在错误恢复规则覆盖范围不足,以及行号计数逻辑冲突,以下是具体修复方案:
1. 修改错误恢复规则,覆盖整行错误内容
原规则X: error newline_TOK仅能匹配错误后直接换行的极端场景,若错误行包含其他字符,解析器无法触发恢复逻辑,导致后续输入持续报错。需修改为跳过错误行所有字符直到换行:
X: S | error any_TOK* newline_TOK { yyerrok; yyclearin; linenum++; };
any_TOK*会匹配错误行中所有未被识别的字符,确保解析器跳过整行错误内容,回到正确的解析起点。
2. 修正行号计数逻辑
原代码中yyerror和错误恢复规则都在递增linenum,会导致行号重复计数。调整yyerror的行号输出逻辑,让它输出当前错误行的行号(未递增前的linenum+1),错误恢复规则处理换行时再递增行号:
int yyerror(char *s) { printf("Syntax error - line %d\n", linenum + 1); return 0; }
保留LF规则中的行号递增逻辑:
LF: newline_TOK { linenum += 1; printf("Correct derivation - line %d!\n", linenum); };
3. 确保any_TOK在词法分析器中正确实现
在对应的Flex词法文件中,需正确定义any_TOK以匹配所有未被其他规则识别的字符:
. { return any_TOK; }
完整修正后的Bison代码
%{ int yyerror(char *s); int yylex(void); //#define YYDEBUG 1 #include <stdio.h> int linenum = 0; %} %token a_TOK b_TOK c_TOK d_TOK e_TOK f_TOK g_TOK h_TOK newline_TOK any_TOK %% X: S | error any_TOK* newline_TOK { yyerrok; yyclearin; linenum++; }; S: A B LF X; A: a_TOK h_TOK | a_TOK b_TOK A c_TOK | a_TOK B c_TOK; B: C D E; LF: newline_TOK { linenum += 1; printf("Correct derivation - line %d!\n", linenum); }; C: d_TOK | e_TOK; D: f_TOK D | f_TOK; E: B | g_TOK; %% int yyerror(char *s) { printf("Syntax error - line %d\n", linenum + 1); return 0; } int main(void) { #if YYDEBUG yydebug = 1; #endif if(!yyparse()) printf("End of input reached\n"); return 0; }
原理说明
yyerrok:通知解析器恢复正常错误处理模式,不再持续触发报错。yyclearin:清空当前输入缓冲区,避免残留的错误字符干扰后续解析。any_TOK*:确保跳过错误行的全部内容,让解析器能从下一行重新开始语法分析。
内容的提问来源于stack exchange,提问作者filipcimo
相关产品推荐
相关产品推荐

