flex / bison中的多个解析器:包含失败

时间:2016-02-24 15:36:04

标签: c++ compilation bison flex-lexer

我正在尝试使用多个解析器构建程序。我已将不同解析器的flex / bison文件放在不同的文件夹中以避免冲突。

我使用了不同的前缀来使用它们。但是,我的程序不会从头开始构建,扫描程序类会产生错误:

#pragma once

#if ! defined(yyFlexLexerOnce)
#define yyFlexLexer spFlexLexer
#include <FlexLexer.h>
#undef yyFlexLexer
#endif

#include "split_pattern_parser.h"

namespace SP {

class SP_Scanner : public spFlexLexer {
...
}

我收到此错误:

error: expected class-name before ‘{’ token
 class SP_Scanner : public spFlexLexer {

我设法通过多次删除#if ! defined(yyFlexLexerOnce)条件进行编译,并在出现此错误时重新添加:

src/actions/actions_scanner.h:4:21: error: redefinition of ‘class actFlexLexer’
#define yyFlexLexer actFlexLexer
                 ^
actions_lexer.cpp:32:25: error: previous definition of ‘class actFlexLexer’

(行动只是另一个词法分析者)

即使对我来说这不是一个大问题(我可以继续处理我的项目),但是当我必须分发我的项目时它会变得非常棘手:要解释这个程序来构建它并不是一件好事。代码。

提前感谢您的帮助

1 个答案:

答案 0 :(得分:2)

你不应该和yyFlexLexerOnce一起愚弄。这是Flex实施的内部。

您需要声明您使用的各种FlexLexer,理想情况下恰好一次。您还需要准确地声明FlexLexer本身一次。 yyFlexLexerOnce宏是将弹性扫描仪的C ++接口放在一起选择使其成为可能的方式。 (我会选择多个头文件,但我确定他们有自己的理由。)

所以忘记曾经见过yyFlexLexerOnce,并按手册告诉你的方式去做:

#define yyFlexLexer spFlexLexer
#include "FlexLexer.h"
#undef yyFlexLexer

// This will not normally be in the same header file, but it could be.

#define yyFlexLexer actFlexLexer
#include "FlexLexer.h"
#undef yyFlexLexer

FlexLexer.h有两个重要问题。

如上所示,第一个是它被设计为#include d不止一次,所以它没有标题保护。这意味着您必须确保它在yyFlexLexer的相同预处理器定义中永远不会包含两次。一个好习惯可能是创造一个小包装:

/*** File: sp_scanner.h ***/

#pragma once
#define yyFlexLexer spFlexLexer
#include "FlexLexer.h"
#undef yyFlexLexer

但是这会遇到第二个问题:yyFlexLexer在生成的扫描程序实施文件中自动为#include d,并且#defineyyFlexLexer。因此, #include扫描程序定义文件中的任何插入代码中的 .l(甚至间接地)都不能 sp_lexer.h

这会在非常罕见的情况下产生烦恼,在这种情况下,您需要执行扫描程序所需的其他声明。诱惑是将这些声明放在#incldue "sp_lexer.h"头文件中(如上所述),但这不会起作用,因为您不能在扫描仪定义文件中#include。相反,您需要创建另一个头文件,并scanner.l文件和sp_lexer.h文件中的yyclass

具体地说,假设您使用/*** File: sp_scanner_internal.h ***/ #pragma once namespace sp { class Scanner : public spFlexLexer { /* ... */ }; } /*** File: sp_scanner.h ***/ #pragma once #define yyFlexLexer spFlexLexer #include "FlexLexer.h" #undef yyFlexLexer #include "sp_scanner_internal.h" /*** File: sp_scanner.l ***/ %option prefix="sp" %option outfile="sp_scanner.cpp" %option yyclass="sp::Scanner" %{ #include "sp_scanner_internal.h" #include "sp_parser.h" %} 选项在派生类中插入scanner实现方法。显然,您需要在生成的扫描程序之前声明此派生类,并且还要在生成的扫描程序的任何使用者中声明此派生类。所以你最终会得到这样的东西:

%option header-file

我从示例文件中删除了--header-file,因为该头文件不应该在C ++项目中使用。请参阅Flex manual

  

--c++选项与yyFlexLexer.h选项不兼容,因为C ++扫描程序在#include <iostream>中提供了自己的标头。

我也删除了FlexLexer.h,因为它包含在sprintf中,但当然如果您愿意保留它也不是问题。