繁体   English   中英

为什么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 { ... }放入了头文件中。

您的每个C ++转换单元(包括该转换单元)都将获取头文件的原始文本的副本 ,因此具有名称空间声明的副本 由于名称空间是匿名的,因此每个副本都是独立的。 每个翻译单元,其包括这有它自己的 counter ,以及dosomethingafterfinish

这与C语言中将一些静态定义放入标头中的情况非常相似,如下所示:

static int counter = 0;
static void dosomething(void) { printf("%d\n", ++counter); }
static void afterfinish(void) { printf("%d\n", counter); }

其中每个C单元#include -s此标头得到它自己的计数器,用它自己的私有双功能一起dosomethingafterfinish ,其在其上进行操作。

词法分析器模块在其自己的计数器上运行,而包含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的主模块中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM