为什么 Flex/Lex 将 c++ 代码的变量重置为其初始值?
Why does Flex/Lex reset variable of c++ code to its initial value?
我试图使用 Flex 和 Bison 与 C++ 创建简单的编译器,但我不明白为什么当 Flex 到达文件末尾时它会将 C++ 文件中声明的变量重置为其初始值。
在lex.l文件中:
%{
#include "HelperCode.h"
// ... etc
%}
%option c++
%option noyywrap
%option yylineno
%%
[\n] { dosomething();}
// ...etc
%%
和HelperCode.h文件:
namespace
{
int counter = 0;
//rest of code
void dosomething()
{
counter++;
cout << counter << " ";
// here it will print the correct values based on input
// ex: 1 2 3 4 5
}
void afterfinish()
{
cout << endl << counter;
// but here it will print '0', like if the counter reset to 0
}
}
并在 yacc.y 文件中:
// ... etc
// ...
void main(void)
{
Parser* p = new Parser();
p->parse();
afterfinish();
}
问题几乎可以肯定是您将 namespace { ... }
放入了 header 文件。
包含此内容的每个 C++ 翻译单元都会获得 header 文件原始文本的副本,因此具有命名空间声明的 副本 。由于命名空间是匿名的,因此每个副本都是独立的;每个包含此 的翻译单元都有自己的 counter
,以及 dosomething
和 afterfinish
.
这与C语言中将一些静态定义放入header中的情况非常相似,像这样:
static int counter = 0;
static void dosomething(void) { printf("%d\n", ++counter); }
static void afterfinish(void) { printf("%d\n", counter); }
#include
-s 这个 header 的每个 C 单元都有自己的计数器,以及一对自己的私有函数 dosomething
和 afterfinish
它。
词法分析器模块在自己的计数器上运行,包含 main
的模块中的 afterfinish
在 其 自己的计数器上运行,该计数器仍然为零.
如果您想要一个由您的模块共享的命名空间,只需为其命名即可。
// header file HelperCode.h
namespace parser_stuff {
// We no longer *define* the counter in the header, just declare it.
extern int counter;
// And we use inline on functions defined in the header, otherwise
// they will now be multiply defined!
inline void dosomething()
{
counter++;
// ... etc
}
// non-inline function
void afterfinish();
}
// In one .cpp file somewhere, perhaps HelperCode.cpp
#include "HelperCode.h"
namespace parser_stuff {
int counter = 0; // One program-wide definition of parser_stuff::counter.
void afterfinish()
{
// ....
}
}
当然,我们现在要做的
%{
#include "HelperCode.h"
// ... etc
%}
%option c++
%option noyywrap
%option yylineno
%%
[\n] { parser_stuff::dosomething();}
// ...etc
%%
否则:
%{
#include "HelperCode.h"
// ... etc
// one of these: bring in a specific identifier, or whole namespace:
using parser_stuff::dosomething;
using namespace parser_stuff;
%}
%option c++
%option noyywrap
%option yylineno
%%
[\n] { dosomething();}
// ...etc
%%
并且在引用 afterfinish
.
的主模块中类似
我试图使用 Flex 和 Bison 与 C++ 创建简单的编译器,但我不明白为什么当 Flex 到达文件末尾时它会将 C++ 文件中声明的变量重置为其初始值。
在lex.l文件中:
%{
#include "HelperCode.h"
// ... etc
%}
%option c++
%option noyywrap
%option yylineno
%%
[\n] { dosomething();}
// ...etc
%%
和HelperCode.h文件:
namespace
{
int counter = 0;
//rest of code
void dosomething()
{
counter++;
cout << counter << " ";
// here it will print the correct values based on input
// ex: 1 2 3 4 5
}
void afterfinish()
{
cout << endl << counter;
// but here it will print '0', like if the counter reset to 0
}
}
并在 yacc.y 文件中:
// ... etc
// ...
void main(void)
{
Parser* p = new Parser();
p->parse();
afterfinish();
}
问题几乎可以肯定是您将 namespace { ... }
放入了 header 文件。
包含此内容的每个 C++ 翻译单元都会获得 header 文件原始文本的副本,因此具有命名空间声明的 副本 。由于命名空间是匿名的,因此每个副本都是独立的;每个包含此 的翻译单元都有自己的 counter
,以及 dosomething
和 afterfinish
.
这与C语言中将一些静态定义放入header中的情况非常相似,像这样:
static int counter = 0;
static void dosomething(void) { printf("%d\n", ++counter); }
static void afterfinish(void) { printf("%d\n", counter); }
#include
-s 这个 header 的每个 C 单元都有自己的计数器,以及一对自己的私有函数 dosomething
和 afterfinish
它。
词法分析器模块在自己的计数器上运行,包含 main
的模块中的 afterfinish
在 其 自己的计数器上运行,该计数器仍然为零.
如果您想要一个由您的模块共享的命名空间,只需为其命名即可。
// header file HelperCode.h
namespace parser_stuff {
// We no longer *define* the counter in the header, just declare it.
extern int counter;
// And we use inline on functions defined in the header, otherwise
// they will now be multiply defined!
inline void dosomething()
{
counter++;
// ... etc
}
// non-inline function
void afterfinish();
}
// In one .cpp file somewhere, perhaps HelperCode.cpp
#include "HelperCode.h"
namespace parser_stuff {
int counter = 0; // One program-wide definition of parser_stuff::counter.
void afterfinish()
{
// ....
}
}
当然,我们现在要做的
%{
#include "HelperCode.h"
// ... etc
%}
%option c++
%option noyywrap
%option yylineno
%%
[\n] { parser_stuff::dosomething();}
// ...etc
%%
否则:
%{
#include "HelperCode.h"
// ... etc
// one of these: bring in a specific identifier, or whole namespace:
using parser_stuff::dosomething;
using namespace parser_stuff;
%}
%option c++
%option noyywrap
%option yylineno
%%
[\n] { dosomething();}
// ...etc
%%
并且在引用 afterfinish
.