将STL容器从Flex传递到Bison [英] Pass STL containers from Flex to Bison
问题描述
我正在使用Flex和Bison编写扫描仪/解析器组合,如果可能的话,我想避免同时使用这两个程序的C ++特定功能,但是我仍然需要从Bison生成的源文件访问C ++库.目前,我正在将Flex生成的源文件编译为C程序.
I'm writing a scanner/parser combination using Flex and Bison, if possible I would like to avoid using C++ specific features of both programs but nevertheless I need to access a C++ library from the source file generated by Bison. At the moment I'm compiling the source file generated by Flex as a C program.
我想我可以做的一件事是在Bison的%union
语句中声明STL类型成员,例如:
One thing I thought I might be able to do is to declare STL type members inside Bison's %union
statement, e.g.:
%union {
std::string str;
};
我很快意识到这是行不通的,因为这会产生一个包含在Flex源文件中的并集.然后我以为我可能也可以使用C ++编译器进行编译,但是运行野牛时上面的语句已经被拒绝了:
I quickly realized that this cannot work because this produces a union that is included by the Flex source file. I then thought I might just compile that with a C++ compiler as well but the statement above is already rejected when running bison:
error: expected specifier-qualifier-list before ‘std’
我真的不想解决整个解析器中使用C stdlib函数复制和连接字符串的麻烦.为了使扫描程序将STL类型返回到解析器,我该怎么办?
I don't really want to go through the trouble of copying and concatenating strings with C stdlib functions throughout my parser. What can I do in order to make the scanner return STL types to the parser?
链接的重复项并不能真正回答我的问题,对此的回答仅显示了如何使用C ++编译器来编译两个文件,这不是我的问题.
the linked duplicate does not really answer my question, the answers to that one only show how to compile both files using a C++ compiler which is not my issue.
推荐答案
您当然可以使用C ++编译生成的扫描程序和解析器,即使您使用默认的C框架(我也同意C ++框架的文档记录不充分,并且过于复杂).因此,没有什么可以阻止您在解析器内部使用 std :: string
.
You can certainly compile both your generated scanner and parser with C++, even if you use the default C skeletons (and I agree that the C++ skeletons are badly documented and excessively complicated). So there is nothing stopping you from using std::string
inside your parser.
但是,这不能让您将 std :: string
放入 union
内,因为您不能仅仅将一个带有非平凡析构函数的类扔掉变成 union
.可以通过显式声明语义类型并提供显式的构造函数和析构函数来解决此限制,但这将是相当多的工作,而且可能不值得.
However, that won't let you put a std::string
inside a union
, because you can't just toss a class with a non-trivial destructor into a union
. It's possible to work around this limitation by explicitly declaring the semantic type and providing explicit constructors and destructors, but it's going to be a fair amount of work and it may well not be worth it.
这仍然给您提供了两个选择.一种是使用指向 std :: string
的指针,这意味着您的扫描仪操作必须执行以下操作:
That still leaves you with a couple of options. One is to use a pointer to a std::string
, which means that your scanner action has to do something like:
[[:alpha:]][[:alnum:]_]* yylval.strval = new std::string(yytext);
另一种方法是只使用C字符串,从而导致:
Another one is to just use C strings, leading to:
[[:alpha:]][[:alnum:]_]* yylval.strval = strdup(yytext);
在这两种情况下,您最终都必须手动管理分配的内存.C ++的智能指针不会帮助您,因为它们也具有非平凡的析构函数,因此它们也不容易轻易地陷入语义联合中.
In both cases, you'll end up having to manually manage the allocated memory; C++'s smart pointers won't help you because they also have non-trivial destructors, so they can't be easily shoe-horned into semantic unions either.
由于您似乎最终会将令牌变成了 std :: string
,因此不妨从头开始使用上面的第一个选项进行操作.由于大多数令牌都很短,并且大多数C ++库现在都实现了短字符串优化,因此 new std :: string(yytext)
通常只需要分配一个内存(如果需要分配两个内存,则该库将透明地处理第二个).
Since it appears that you're going to eventually make the token into a std::string
, you might as well do it from the start using the first option above. Since most tokens are short and most C++ libraries now implement a short string optimization, new std::string(yytext)
will frequently require only one memory allocation (and if it requires two, the library will transparently handle the second one).
这篇关于将STL容器从Flex传递到Bison的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!