I am trying to compile lex.yy.c and y.tab.c with C++ code, here is the Make status -
(base) rajatkmitra@spider:~/modeler> make
flex ./src/lex.l
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o main.o ./src/main.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o convertFloatToFixed.o ./src/convertFloatToFixed.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o convertProductFloatToFixed.o ./src/convertProductFloatToFixed.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o printer.o ./src/printer.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o vectorToString.o ./src/vectorToString.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o printFixedPointProduct.o ./src/printFixedPointProduct.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o fixedPointFormatter.o ./src/fixedPointFormatter.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o tokenize.o ./src/tokenize.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o y.tab.o y.tab.c
bison -y -d ./src/bison.y
./src/bison.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o lex.yy.o lex.yy.c
###############################################################################
# Building main.o convertFloatToFixed.o convertProductFloatToFixed.o printer.o vectorToString.o
printFixedPointProduct.o fixedPointFormatter.o tokenize.o y.tab.c lex.yy.c
###############################################################################
g++ -Wno-write-strings -I ./ main.o convertFloatToFixed.o convertProductFloatToFixed.o printer.o vectorToString.o printFixedPointProduct.o fixedPointFormatter.o tokenize.o y.tab.c lex.yy.c -o lynx -lm
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: /tmp/cc8jVMLM.o: in function `yylex()':
lex.yy.c:(.text+0x343): undefined reference to `yyerror(char*)'
collect2: error: ld returned 1 exit status
make: *** [Makefile:71: lynx] Error 1
----Makefile----
####################################################################
# Library Paths
####################################################################
####################################################################
#Sources, use vpath and $CC/$LEX/$YACC should have arguments $<
#debug %make --just-print should show simulate make procedure
####################################################################
INCLUDE=-I ./
LEXSRC=lex.l
YACCSRC=bison.y
SRC=main.cc convertFloatToFixed.cc convertProductFloatToFixed.cc \
printer.cc vectorToString.cc printFixedPointProduct.cc fixedPointFormatter.cc \
tokenize.cc y.tab.c lex.yy.c
vpath %cc ./src
vpath %l ./src
vpath %y ./src
#####################################################################
#Compiler Settings
#####################################################################
OBJCC=$(SRC:.cc=.o)
OBJC=$(SRC:.c=.o)
EXE=lynx
DEFINE=#-D _XOPEN_SOURCE
CFLAGS=$(INCLUDE) $(DEFINE) $(LIBPATH) -c -Wall -Wreorder -Wno-write-strings \
-Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm
CXXFLAGS=$(CFLAGS)
CC=g++
LEX=flex
YACC=bison -y -d
######################################################################
#Build Rules
######################################################################
new: all
all:$(SRC) $(EXE)
# These dependency rules indicate that (1) lex.yy.o depends on
# lex.yy.c and y.tab.h and (2) lex.yy.o and y.tab.o depend on calc.h.
# Make uses the dependencies to figure out what rules must be run when
# a file has changed.
lex.yy.o: lex.yy.c y.tab.h
lex.yy.o y.tab.o:
## This rule will use yacc to generate the files y.tab.c and y.tab.h
## from our file $(YACCSRC).y
y.tab.c y.tab.h: $(YACCSRC)
$(YACC) $<
## this is the make rule to use lex to generate the file lex.yy.c from
## our file $(LEXSRC).lex
lex.yy.c: $(LEXSRC)
$(LEX) $<
## for lex.yy.c and y.tab.c
%.c.o:
$(CC) $(CFLAGS) $< -o $@
## all other C++ files
%.cc.o:
$(CC) $(CFLAGS) $< -o $@
$(EXE):$(OBJCC) $(OBJC)
@echo \###############################################################################
@echo \# Building $(OBJCC)
@echo \###############################################################################
$(CC) -Wno-write-strings $(INCLUDE) $(OBJCC) $(LIBPATH) $(LIB) -o $@ -lm
clean:
rm -rf $(EXE) *~ *.o lex.yy.c y.tab.h
Okay so here is the grammar file bison.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
int yylex();
void yyerror(const char *s);
/*|--------------------------
for global parsing
-----------------------------|*/
unsigned int attributeFlag;
%}
/*Possible types from lexer*/
%union {
int ival;
double fval;
const char *sval;
}
/*Possible tokens*/
%token KWREAL
%token <ival> INTEGER
%token <fval> FLOAT;
%token <sval> VARIABLE
/*associativity*/
%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
/*parse rules*/
%%
description:
description decl_attributes {}
| description stmt_list {}
| description real_variable_decl {}
| decl_attributes {}
| stmt_list {}
| real_variable_decl {}
;
decl_attributes:
attribute {}
| decl_attributes attribute {}
;
attribute:
open_attribute several_attribute_assignments close_attribute
real_variable_decl
{
attributeFlag = 0;
}
;
open_attribute:
'(' '*' {attributeFlag = 1;}
;
close_attribute:
'*' ')' {}
;
several_attribute_assignments:
integer_assignment {}
| continued_attribute_assignments integer_assignment {}
;
continued_attribute_assignments:
integer_assignment ',' {}
| continued_attribute_assignments integer_assignment ',' {}
;
real_variable_decl:
KWREAL VARIABLE ';'
{
}
;
stmt_list:
stmt { }
| stmt_list stmt { }
;
stmt:
VARIABLE '=' expr ';' {printf("%s\n\n",$1); }
| integer_assignment ';' { }
;
integer_assignment:
VARIABLE '=' INTEGER
{
if(attributeFlag==1){
if(strcmp($1, "S")==0){
//attrContainer.isSigned = $3;
}else if(strcmp($1, "IB")==0){
//attrContainer.intBits = $3;
}else if(strcmp($1, "FB")==0){
//attrContainer.fracBits = $3;
}
}
}
;
expr:
VARIABLE { printf("%s\n",$1); }
| FLOAT { printf("%f\n",$1); }
| '-' expr %prec UMINUS { }
| expr '+' expr { }
| expr '-' expr { }
| expr '*' expr { }
| expr '/' expr { }
| expr '<' expr { }
| expr '>' expr { }
| expr GE expr { }
| expr LE expr { }
| expr NE expr { }
| expr EQ expr { }
| '(' expr ')' { }
;
%%
/*|-----------------------------------------------------
Parsing Functions
-----------------------------------------------------|*/
/*Definition of yyerror*/
void yyerror(const char *s)
{
extern int yylineno; // defined and maintained in lex.c
extern char *yytext; // defined and maintained in lex.c
printf("ERROR: %s on line %d\n", yytext, yylineno);
}
and the lexer -
%{
#include <stdlib.h>
#include <stdio.h>
#include "y.tab.h"
void yyerror(char *);
%}
%%
"real" return KWREAL;
[a-zA-Z][a-zA-Z]* {
//yylval.sval= *yytext - 'a';
yylval.sval = strdup(yytext);
return VARIABLE;
}
0 {
yylval.ival = atoi(yytext);
return INTEGER;
}
[1-9][0-9]* {
yylval.ival = atoi(yytext);
return INTEGER;
}
(([0-9]*\.[0-9]*)([eE][-+]?[0-9]+)?) {
yylval.fval = atof(yytext);
return FLOAT;
}
[-()<>=+*/;,{}.] {
return *yytext;
}
">=" return GE;
"<=" return LE;
"==" return EQ;
"!=" return NE;
#[^\n]* { /* Discard preprocessor comments. */ }
"//"[^\n]* { /* Discard c99 comments. */ }
[ \t\n]+ ; /* ignore whitespace */
. yyerror("Unknown character");
%%
int yywrap(void) {
return 1;
}
This is the main routine main.cc
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
/*------------------------------------------------
Front end parser
------------------------------------------------*/
extern void yyparse(void);
extern FILE *yyin;
int main(int argc, char **argv)
{
/*------------------------
parse the file
------------------------*/
/*open file handle to a file of interest*/
if(argc < 2){
printf("Usage: main <filename> \n");
exit(-1);
}
yyin = fopen(argv[1],"r");
if(yyin==NULL){
printf("Could not open file !\n");
exit(-1);
}
/*Parse the design*/
do{
yyparse();
}while(!feof(yyin));
}
So there you go! I have added the Minimal Reproducable Example. When I compile everything with g++ I end up getting a linker error that does not find the yyerror() routine in yylex()
g++ -Wno-write-strings -I ./ y.tab.o lex.yy.o main.o -o lynx -lm -lfl -
std=c++11
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld:
lex.yy.o: in function yylex()': /home/rajatkmitra/modeler/minimal/lex.l:46: undefined reference to
yyerror(char*)'
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld:
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../lib64/libfl.so: undefined
reference to `yylex'
collect2: error: ld returned 1 exit status
make: *** [Makefile:68: lynx] Error 1
Changes Made to get this environment to work -
(1) Compile ALL sources including the output from lex and yacc with g++
(2) yyerror arguments are (char *s) and NOT (const char *s)
(2) do not link with -lfl as this is not not required with g++
extern "C"
block somewhere is to blame, but yeah, need a minimal reproducible example. Emphasis on minimal. – Shawn