shailavi shah
shailavi shah

Reputation: 181

Undefined reference to `yylex'

I am trying to parse one input file using flex and bison but I am facing one difficulty while compiling my program. I am attaching my flex and bison code and error which I am getting.

Please help me out to solve these errors

lex.l

%{
 #include <iostream>  
 #include <stdio.h>
#include "yacc.tab.h"
 #define YY_DECL extern "C" int yylex()

using namespace std;  


%}

DOT             "."  
COLON           ":"  
SEMICOLON       ";"  
COMMA           ","  
ANGLE_LEFT      "<"  
ANGLE_RIGHT     ">"  
AT              "@"  
EQUAL           "="  
SQUARE_OPEN     "["  
SQUARE_CLOSE    [^\\]"]"  
OPENBRACE       "\("  
CLOSEBRACE      "\)"  
QUOTE           "\""  
QUOTE_OPEN      "\""  
QUOTE_CLOSE     [^\\]"\""  
SPACE           " "  
TAB             "\t"  
CRLF            "\r\n"  
QUOTED_PAIR     "\\"[^\r\n]  
DIGIT           [0-9]  
ALPHA           [a-zA-Z]  
QTEXT           [0-9a-zA-Z!#$%&'()*+,\-.\/:;<=>?@\[\]^_`{|}~]  

%%

[a-zA-Z0-9]+            { yylval.sval = strdup(yytext); return TOK_STRING; }

{SPACE}*                    {return TOK_SPACE; }

{SPACE}*Name.*              {return TOK_NAME; }  
{SPACE}*SIZE.*              {return TOK_SIZE; }  
{SPACE}*ITERATE.*           {return TOK_ITERATE; }  
{SPACE}*DIRECTION.*     {return TOK_DIRECTION; }  

^{CRLF}                         { return TOK_EMPTY_LINE; }  
{CRLF}                          {}  
.                               {}/* ignore unknown chars */  

yacc.y

 %{
 #include <cstdio> 
 #include <cstring>
 #include <iostream>
 #include <stdio.h>

using namespace std;

extern "C" int yylex();  
extern "C" FILE *yyin;

void yyerror(const char* s);  


%}

%union  
{  
    char* sval;  
};  

%token <sval> TOK_NAME  
%token <sval> TOK_SIZE  
%token <sval> TOK_STRING  
%token <sval> TOK_ITERATE  
%token <sval> TOK_DIRECTION  


%token TOK_SPACE  


%%

str:  
    TOK_SPACE TOK_NAME TOK_SPACE TOK_STRING   
    {  
        cout << "Value:" << $2 << "->" << $4;  
    }  
    ;  
%%  

int main(void) {  
    FILE * pt = fopen("new file ", "r" );  
    if(!pt)  
    {  
    cout << "Bad Input.Noexistant file" << endl;  
    return -1;  
    }  
    yyin = pt;  
    do  
    {  
        yyparse();  
     }while (!feof(yyin));        
}  
void yyerror(const char *s)  
{  
   cout << "Error. " << s << endl;   
   exit(-1);     
}  

I build these using:

flex bas.l 
bison -d yacc.y 
g++ lex.yy.c yacc.tab.c -lfl -o scanner.exe 

While compiling program I found following errors:

/tmp/cceIyDkD.o: In function `main':
yacc.tab.c:(.text+0x708): multiple definition of `main'
/tmp/ccatq95p.o:lex.yy.c:(.text+0x1228): first defined here
/usr/bin/ld: Warning: size of symbol `main' changed from 86 in /tmp/ccatq95p.o to 120 in /tmp/cceIyDkD.o
/tmp/cceIyDkD.o: In function `yyparse()':
yacc.tab.c:(.text+0x2d6): undefined reference to `yylex'
collect2: ld returned 1 exit status

Please help me out

Upvotes: 4

Views: 20244

Answers (4)

foxesque
foxesque

Reputation: 1040

I had the same issue trying to compile a Flex + Bison program with C++ while not using them in C++ mode (which is an other headscratcher of its own).

First in your .y file add extern "C" int yylex(void); in the declaration section.

Then look for this line in the source generated by Flex, the yy.c file or similar:

extern int yylex (void);

and replace it with

extern "C" int yylex (void);

This hack "solved" it for me, but there should be a better solution.

Upvotes: 1

Gustavo Oliveira
Gustavo Oliveira

Reputation: 93

I had a similar problem, it turns out that flex 2.6.x changed the way yylex behaves. I solved this problem by using an older version of Flex. In Ubuntu, there's this package called flex-old that is that older version. Replacing flex by flex-old solved this problem for me.

Upvotes: 8

Aleksandar Makragić
Aleksandar Makragić

Reputation: 1997

  1. In parser.y, more precisely C part of the code where you include stuff, you need to write: extern int yylex(void);. Extern keyword is not needed, because global functions by default have dynamic connectivity, but it is good practice to write keyword to point that function is not from that file you're working. Your code has no mistake here however.

  2. Compile lex.yy.c to the object file, compile y.tab.c to object file and then link them together in final program. It is very important to first do yacc command, because Lex is using yacc.tab.h generated with Yacc. You're getting error because you flex it, but you don't know what yacc.tab.h is.

    yacc -d yacc.y Make y.tab.c

    g++ -c y.tab.c -o y.tab.o Compile y.tab.c to object file y.tab.o

    flex lex.l Make lex.yy.c

    g++ -c lex.yy.c -o lex.yy.o Compile lex.yy.c to object file lex.yy.o

    g++ lex.yy.o y.tab.o -o program Link them together.

Note: Make sure that in your lex file you include "y.tab.h" after other includes, because it is possible that other includes use some function declared in y.tab.h, so have that in mind. Situations like this can occur when you're writing more complex parsers.

Upvotes: 3

You have some errors in the code which stop it from compiling. You need to add into the file yacc.y:

%token <sval> TOK_EMPTY_LINE 

and at the end:

#include "lex.yy.c"

and build this way:

flex bas.l 
bison -d yacc.y 
g++ yacc.tab.c -lfl -o scanner.exe 

You will find it now compiles.

You may want to note I removed a couple of typos in your lexer source in the question. Not all the the rules started in the first column. I removed a couple of leading spaces on the basis that they were typos.

Upvotes: 2

Related Questions