将STL容器从Flex传递到Bison

时间:2018-07-17 21:43:00

标签: c++ bison flex-lexer

我正在使用Flex和Bison编写扫描器/解析器组合,如果可能的话,我想避免同时使用这两个程序的C ++特定功能,但是我仍然需要从Bison生成的源文件访问C ++库。目前,我正在将Flex生成的源文件编译为C程序。

我想我可以做的一件事是在Bison的%union语句中声明STL类型成员,例如:

%union {
  std::string str;
};

我很快意识到这是行不通的,因为这会产生一个包含在Flex源文件中的并集。然后我以为我也可以使用C ++编译器进行编译,但是运行野牛时上面的语句已经被拒绝了:

error: expected specifier-qualifier-list before ‘std’

我真的不想在整个解析器中使用C stdlib函数复制和连接字符串的麻烦。为了使扫描程序将STL类型返回解析器,我该怎么做?

编辑:链接的重复项并不能真正回答我的问题,对此的回答仅显示了如何使用C ++编译器来编译两个文件,这不是我的问题。

1 个答案:

答案 0 :(得分:2)

您当然可以使用C ++编译生成的扫描器和解析器,即使您使用默认的C框架(我也认为C ++框架的文档记录不当且过于复杂)。因此,没有什么阻止您在解析器中使用std::string

但是,这不能让您将std::string放在union内,因为您不能仅仅将具有非平凡析构函数的类扔到union中。可以通过显式声明语义类型并提供显式的构造函数和析构函数来解决此限制,但这将是相当多的工作,而且可能不值得。

这仍然给您提供了两个选择。一种是使用指向std::string的指针,这意味着您的扫描仪操作必须执行以下操作:

[[:alpha:]][[:alnum:]_]*    yylval.strval = new std::string(yytext);

另一种方法是只使用C字符串,从而导致:

[[:alpha:]][[:alnum:]_]*    yylval.strval = strdup(yytext);

在这两种情况下,您最终都必须手动管理分配的内存。 C ++的智能指针不会帮助您,因为它们也具有非平凡的析构函数,因此它们也不容易轻易地陷入语义联合中。

由于您似乎最终会将令牌制作成std::string,因此不妨从头开始使用上述第一个选项来完成。由于大多数令牌都很短,并且大多数C ++库现在都实现了短字符串优化,因此new std::string(yytext)通常只需要分配一个内存(如果需要两个,则该库将透明地处理第二个)。