如何在 `bison/yacc` 中重新定义 `YYSTYPE`?
How to redefine `YYSTYPE` in `bison/yacc`?
我定义了一个用户 class 来保存所有对象。但是yacc
要做一个头文件,yylval
的类型必须是YYSTYPE
。如果我不使用 %union
,它将把它保存为一个整数。但是如果我使用 %union
,它将成为一个联合。联合是丑陋的——它不能容纳 class 或 shared_ptr(可以但不是一个好主意),它只希望我使用指针。
我只想让 YYSTYPE
有一个类型作为用户 class 类型。我该怎么做?
如您所见,lex
和yacc
制作的源文件需要yacc
制作的header文件。
header 很短,所以我们可以在其中寻找一些解决方案。
定义yylval
类型的部分是这样的:
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE yylval;
所以我们可以在包含 yacc
的 header 文件之前定义 YYSTYPE
,看起来像:
#include "your-header-file-that-define-the-class.h"
#define YYSTYPE your-class-type
#include "the-header-file-that-made-by-yacc.h"
不要使用 YYSTYPE
。
使用 bison——这是您实际用作 yacc 实现的东西——定义语义值类型的正确方法是
%define api.value.type { MyType }
如果您需要包含一个或多个头文件以使声明有效,请将它们放在 %code requires
块中:
%code requires {
#include "MyType.h"
}
这两个指令生成的代码被复制到bison生成的头文件中,所以其他文件只需要包含生成的头文件。
警告:请注意,除非您使用 bison 的 C++ 接口,否则语义值类型必须是普通可复制的,这将消除大多数标准 C++ 库类型。不遵守此规则将产生未定义的行为,在您尝试解析足够复杂的输入之前,这些行为可能不会被发现。换句话说,使用简单输入的测试可能无法揭示错误。
我定义了一个用户 class 来保存所有对象。但是yacc
要做一个头文件,yylval
的类型必须是YYSTYPE
。如果我不使用 %union
,它将把它保存为一个整数。但是如果我使用 %union
,它将成为一个联合。联合是丑陋的——它不能容纳 class 或 shared_ptr(可以但不是一个好主意),它只希望我使用指针。
我只想让 YYSTYPE
有一个类型作为用户 class 类型。我该怎么做?
如您所见,lex
和yacc
制作的源文件需要yacc
制作的header文件。
header 很短,所以我们可以在其中寻找一些解决方案。
定义yylval
类型的部分是这样的:
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE yylval;
所以我们可以在包含 yacc
的 header 文件之前定义 YYSTYPE
,看起来像:
#include "your-header-file-that-define-the-class.h"
#define YYSTYPE your-class-type
#include "the-header-file-that-made-by-yacc.h"
不要使用 YYSTYPE
。
使用 bison——这是您实际用作 yacc 实现的东西——定义语义值类型的正确方法是
%define api.value.type { MyType }
如果您需要包含一个或多个头文件以使声明有效,请将它们放在 %code requires
块中:
%code requires {
#include "MyType.h"
}
这两个指令生成的代码被复制到bison生成的头文件中,所以其他文件只需要包含生成的头文件。
警告:请注意,除非您使用 bison 的 C++ 接口,否则语义值类型必须是普通可复制的,这将消除大多数标准 C++ 库类型。不遵守此规则将产生未定义的行为,在您尝试解析足够复杂的输入之前,这些行为可能不会被发现。换句话说,使用简单输入的测试可能无法揭示错误。