Bison编译报错:%yacc与%define api.value.type union无法共存
%define api.value.type union与%yacc冲突的问题 首先,咱们先搞清楚%yacc是什么:
这是Bison提供的一个兼容指令,用来让Bison尽可能模拟传统Yacc的行为模式。传统Yacc有很多固定约定,比如默认会生成一个名为YYSTYPE的全局union类型,用来存储语法符号的值——这和你想用的现代Bison值类型机制是直接冲突的。
报错原因
当你添加%define api.value.type union时,你是在告诉Bison使用它的现代值类型系统:允许你自定义union的成员,甚至可以不用union改用结构体等类型。但%yacc指令强制Bison回到旧Yacc的行为逻辑,其中就包括锁定值类型为传统的YYSTYPE,这两个设置在值类型的处理规则上完全矛盾,所以Bison会抛出这个错误。
解决办法
你有两个选择,根据你的开发需求来选:
移除
%yacc指令(推荐,适合新开发的编译器)
既然你是在开发全新的简易编译器,没必要兼容旧Yacc的行为。直接删掉代码中的%yacc指令,然后继续使用%define api.value.type union,接下来你可以通过%token和%type直接指定每个符号的具体类型,示例如下:%define api.value.type union %token <int> INT %token <char*> STRING %type <int> expr这种方式下Bison会自动生成包含对应成员的union,比传统Yacc的写法更灵活清晰。
保留
%yacc,改用传统Yacc的方式定义值类型
如果你因为某些原因必须保留%yacc(比如要兼容旧的Yacc代码结构),那就要放弃%define api.value.type union,转而手动定义YYSTYPE:%yacc %{ #include <stdio.h> // 手动定义YYSTYPE union typedef union { int ival; char* sval; } YYSTYPE; // 告诉Bison使用这个自定义的YYSTYPE #define YYSTYPE_IS_DECLARED 1 %} %token INT STRING %type expr这种方式是传统Yacc的标准做法,需要手动管理union的定义和成员。
内容的提问来源于stack exchange,提问作者Kamal El-Saaid

