You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:52:25