Search code examples
c++flex-lexer

build error : undefined reference to `yyFlexLexer::yyFlexLexer(std::istream*, std::ostream*)


I have used Flex in my application on windows machine and the compiler is mingw32-make. I got an an build error on My C++ code.

I have done Flex installation and I have done routed include and lib directory on PATH.
The code line is:

const char * filename;

std::fstream file;

file.open(filename, std::ios_base::in);

yyFlexLexer * scanner;

scanner = new yyFlexLexer(&file);

The error is:

"File.cpp:63: undefined reference to `yyFlexLexer::yyFlexLexer(std::istream*, std::ostream*)'"

Please help me to resolve this issue.

Thanks in advance!


Solution

  • File.cpp:63: undefined reference to `yyFlexLexer::yyFlexLexer(std::istream*, std::ostream*)
    

    This means that your c++ lexer is either undefined, or defined under a different name.

    You can't write the following, without compiling and linking the flex file:

    #include <fstream>
    #include <FlexLexer.h>
    int main()
    {
      const char * filename= "file.txt";;
      std::fstream file;
      file.open(filename, std::ios_base::in);
    
      // better use auto scanner = std::make_unique<yyFlexLexer>(&file)
      yyFlexLexer * scanner; 
      // leaks memory
      scanner = new yyFlexLexer(&file);
    }
    

    The above won't work without writing a flex file, running flex (which by default generates lex.yy.cc), and then compiling and linking the generated code. You can read all about it in Generating C++ Scanners.

    If you did compile and link the generated code, you still may get this error if a named scanner was created. Basically, if your program has more than one scanner, giving different names to different scanners is the correct solution. In that case you need to access the correct name.

    This is all in the flex manual, at the Generating C++ Scanners section. Which I quote here:

    If you want to create multiple (different) lexer classes, you use the `-P' flag (or the `prefix=' option) to rename each yyFlexLexer to some other xxFlexLexer. You then can include `<FlexLexer.h>' in your other sources once per lexer class, first renaming yyFlexLexer as follows:

    #undef yyFlexLexer 
    #define yyFlexLexer xxFlexLexer 
    #include <FlexLexer.h> 
    
    #undef yyFlexLexer   
    #define yyFlexLexer zzFlexLexer   
    #include <FlexLexer.h> 
    

    if, for example, you used `%option prefix="xx"' for one of your scanners and `%option prefix="zz"' for the other.

    This is ugly and tricky, but it is the way flex works with C++. This has been documented as experimental since the 90's, or before. I assume that it won't change.