Undefined reference to `_yyerror' when compiling with Flex and Bison

fanulis picture fanulis · Jun 15, 2013 · Viewed 11.7k times · Source

I'm trying to make a compiler for a mini Pascal-like language. I'm using Flex and Bison for this and I came up with this error.

My Flex file:

%{
#include "y.tab.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
void yyerror(char *);
%}

%%

[1-9][0-9]*     {
                yylval.i = atoi(yytext);
                return INT;
}

program     return PROGRAM;
or          return OR;
and         return AND;
not         return NOT;
if          return IF;
else        return ELSE ;
while       return WHILE;
"+"         return PLUS;
"-"         return MINUS;
"*"         return MUL;
"/"         return DIV;
"["         return LSB;
"]"         return RSB;
"{"         return LCB;
"}"         return RCB;
"("         return LEFTPAR;
")"         return RIGHTPAR;
":="        return ASSIGN;
"=="        return ISEQUAL;
"<"         return LTHAN;
">"         return GTHAN;
"<>"        return NOTEQUAL;
"<="        return LESSEQUAL;
">="        return GREATEREQUAL;

[a-zA-z][a-z0-9]*   {
                    yylval.s = (char*)malloc(strlen(yytext)*sizeof(char));
                    strcopy(yylval.s,yytext);
                    return ID;
}               

[ \t\n]+                            /* eat up whitespace */         

.                                   yyerror("Unknown Character");

%%
int yywrap(void) {
    return 1;
}

My Bison file:

%{
    #include <stdio.h>
    #include <string.h>
    int yylex(void);
    void yyerror(char *s);
%}

%union {
    int i;
    char *s;
};

%token <i> INTEGERNUM

%token PROGRAM;
%token OR;
%token AND;
%token NOT;
%token IF;
%token ELSE;
%token WHILE;
%token PLUS;
%token MINUS;
%token MUL;
%token DIV;
%token LSB;
%token RSB;
%token LCB;
%token RCB;
%token LEFTPAR;
%token RIGHTPAR;
%token ID;
%token INT;
%token ASSIGN;
%token ISEQUAL;
%token LTHAN;
%token GTHAN;
%token NOTEQUAL;
%token LESSEQUAL;
%token GREATEREQUAL;

%%

program:
        PROGRAM ID block
        ;

block:
        LCB sequence RCB
        ;

sequence:
        statement ';' sequence
        | statement ';' 
        ;

bracketsSeq:
        LCB sequence RCB
        ;

brackOrStat:        
        bracketsSeq
        | statement
        ;

statement:
        assignmentStat
        |ifStat
        |whileStat
        |
        ;

assignmentStat:
        ID ':=' expression

ifStat:
        IF LEFTPAR condition RIGHTPAR brackOrStat elsepart
        ;

elsepart:
        ELSE brackOrStat
        |
        ;

whileStat:
        WHILE LEFTPAR condition RIGHTPAR brackOrStat
        ;

expression:
        optionalSign expression
        |expression addOper expression
        |term
        ;

term:
        term mulOper term
        |factor
        ;

factor:
        INT
        |LEFTPAR expression RIGHTPAR
        |ID
        ;

condition:
        condition AND condition
        |boolterm
        ;

boolterm:
        boolterm OR boolterm
        |boolfactor
        ;

boolfactor:
        NOT LSB condition RSB
        |LSB condition RSB
        |expression relationalOper expression
        ;

relationalOper:
        ISEQUAL
        |LTHAN
        |GTHAN
        |NOTEQUAL
        |LESSEQUAL
        |GREATEREQUAL
        ;

addOper:
        PLUS
        |MINUS
        ;

mulOper:
        MUL
        |DIV
        ;

optionalSign:
        addOper
        |
        ;

%%

int main( int argc, char **argv )
             {
             printf("TEST\n");

             }      

The series of steps I executed was:

$ ./bison.exe -dy comp.y
$ ./flex.exe comp.l
$ gcc -c -w lex.yy.c 
$ gcc -c -w comp.tab.c
$ gcc comp.tab.o lex.yy.o -o ex
comp.tab.o:comp.tab.c:(.text+0x4cd): undefined reference to `_yyerror'
comp.tab.o:comp.tab.c:(.text+0x61c): undefined reference to `_yyerror'
lex.yy.o:lex.yy.c:(.text+0x34a): undefined reference to `_strcopy'
lex.yy.o:lex.yy.c:(.text+0x362): undefined reference to `_yyerror'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/ld: lex.yy.o: bad reloc address                0x828 in section `.rdata'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/ld: final link failed: Invalid                operation
collect2: ld returned 1 exit status
$

Any advice as to what to declare and where cause there seems to be that I have declared something the wrong way!

Answer

rici picture rici · Jun 16, 2013

It's not enough to declare yyerror. You must provide a definition.

The bison manual suggests the following as a minimal implementation:

 void yyerror (char const *s) {
   fprintf (stderr, "%s\n", s);
 }

The other problem you have is that you misspelled strcpy in your flex file.

More accurately, the other problem revealed by the linker errors is the misspelled strcpy, because your copying code is incorrect. It does not account for the NUL byte which must terminate strings. strcpy will copy that byte, with the result that it will write a 0 in unallocated storage. You'll find it much simpler to use strdup. (And don't forget that you need to free the strings when you're finished with them.)