1

lexで単純なパーサーを作成し、C++で実行しようとしています。私はここの指示に従うことから始めました

WIKILINK    \133{2}[^\135]+\135{2}
%option noyywrap
%option c++
%{
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>

#include <FlexLexer.h>

class xxFlexLexer : public yyFlexLexer
{
    public:
    virtual int yylex()
    {
        std::cout << "hello" << std::endl;
    }
private:
            vector<string> listOfLinks;
};

using namespace std;
%}

%%
{WIKILINK}    {
                            int size = YYLeng();
                            string link(YYText());
                            link.erase(YYLeng()-3, 2);
                            link.erase(0, 2);
                            listOfLinks.push_back(link);
                            }
%%

int main()
{
    ifstream in;
    ofstream out;

    in.open("in.txt");
    out.open("out.txt");

    yyFlexLexer lexer(&in, &out);
    lexer.yylex();
}

プログラムlex.yy.ccをコンパイルしようとすると、次のエラーが発生します-

In file included from tmp.cpp:12:0:
/usr/include/FlexLexer.h:112:7: error: redefinition of ‘class yyFlexLexer’
/usr/include/FlexLexer.h:112:7: error: previous definition of ‘class yyFlexLexer’
tmp.cpp: In member function ‘virtual int yyFlexLexer::yylex()’:
tmp.cpp:33:29: error: ‘listOfLinks’ was not declared in this scope

このエラーがわかりません。何が起こっている?

4

1 に答える 1

0

Web を見ると、この FlexLexer.h インクルード ファイルhttps://www.w3.org/2005/05/22-SPARQL-MySQL/sparql/FlexLexer.hが見つかりました。署名にyylex()は引数があるようFLEXFIXです。

virtual int yylex(FLEXFIX) = 0;

// Call yylex with new input/output sources.
int yylex(FLEXFIX, istream* new_in, ostream* new_out = 0 )
    {
    switch_streams( new_in, new_out );
    return yylex(FLEXFIX2);
    }

ただし、 https://www.w3.org/2008/04/SPARQLfed/win/FlexLexer.hなどの他のバージョンのファイルにはありません。

virtual int yylex() = 0;

// Call yylex with new input/output sources.
int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 )
    {
    switch_streams( new_in, new_out );
    return yylex();
    }

ところで、あなたのyylex()関数は int 値を返していません。

@Gir のコメントとバグ レポートBug 67277 - Error compiling libclassparser_la.all_cc.cc: "class yyFlexLexer" redefinedへのリンクも参照してください。

問題は、FlexLexer.h ヘッダーがそれ自体の複数のインクルードを処理する奇妙な方法を持っていることです。tokenizer.l (tokenizer.cc) と ClassParser.cc の両方にこのヘッダーが間接的に含まれており、個別のコンパイルでは問題なく動作します。しかし、連結されたソースをコンパイルすると、「#define yyFlexLexer yyFlexLexer」宣言 (flex によって挿入される) が tokenizer.cc から ClassParser.cc に引き継がれ、2 番目のインクルードで混乱が生じます。(上記のエラー メッセージでは、FlexLexer.h の 2 行がそれぞれ 2 番目と 1 番目のインクルードです。)

/A の解決策は、tokenizer.l の末尾に「#undef yyFlexLexer」を追加することです。その理由を説明したパッチを添付します。

FlexLexer.h インクルード ファイルのコメントは、複数のインスタンスとインクルードのバグ レポートにあるものを使用して言及しています。ただし、この単純で単純なものになぜそれが必要なのかはわかりません。

// This file defines FlexLexer, an abstract class which specifies the
// external interface provided to flex C++ lexer objects, and yyFlexLexer,
// which defines a particular lexer class.
//
// If you want to create multiple lexer classes, you use the -P flag
// to rename each yyFlexLexer to some other xxFlexLexer.  You then
// include <FlexLexer.h> in your other sources once per lexer class:
//
//  #undef yyFlexLexer
//  #define yyFlexLexer xxFlexLexer
//  #include <FlexLexer.h>
//
//  #undef yyFlexLexer
//  #define yyFlexLexer zzFlexLexer
//  #include <FlexLexer.h>
//  ...

あなたが提供したリンクを見ると、パーサーが 1 つしかないため、FlexLexer.h インクルードを削除する必要があるのではないかと思います。

于 2012-08-13T18:38:32.407 に答える