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

如何让Bison解析器捕获并报告多个语法错误

Bison解析器多错误处理实现方案

核心修改思路

Bison默认遇到语法错误就终止解析,要实现多错误捕获,需通过错误同步规则让解析器跳过错误片段,回到合法语法上下文继续执行,同时确保错误信息和行号的准确输出。

具体修改步骤

1. 在Bison语法文件(file.y)中添加错误恢复规则

选择语言中明确的语法分隔符(如分号、花括号)作为同步点,在语法规则中加入错误处理分支,让解析器跳过错误内容直到同步标记,恢复解析。示例如下:

// 假设顶层规则为program,包含多个statement
program:
    %empty
    | program statement
    | program error ';'  // 遇到错误后跳过直到分号,继续解析后续内容
    ;

// 针对代码块的错误恢复
block:
    '{' statements '}'
    | '{' error '}'      // 跳过块内错误,直到闭合花括号
    ;

2. 配置Bison错误处理选项

在file.y的声明段(%{...%}之后、%%之前)添加以下选项,提升错误报告的准确性和详细度:

%define parse.error verbose  // 生成更具体的错误描述
%define parse.lac full       // 启用前瞻纠错,减少误判

3. 修正yyparse调用与yyerror参数

Bison生成的yyparse默认不需要传入FILE指针(已通过yyrestart重定向输入),同时调整yyerror的参数匹配Bison默认调用规范:

  • file.y的main函数中,将yyparse(input_file)改为yyparse()
  • file.l的yyerror函数参数改为const char* msg(移除多余的FILE参数)

4. 确保Flex行号跟踪正常

在Flex规则中添加换行符处理,更新yylineno变量保证错误行号准确:

\n          { yylineno++; }

修改后的完整代码示例

修改后的file.l

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Part_B.tab.h"
%}

// Lexical rules...

%%

\n          { yylineno++; }  // 跟踪行号
// 其他词法规则...

%%

int yywrap() {
    return 1;
}

int yyerror(const char* msg) {
    fprintf(stderr, "Error | Line: %d %s\n", yylineno, msg);
    return 0;
}

修改后的file.y

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Part_B.tab.h"

extern int yylineno;  // 引用Flex的行号变量
extern FILE* yyin;
%}

// Bison错误处理配置
%define parse.error verbose
%define parse.lac full

// 语法符号声明...

%%

// 带错误恢复的语法规则示例
program:
    %empty
    | program statement
    | program error ';'
    ;

statement:
    expr ';'
    | block
    // 其他语句规则...
    ;

block:
    '{' statements '}'
    | '{' error '}'
    ;

statements:
    %empty
    | statements statement
    ;

expr:
    // 表达式规则...
    ;

%%

int main() {
    const char* file_path = "test_input.txt";  // 补充文件路径定义
    FILE *input_file = fopen(file_path, "r");
    if (input_file == NULL) {
        fprintf(stderr, "Error: Unable to open input file\n");
        return 1;
    }
    yyrestart(input_file);

    yyparse();

    fclose(input_file);  // 关闭文件
    return 0;
}

关键说明

  • 同步点的选择需贴合你的自定义语言语法,优先选语句/块的结束标记,确保解析器能快速回到合法上下文。
  • parse.error verbose会让Bison输出如“expected ';' found '}'”的具体错误信息,便于定位问题。
  • 必须保证yylineno在Flex中正确更新,否则错误行号会出现偏差。

内容的提问来源于stack exchange,提问作者Salah Amani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:18:17