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

在网上看,我发现这个 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 - 编译 libclassparser_la.all_cc.cc 时出错:“class yyFlexLexer”重新定义的链接。

问题是 FlexLexer.h 标头有一种奇怪的方式来处理自身的多个包含。tokenizer.l (tokenizer.cc) 和 ClassParser.cc 都间接包含这个头文件,并且在单独的编译中它们工作正常;但是在编译连接源时,“#define yyFlexLexer yyFlexLexer”声明(由 flex 插入)从 tokenizer.cc 传递到 ClassParser.cc,并对第二个包含造成严重破坏。(在上面引用的错误消息中,两个 FlexLexer.h 行分别是第二个和第一个包含项。)

/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>
//  ...

查看您提供的链接,我想知道您是否需要删除 FlexLexer.h 包含,因为您只有一个解析器。

于 2012-08-13T18:38:32.407 回答