1

小さなプロジェクトでフレックス ツールとバイソン ツールを使用しようとしています。ツールを正しく理解して使用するために、ミニ電卓を作成しています。

問題はyyin、別の名前空間で宣言したクラスの関数内で変数を使用できないことです。

main()関数は run 引数を読み取り、 namespace で使用する必要が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

私の提案は、変数が flex によって外部的に定義されているが、名前空間yyinに適切に移植されていないということです。ExNameSpace

私が使用するソースファイルを添付する

例.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_ */

例.cpp:

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

パーサー.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;        
}

スキャナー.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
4

1 に答える 1

1

問題は宣言

extern FILE* yyin;

関数でExample::ParseFile。この宣言子には明示的なスコープがなく、含まれているメソッドは namespace の一部であるExNameSpaceため、宣言は暗黙的にその名前空間にあります。ExNameSpace::yyinしかし、どこにも定義しないため、リンク障害が発生します。bison によって作成されたデフォルトyyinは、グローバル名前空間にあります。したがって、この行を次のように変更する必要があります

extern FILE * ::yyin;

または、ファイルスコープの宣言がファイルのこの時点で既に表示されているはずなので、完全に削除するだけyyinです。そのため、ファイルスコープの宣言をシャドウするローカル宣言は必要ありません。

于 2013-01-22T19:54:13.480 に答える