在另一个命名空间中使用外部yyin

时间:2013-01-22 17:52:14

标签: c++ linker bison extern flex-lexer

我正在尝试在我的小项目中使用flex和bison工具。 为了正确理解和使用我正在编写迷你计算器的工具。

问题是我无法在另一个名称空间中声明的类的函数中使用变量yyin

main()函数应读取运行参数并在名称空间Example::parse_file()中使用ExNameSpace

在链接已编译的文件时,我得到:

make all
bison --defines=parser.hpp --output=parser.cpp parser.y
flex --outfile=scanner.cpp scanner.l
g++ -o program scanner.cpp parser.cpp Example.cpp -lfl 
/tmp/ccyQN7z9.o: In function `ExNameSpace::Example::parse_file(std::string const&)':
parser.cpp:(.text+0xabc): undefined reference to `ExNameSpace::yyin'
parser.cpp:(.text+0xac3): undefined reference to `ExNameSpace::yyin'
parser.cpp:(.text+0xb3e): undefined reference to `ExNameSpace::yyin'
collect2: error: ld returned 1 exit status
make: *** [app] Error 1

我的建议是变量yyin由flex在外部定义,但没有正确移植到ExNameSpace命名空间。

附加我使用的源文件

example.h文件:

#include <string>
#include <iostream>

#ifndef EXAMPLE_H_
#define EXAMPLE_H_

namespace ExNameSpace {
    /* global namespace variable */
    extern std::ostream *err;
    class Example {
    public:
        bool parse_file (const std::string &file);
};
}
#endif /* EXAMPLE_H_ */

Example.cpp:

#include "Example.h"
namespace ExNameSpace {
    std::ostream *err = &std::cout;
    Example::Example() {}
    Example::~Example() {}
}

parser.y:

%{
#include <stdio.h>
#include "Example.h"

void yyerror (const char *);
int yylex();

using namespace ExNameSpace;
%}

%%
/* bison rules */
%%

void yyerror(const char *message)
{
  extern int yylineno;
  *err << "(line " << yylineno << ") " << message << std::endl;
}

bool Example::parse_file(const std::string &file)
{
  extern FILE* yyin;
  if(!(yyin=fopen(file.c_str(), "r")))
  {
    *err << "Could not open " << file << std::endl;
    return true;
  }
  int result=yyparse();
  fclose(yyin);
  return result;        
}

scanner.l:

%{
#include "parser.hpp"
#include "Example.h"

using namespace ExNameSpace;
%}

%%
/* flex rules */
%%

生成文件:

all: app
app: scanner.l parser.y
    bison --defines=parser.hpp --output=parser.cpp parser.y
    flex --outfile=scanner.cpp scanner.l
    g++ -o program scanner.cpp parser.cpp Example.cpp -lfl 

clean:
    rm parser.hpp parser.cpp scanner.cpp

1 个答案:

答案 0 :(得分:1)

问题是声明

extern FILE* yyin;

在函数Example::ParseFile中。由于此声明符没有显式作用域,并且contains方法是名称空间ExNameSpace的一部分,因此声明隐含在该名称空间中。但是,由于您从未在任何地方定义ExNameSpace::yyin,因此会出现链接失败。 bison创建的默认yyin位于全局命名空间中。所以你需要将这一行改为

extern FILE * ::yyin;

或者完全摆脱它,因为yyin的文件范围声明应该已经在文件的这一点上可见,因此不需要本地声明来遮蔽文件范围。