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

Bison使用%code requires时YY_DO_BEFORE_ACTION未定义原因

问题产生原因

这个错误是依赖方向错误+循环include触发Flex条件编译逻辑异常导致的,核心逻辑如下:

  • %code requires 块的内容会被Bison直接放到生成的对外头文件prologue.tab.h的最开头,所有include这个头的代码都会先执行requires块里的内容;而普通无标识的%code块内容只会被放到Bison生成的.c实现文件中,不会进入对外头文件。
  • 将include语句放入%code requires块后,会触发两个关键问题:
    • 块内写了#include "prologue.tab.h",属于在Bison生成的头文件内部自引用,会触发无意义的循环include
    • 块内写了#include "prologue.h"(Flex生成的lexer头文件),完全反转了依赖方向:正常依赖关系是Flex生成的lexer代码依赖Bison生成的parser头文件,反向在parser头中引入lexer头会破坏Flex生成代码的宏定义顺序
  • Flex生成的lex.yy.c中,YY_DO_BEFORE_ACTION、YY_NEW_FILE这两个宏是在引入用户自定义头文件区块之后,通过条件编译判断未定义才会生成默认实现。当在Bison头文件中提前引入Flex生成的prologue.h时,会提前触发Flex头中的条件编译守卫,导致后续lex.yy.c中本该定义这两个宏的代码被跳过,最终编译时提示宏未定义。
  • 未使用%code requires时,所有include语句都只存在于Bison生成的.c文件中,编译lex.yy.c时不会提前加载Flex头文件触发守卫,因此宏可以正常定义,编译不会报错。
修复方案

按照以下步骤调整代码即可:

  • 清理%code requires块的内容,该块仅放%union、token定义需要的最小依赖,禁止放入任何生成文件的include语句:
    %code requires {
    // 仅保留union依赖的标准库头,比如在union中用了std::string就保留<string>引入
    #include <string>
    }
    
  • 将其他依赖引入语句移到普通%code块(仅在Bison生成的.c文件中生效,不会进入对外头文件),移除冗余的自引用include:
    %code top{
    #include <iostream>
    #include <fstream>
    #include <stdio.h>
    #include "prologue.h" // Flex生成的头仅在parser实现中引入即可,不需要对外暴露
    void yyerror (char const *s);
    }
    
    注意:普通%code块和%code top块中都不需要再写#include "prologue.tab.h",Bison生成实现文件时会自动把自身头的引入放在合适位置,手动自引入只会触发循环引用问题。
  • 调整完成后先执行make clean清除旧的生成文件,再重新make即可正常编译。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:33:00