如何初始化 Bison 的 %union 值?

发布于 2024-07-30 05:26:10 字数 340 浏览 6 评论 0原文

在 Bison 中,我有一个 union

%union
{
   std::string* sval;
}

我想像这样使用它

在 Lex 中:

*(yylval->sval) = "ABCD";

而不是

yylval->sval = new std::string("ABCD");

轻松防止内存泄漏

但是我需要某种方法来将 std::string 分配给 sval 首先。

我怎样才能做到这一点?

In Bison I have a union

%union
{
   std::string* sval;
}

And I want to use it like this

In Lex:

*(yylval->sval) = "ABCD";

Rather than

yylval->sval = new std::string("ABCD");

To prevent memory leaks easily

However I need some way to allocated a std::string to sval to begin with.

How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挖鼻大婶 2024-08-06 05:26:10

您无法安全地将具有构造函数或析构函数的类型(例如 std::string)放入联合中,因此这不起作用。

你可以做的就是根本不使用 %union ——而是使用宏将 YYSTYPE 直接映射到其他类型:

%{
#define YYSTYPE std::string
%}

然后 yylval 将是该类型(语法代码中的所有 $n 选项也是如此)

You can't safely put types with constructors or destructors (such as std::string) in a union, so this won't work.

What you can do instead is not use %union at all -- instead use a macro to map YYSTYPE directly to some other type:

%{
#define YYSTYPE std::string
%}

then yylval will be that type (as will all $n options in the grammar code)

淤浪 2024-08-06 05:26:10

我不完全清楚你为什么要这样做,但我可以明白为什么你所拥有的不起作用。 这是因为 "ABCD"const char *,而不是 std::string

我知道 Yacc 的第一个 "%{ ... %}" 部分允许您在 Yacc 的控制之外定义 C 内容(而且 Bison 似乎具有类似的功能,基于它的向上兼容性)声明和文档此处,2.1.1) 。 为什么不将: 放在

std::string *strABCD = new std::string("ABCD");

该部分中,然后

yylval->sval = strABCD;

在需要指向该字符串的指针时使用: ?

在我看来,这是实现(我认为)你想要的最简单的方法。

如果您担心 Bison 解析器内的分配未被释放(它们应该被释放),我的建议是不要在那里进行分配。 您可以在调用 yyparse() 之前设置字符串,然后在返回后释放它。

更新:

以下是我如何避免在 Bison 解析器中分配/释放该固定值的方法。 将其设置为在程序运行期间有效的全局变量。

主要代码:

std::string *strABCD = new std::string ("ABCD");

int main(...) {
    // Do some stuff.
    : : :
    yyparse();
    : : :
    // Do some other stuff.
}

Bison 解析器源代码:

%{
    extern std::string *strABCD;
%}
: : :
yylval->sval = strABCD;

返回指向 ABCD 字符串的固定指针,在 Bison 代码中根本没有分配或释放(甚至在主代码中也很少)。

I'm not entirely clear why you want to do this but I can see why what you have isn't working. It's because "ABCD" is a const char *, not a std::string.

I know with Yacc that the first "%{ ... %}" section allows you to define C stuff outside the control of Yacc (and it appears Bison has a similar feature, based on it's upward compatibility claim and the documentation here, 2.1.1). Why would you not put:

std::string *strABCD = new std::string("ABCD");

in that section and then use:

yylval->sval = strABCD;

later on whenever you needed a pointer to that string?

That seems to me to be the easiest way to achieve what (I think) you want.

If you're worried about allocations within the Bison parser not being freed (and they should be), my advice is to not do them in there. You can set up your string before calling yyparse() then free it after return.

Update:

Here's how I'd do it to avoid allocating/freeing that fixed value within the Bison parser. Set it up as a global that lives for the duration of the program.

Main code:

std::string *strABCD = new std::string ("ABCD");

int main(...) {
    // Do some stuff.
    : : :
    yyparse();
    : : :
    // Do some other stuff.
}

Bison parser source:

%{
    extern std::string *strABCD;
%}
: : :
yylval->sval = strABCD;

That returns the fixed pointer to your ABCD string with no allocation or freeing in the Bison code at all (and precious little even in the main code).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文