c++ - 在 C++ 中使用 flexlexer 重载 yylex()

标签 c++ lex flex-lexer

我正在尝试用 lex 编写一个简单的解析器,然后用 c++ 来完成。我按照指示开始了 here

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

我不明白这个错误。发生了什么事?

最佳答案

在网络上我发现了这个 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 .

The problem is that the FlexLexer.h header has a strange way of handling multiple inclusions of itself. tokenizer.l (tokenizer.cc) and ClassParser.cc both include this header indirectly, and in separate compilation they work fine; but when compiling concatenated source, a "#define yyFlexLexer yyFlexLexer" declaration (inserted by flex) carries through from tokenizer.cc to ClassParser.cc, and causes havoc on the second inclusion. (In the error message quoted above, the two FlexLexer.h lines are the second and first inclusions, respectively.)

The/A solution is to "#undef yyFlexLexer" at the end of tokenizer.l, and I will attach a patch that does this with an explanation why.

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 包含,因为您只有一个解析器。

关于c++ - 在 C++ 中使用 flexlexer 重载 yylex(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11939584/

相关文章:

c++ - ofstream operator<< 访问冲突错误

c# - 两张脸对比

c++ - 为什么模板参数包必须在最后?

c - 用于生成 AWK 扫描器的 FLEX - 识别变量

c++ - 使用像 std::string 这样有趣的类型来保存一些标记类型

c++ - 为什么我不能在 C++11 中创建一个 lambda vector (相同类型)?

python - 消除 PLY 语法中的这种 Shift-Reduce 冲突

linux - Lex文件无法识别的规则

c - 在 lex 的定义和规则部分中编写语句之间的区别

compiler-construction - lex 程序中对 yylval 的 undefined reference