Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am trying to run an example I found online of a calculator. But I have this error showing every time I run my gcc command. Here are the commands that I run:

flex -l calc3.l
yacc -vd calc3.y
gcc y.tab.c -lm -ll

-> at this point I got this error message:

/tmp/ccPOq58f.o : In function 'yyparse':
y.tab.c: undefined reference to 'yylex' 
collect2: error: ld returned 1 exit status

Here is my code:

calc3.l

#include <stdlib.h> #include "calc3.h" #include "y.tab.h" void yyerror(char *); [a-z] { yylval.sIndex = *yytext - 'a'; return VARIABLE; 0 { yylval.iValue = atoi(yytext); return INTEGER; [1-9][0-9]* { yylval.iValue = atoi(yytext); return INTEGER; [-()<>=+*/;{}.] { return *yytext; ">=" return GE; "<=" return LE; "==" return EQ; "!=" return NE; "while" return WHILE; "if" return IF; "else" return ELSE; "print" return PRINT; [ \t\n]+ ; /* ignore whitespace */ . yyerror("Unknown character"); int yywrap(void) { return 1;

here is calc3.h

typedef enum { typeCon, typeId, typeOpr } nodeEnum;
/* constants */
typedef struct {
    int value;                  /* value of constant */
} conNodeType;
/* identifiers */
typedef struct {
    int i;                      /* subscript to sym array */
} idNodeType;
/* operators */
typedef struct {
    int oper;                   /* operator */
    int nops;                   /* number of operands */
    struct nodeTypeTag **op;    /* operands */
} oprNodeType;
typedef struct nodeTypeTag {
    nodeEnum type;              /* type of node */
    union {
        conNodeType con;        /* constants */
        idNodeType id;          /* identifiers */
        oprNodeType opr;        /* operators */
} nodeType;
extern int sym[26];

and here is calc3.y

#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "calc3.h" /* prototypes */ nodeType *opr(int oper, int nops, ...); nodeType *id(int i); nodeType *con(int value); void freeNode(nodeType *p); int ex(nodeType *p); int yylex(void); void yyerror(char *s); int sym[26]; /* symbol table */ %union { int iValue; /* integer value */ char sIndex; /* symbol table index */ nodeType *nPtr; /* node pointer */ %token <iValue> INTEGER %token <sIndex> VARIABLE %token WHILE IF PRINT %nonassoc IFX %nonassoc ELSE %left GE LE EQ NE '>' '<' %left '+' '-' %left '*' '/' %nonassoc UMINUS %type <nPtr> stmt expr stmt_list program: function { exit(0); } function: function stmt { ex($2); freeNode($2); } | /* NULL */ stmt: ';' { $$ = opr(';', 2, NULL, NULL); } | expr ';' { $$ = $1; } | PRINT expr ';' { $$ = opr(PRINT, 1, $2); } | VARIABLE '=' expr ';' { $$ = opr('=', 2, id($1), $3); } | WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, $3, $5); } | IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, $3, $5); } | IF '(' expr ')' stmt ELSE stmt { $$ = opr(IF, 3, $3, $5, $7); } | '{' stmt_list '}' { $$ = $2; } stmt_list: stmt { $$ = $1; } | stmt_list stmt { $$ = opr(';', 2, $1, $2); } expr: INTEGER { $$ = con($1); } | VARIABLE { $$ = id($1); } | '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, $2); } | expr '+' expr { $$ = opr('+', 2, $1, $3); } | expr '-' expr { $$ = opr('-', 2, $1, $3); } | expr '*' expr { $$ = opr('*', 2, $1, $3); } | expr '/' expr { $$ = opr('/', 2, $1, $3); } | expr '<' expr { $$ = opr('<', 2, $1, $3); } | expr '>' expr { $$ = opr('>', 2, $1, $3); } | expr GE expr { $$ = opr(GE, 2, $1, $3); } | expr LE expr { $$ = opr(LE, 2, $1, $3); } | expr NE expr { $$ = opr(NE, 2, $1, $3); } | expr EQ expr { $$ = opr(EQ, 2, $1, $3); } | '(' expr ')' { $$ = $2; } nodeType *con(int value) { nodeType *p; /* allocate node */ if ((p = malloc(sizeof(nodeType))) == NULL) yyerror("out of memory"); /* copy information */ p->type = typeCon; p->con.value = value; return p; nodeType *id(int i) { nodeType *p; /* allocate node */ if ((p = malloc(sizeof(nodeType))) == NULL) yyerror("out of memory"); /* copy information */ p->type = typeId; p->id.i = i; return p; nodeType *opr(int oper, int nops, ...) { va_list ap; nodeType *p; int i; /* allocate node */ if ((p = malloc(sizeof(nodeType))) == NULL) yyerror("out of memory"); if ((p->opr.op = malloc(nops * sizeof(nodeType *))) == NULL) yyerror("out of memory"); /* copy information */ p->type = typeOpr; p->opr.oper = oper; p->opr.nops = nops; va_start(ap, nops); for (i = 0; i < nops; i++) p->opr.op[i] = va_arg(ap, nodeType*); va_end(ap); return p; void freeNode(nodeType *p) { int i; if (!p) return; if (p->type == typeOpr) { for (i = 0; i < p->opr.nops; i++) freeNode(p->opr.op[i]); free (p->opr.op); free (p); void yyerror(char *s) { fprintf(stdout, "%s\n", s); int main(void) { yyparse(); return 0; You need to compile calc3.l.c too. You only passing the generated parser to the compiler. – leppie Jan 29, 2015 at 10:58 Sorry I don't understand to which file you are refering to as calc3.l.c. I just have a calc3.l , calc3.y and calc3.h – user4506618 Jan 29, 2015 at 11:15
flex calc3.l

then flex produces a scanner called lex.yy.c. (I removed the -l option which was used in the original question. -l causes flex to be more compatible with certain aspects of the original lex utility, and it has no use except for compiling ancient lex scanners.)

Similarly, if you just use

yacc -vd calc3.y

the bison will produce files called y.tab.c and y.tab.h. And

gcc y.tab.c -lm -ll

will produce a file called a.out.

None of that is a good idea. It's far better to give the files meaningful names, based on the input filenames. All three of these tools understand a -o command-line flag which specifies the output name file.

So you could do this:

flex calc3.l
yacc -vd calc3.y
gcc lex.yy.c y.tab.c -lm -ll

But I'd recommend something like this:

flex -o calc3.lex.c calc3.l
bison -o calc3.tab.c -vd calc3.y
gcc -o calc3 calc3.lex.c calc3.tab.c -lm -ll

When you do this, you'll need to change the #include "y.tab.h" to #include "calc3.tab.h". (Note that if you invoke bison as bison rather than as yacc, it will automatically produce output files with names based on the grammar file. But it doesn't hurt to be explicit.)

Even better if you put it in a Makefile, or at least a script file.

After your answer and with same code, I got this error, any help will be appreciated, I can't get the difference /tmp/ccyL6zXM.o: In function 'yyparse': calc3.tab.c:(.text+0x4f0): undefined reference to 'ex' collect2: error: ld returned 1 exit status – Emre Akcan Apr 6, 2019 at 14:32 @emre: that code declares and uses a function called ex but apparently its definition is not included in the snippet. That has nothing to do with bison. – rici Apr 6, 2019 at 16:52 @SouravKannanthaB: good question. I don't remember why I didn't say anything about that. I certainly wouldn't use it myself, but it's legal and not relevant to the question. Maybe I'll add a note in the morning. – rici Jul 19, 2021 at 7:17 @rici I searched on Google for -l to find nothing. Please edit your answer to include that. – Sourav Kannantha B Jul 21, 2021 at 5:39

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.