How to inherit from yyFlexLexer?
Asked Answered
S

1

6

I'm writing trying to learn flex / bison. I've got some basic c examples now, but I'd like to move on to doing a C++ AST tree. c++ makes this type of object oriented program easier than C. However, there seems to be an issue with the c++ generation from Flex and I'm unsure how to resolve it. I want to add some methods for warning/error reporting so I was going to inherit from yyFlexLexer and in my '.l' file call stuff like warning(const char* str) and error(const char* str) where appropriate.

However, I get a 'yyFlexLexer redefinition' error among others when I try to perform inheritance in the way I BELIEVE the documentation says to do this.

lexer.l

%option nounistd
%option noyywrap
%option c++
%option yyclass="NLexer"

%{
#include "NLexer.h"
#include <iostream>
using namespace std;
%}

%%
[ \t]+
\n  { return '\n';}
[0-9]+(\.[0-9]+)? { cout << "double: " << atof(YYText()) << endl;}
. {return YYText()[0];}
%%

int main(int , char**) 
{
    NLexer lexer;
    while(lexer.yylex() != 0) { };

    return 0;
}

NLexer.h

#ifndef NLEXER_H
#define NLEXER_H
#include <FlexLexer.h>

class NLexer : public yyFlexLexer
{
public:
    virtual int yylex();
};

#endif

Lots of errors:

Error 1 error C2011: 'yyFlexLexer' : 'class' type redefinition c:\users\chase_l\documents\visual studio 2013\projects\nlanguage\nlanguage\include\flexlexer.h 112 1 NLanguage

Error 2 error C2504: 'yyFlexLexer' : base class undefined c:\users\chase_l\documents\visual studio 2013\projects\nlanguage\nlanguage\nlexer.h 6 1 NLanguage

About 80 more related to identifiers inside yyFlexLexer don't exist.

I could post the generated cpp file but it is a 1500 line auto-generated mess.

Edit: Apparently it is an issue with the MacroDefinition of yyFlexLexer so it can generate different base classes xxFlexLexer and so on. If you only need 1 lexer in your project (probable) you can just do the following to get it to work. If someone has a way that is better than that let me know.

#ifndef NLEXER_H
#define NLEXER_H

#undef yyFlexLexer
#include <FlexLexer.h>

class NLexer : public yyFlexLexer
{
public:
    virtual int yylex();
};

#endif
Sufi answered 17/11, 2016 at 19:33 Comment(1)
This answer could be also helpful.Argentum
I
8

Inside the generated lexer.yy.cc file you can find an old comment about your problem:

/* The c++ scanner is a mess. The FlexLexer.h header file relies on the * following macro. This is required in order to pass the c++-multiple-scanners * test in the regression suite. We get reports that it breaks inheritance. * We will address this in a future release of flex, or omit the C++ scanner * altogether. */

#define yyFlexLexer yyFlexLexer

yyFlexLexerOnce include guard could be used to overcome it. NLexer.h:

#ifndef NLEXER_H
#define NLEXER_H

#if !defined(yyFlexLexerOnce)
#include <FlexLexer.h>
#endif

class NLexer : public yyFlexLexer
{
public:
    virtual int yylex();
};

#endif
Intrinsic answered 17/11, 2016 at 21:15 Comment(2)
Yeah that comment was why I tried #undef. I like that solution more though as it appears cleaner. Appreciated.Sufi
Could not agree more that the Flex++ scanner generator is a mess. I tried the new RE/flex scanner generator, which surprisingly worked well with your example except that I had to replace #include "FlexLexer.h" with #include <reflex/flexlexer.h>. Perhaps this could be useful to those seeking a free open source alternative to Flex++? Disclosure: I work on/with RE/flex.Middendorf

© 2022 - 2024 — McMap. All rights reserved.