I have a project for school where we need to use flex and bison. I want to use C++ so that I have access to STL and my own classes that I wrote. We were provided with the following Makefile:
CC = gcc
CFLAGS = -g
OBJs = parse.tab.o symtab.o attr.o lex.yy.o
default: parser
parser: ${OBJs}
${CC} ${CFLAGS} ${OBJs} -o parser -lfl
lex.yy.c: scan.l parse.tab.h attr.h
flex -i scan.l
parse.tab.c: parse.y attr.h symtab.h
bison -dv parse.y
parse.tab.h: parse.tab.c
clean:
rm -f parser lex.yy.c *.o parse.tab.[ch] parse.output
depend:
makedepend -I. *.c
scan.l and parse.y have some initial flex/bison stuff to generate the scanner and parser. I need to add my own stuff to those files. symtab.{h, c} is supposed to be a implementation of a symbol table. attr.{h, c} are for some attribute magic. I want to make symtab.c a .cc file so I can use STL. I also have other reasons for wanting to use C++.
I tried to use a parse.ypp file, so that a .cpp file would be generated. But the problem is that I'm not getting the right .h file. I changed the Makefile to look like this:
CC = g++ # Change gcc to g++
CFLAGS = -g
OBJs = lex.yy.o parse.tab.o symtab.o attr.o
default: lex.yy.c parser # added lex.yy.c so I could just keep lex stuff in C since I don't really need C++ there
parser: ${OBJs}
${CC} ${CFLAGS} ${OBJs} -o parser -lfl
lex.yy.o: scan.l parse.tab.h attr.h # added this rule to use gcc instead of g++
gcc -c -o lex.yy.o lex.yy.c
lex.yy.c: scan.l parse.tab.h attr.h
flex -i scan.l
parse.tab.cpp: parse.ypp attr.h symtab.h
bison -dv parse.ypp
parse.tab.h: parse.tab.cpp # I want a parse.tab.h but I get parse.tab.hpp
clean:
rm -f parser lex.yy.c *.o parse.tab.cpp parse.tab.h parse.output
depend:
makedepend -I. *.c
Can someone tell me what I need to add or do to get C++ working? It should be noted I added some stuff in the .y (or .ypp) file to deal with moving from C to C++. In particular, I had to declare some stuff as extern. My main problem is that when I run make, scan.l has a bunch of syntax errors, and they seem to be because it cannot include parse.tab.h (because it is never generated).
Thanks for your help.
-
Use either a C Compiler or a C++ compiler but not both (till you know what you are upto). You are sure to shoot yourself many times on both your feet otherwise. Mixing gcc and g++ isn't good.
This line is suspect:
lex.yy.o: scan.l parse.tab.h attr.h # added this ... gcc -c -o lex.yy.o lex.yy.c
Also, you don't seem to be using
CC
anywhere, using that'd have made life easier.Assuming you don't change a single line of the C code, you will possibly hit some errors and quite a few warnings (like deprecated headers etc). You'll have to fix them as well.
-
You don't need to do anything with flex or bison to use C++, I have done it many times. You just have to make sure you use g++, not gcc.
Your problems are with the Makefile, not the code.
Tom : Accepting this pretty late :-)... but as I recall this was right and I just needed to play around with my makefile. thanks. -
If you are doing parsers in C++ I would recommend to look at Boost Spirit. It is so much nicer to handle than bison/yacc.
From here:
Spirit is an object-oriented recursive-descent parser generator framework implemented using template meta-programming techniques. Expression templates allow us to approximate the syntax of Extended Backus-Normal Form (EBNF) completely in C++.
Zifre : I disagree. I have tried both and I like bison better (although I prefer ANTLR over both). The weird syntax needed to fit EBNF into C++ makes it very hard to read grammars.Scottie T : Not an option in this case, since he's required to use bison/flex for his project. Beside, not everything in C++ need be done with Boost.Hippicoder : Spirit is one of the worst and overly complicated C++ libraries out there. If anything its nothing more than a whimsical attempt at seeing what kind of operators one can overload in C++.Kasper Peeters : Moreover, Spirit is horribly unstable. Even the most trivial examples fail to compile from one version to the next, often just with a non-explanatory compiler error. -
There are some differences that you can check out in detail here.
-
For using flex with C++: 1: read the flex docs: 2: use flex -+ -o file.cc parser.ll 3: In the .ll file: %option c++ %option yyclass="Your_class_name" %option batch 4: In your .hh file, derive Your_class_name from public yyFlexLexer 5: you can then use your_class_instance.yylex()
piotr : For example, for my robots.txt flex parser which is built with scons it's as simple as: thisenv.CXXFile(target='Robots_flex.cc',source='robots.ll') And Robots.cc constructor has: Robots::Robots(std::istream* in) : yyFlexLexer(in,0), [...]
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.