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 compile an example from book flex and Bison . I was wondering why I got the following build error, and how I can correct it?

$ make
bison -d fb1-5.y
fb1-5.y: warning: 3 shift/reduce conflicts [-Wconflicts-sr]
flex fb1-5.l
cc -o  fb1-5.tab.c lex.yy.c -lfl
fb1-5.l: In function ‘yylex’:
fb1-5.l:27:3: warning: implicit declaration of function ‘yyerror’; did you mean ‘perror’? [-Wimplicit-function-declaration]
 . { yyerror("Mystery character %c\n", *yytext); }
   ^~~~~~~
   perror
/tmp/cctl5WLj.o: In function `yylex':
lex.yy.c:(.text+0x32f): undefined reference to `yylval'
lex.yy.c:(.text+0x363): undefined reference to `yyerror'
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'fb1-5' failed
make: *** [fb1-5] Error 1

Makefile:

fb1-5:  fb1-5.l fb1-5.y
    bison -d fb1-5.y
    flex fb1-5.l
    cc -o  fb1-5.tab.c lex.yy.c -lfl

fb1-5.y

/* simplest version of calculator */
#  include <stdio.h>
/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token OP CP
%token EOL
calclist: /* nothing */
 | calclist exp EOL { printf("= %d\n> ", $2); }
 | calclist EOL { printf("> "); } /* blank line or a comment */
exp: factor
 | exp ADD exp { $$ = $1 + $3; }
 | exp SUB factor { $$ = $1 - $3; }
 | exp ABS factor { $$ = $1 | $3; }
factor: term
 | factor MUL term { $$ = $1 * $3; }
 | factor DIV term { $$ = $1 / $3; }
term: NUMBER
 | ABS term { $$ = $2 >= 0? $2 : - $2; }
 | OP exp CP { $$ = $2; }
main()
  printf("> "); 
  yyparse();
yyerror(char *s)
  fprintf(stderr, "error: %s\n", s);

fb1-5.l:

/* recognize tokens for the calculator and print them out */
# include "fb1-5.tab.h"
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|"     { return ABS; }
"("     { return OP; }
")"     { return CP; }
[0-9]+  { yylval = atoi(yytext); return NUMBER; }
\n      { return EOL; }
"//".*  
[ \t]   { /* ignore white space */ }
.   { yyerror("Mystery character %c\n", *yytext); }
                @Tim liby defines a yyerror() implementation (if no other one is defined), -lfl provides a yywrap default implementation. At least on my system, other systems may handle this otherwise. Usually, -ly and -ll (or -lfl) should be specified to be safe on many platforms.
– Ctx
                Feb 7, 2019 at 22:01
                You have your own implementation of yyerror(), so you probably wouldn't need -ly for that, but it doesn't hurt.
– Ctx
                Feb 7, 2019 at 22:03
                Thanks. (1) can you explain why the error in my post? (2) run your command, cc: error: fb1-5.tab.c: No such file or directory. (3) Is the output file of flex always lex.yy.c? Can there be more than one  input flex files in the same directory, and thus overwriting one another?
– Tim
                Feb 7, 2019 at 21:11
                @tim: you can tell flex what filename to use with the -o option, just like cc. In both cases, you need to follow the option with the name of the desired output file. (Which is the problem with your cc invocation.)
– rici
                Feb 7, 2019 at 21:19
                no if you are compiling it with the same name it will overwrite it if it compiles successfully
– Spinkoo
                Feb 7, 2019 at 21:24
  • yyerror is not declared in your scanner (or, for that mattet in your parser). Bison does not generate a declaration for it so you need to declare it in any translation unit which uses it.

  • cc -o fb1-5.tab.c lex.yy.c -lfl tells the C compiler to compile lex.yy.c placing the resulting executable (the output of the compiler) into fb1-5.tab.c. That's not what you intended. It overwrites the generated parser with an executable, and does not compile the generated parser with the result that symbols defined in the parser are not available to the linker.

  • Thanks. (1) yyerror is defined in fb1-5.y. (2) cc -o fb-1.5 fb1-5.tab.c lex.yy.c -lfl -ly doesn't work, because cc: error: fb1-5.tab.c: No such file or directory – Tim Feb 7, 2019 at 21:26 @tim: the fact that yyerror is defined in the parser does not make its declaration available in the lexer. The compiler is complaining that yyerror is undeclared, which is different from the linker complaining that it is undefined. – rici Feb 7, 2019 at 21:29 I don't know why bison isn't creating fb1-5.tab.c; it probably had to do with some wierdness in your distro. Add -o fb1-5.tab.c to your bison command. – rici Feb 7, 2019 at 21:33 @tim: the makefile in the book says -o $@. You left out the $@. (But $@ is a make syntax. It won't work on the command line.) – rici Feb 7, 2019 at 21:49

    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.