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

Bison中用%code provides{}定义yyerror出现多重定义报错怎么办

报错根因

%code provides {}块的内容会被完整插入Bison生成的*.tab.h头文件中。你在这个块里直接写了yyerror的函数定义(而非声明),而bas.tab.c和lex.yy.c两个编译单元都引入了该头文件,会各自编译生成一份yyerror的函数实现,链接阶段必然触发多重定义错误。
Bison手册提到provides块适合放对外暴露的声明,指的是函数声明、类型定义、宏这类可在头文件中重复出现的内容,并非指函数实现可以放在这里。

修复方案

将yyerror的声明保留在%code provides块中,把函数实现移到仅会被编译进bas.tab.c的代码段即可,修改后的.y文件核心代码如下:

%define parse.error detailed
%define api.pure

%{
#include <stdio.h>

union YYSTYPE;
int yylex(union YYSTYPE *);
%}

%code provides {
// 头文件中仅放函数声明
void yyerror (char const *s);
}

%union {
  int ival;
  char *sval;
}
%token <ival> INT "integer"
%token <sval> STR "string"

%%

expr: INT | STR;

%%

// 函数实现放在生成的c文件代码区,仅编译一次
void yyerror (char const *s) {
  fprintf (stderr, "%s\n", s); 
}

int main() {
  return yyparse();
}
  • 临时兼容方案:如果一定要把函数实现放在%code provides块中,可以给函数加static修饰,让每个编译单元生成私有的函数副本,不会触发链接冲突。但这种方式会生成重复代码,若函数内存在静态变量还可能引发逻辑问题,不推荐常规使用。

修改后重新执行make即可正常编译,扫描器中调用yyerror的逻辑也能正常找到函数声明,不会报编译错误。


内容的提问来源于stack exchange,提问作者Christian Carter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:36:25