#Flex & Bison LALR C++ example#
What?
This is a not-so-crude example showing how to deploy Flex and GNU Bison in modern C++ programs. Example program provides simple commandline that parses function calls with list of arguments (unsigned ints only) and builds AST. AST is printed when parsing completes. See code comments for more details.
Features:
- Compatible with the good, old
C++03
for maximum portability. - Fully reentrant parser and lexer, C++ implementation.
- Parser and lexer are in a customized namespace with custom class names.
- Flex base class has a customized name; multiple different flex scanners in the binary are possible without a name conflict. Believe it or not, but even in the 21st century it is still a bit tricky with Flex.
- Parser and scanner enclosed in a "driver" class (
Interpreter
) - Uses Bison 3.0 token variant API (yay!).
- Location tracking. Not perfect, but the core is there.
Once we overcome the abovementioned obstacles, the Flex/GNU Bison pair becomes quite pleasant to use in day to day work.
Disclaimer
Haven't tested it on MS Windows. Please tell me if it works there... Do not forget to turn off unistd.h
in options.
Why bother?
Official GNU Bison example features C++ parser connected to primitive C-style lexer, which is probably not what you want most of the time. There is currently (2014) no easy way to find a true C++ example of elegant Flex/Bison3 deployment. I really do not understand why a serious project like Bison provides such a poor user-experience for beginners.
##Yea, but still, why bother with old Flex/Bison?##
ANTLR4 has been released without C++ support nor any estimation (last checked September 2014). The Java generator is premium quality though.
ANTRL3 explicitly states that C++ support is total garbage and the mailing lists didn't make my impression any better.
Flexc++ and Bisonc++ are not that popular. I wasn't sure about portability either.
Flex and GNU Bison don't pull any dependencies and the code is (or at least is claimed to be) portable. By "portable" I mean it works in Unix universe and Windows, because the latter one is the only platform on the planet being notorious for catastrophically imbecilic design decisions (cmd.exe
, http:\\www.microsoft.com\backslash\fetish
, etc), causing endless, epic portability issues and developer's nightmares.
Source organization
The main function creates the Interpreter
object and calls parse()
. Scanner
and Parser
are encapsulated in the Interpreter
. By default the Scanner
reads the standard input, but you can switch it using the provided Interpreter
API and feed it with an arbitrary stream, such as std::stringstream
.
Building
Crude Makefile is provided - not much...
make
./a.out
make clean
Legal mumbo-jumbo
The example code is MIT-licensed. The code generated by Flex and Bison has a separate license: Modified, non-viral GPL, which is safe to use. See the source code files.
TODO
- some kind of template to deploy a complete scanner/parser stub in a project with an IDE wizard
- namespace defined with preprocessor?
Special thanks
- My girl - for late coffees and feeding me during deep coding sessions
- Flex and GNU Bison folks - for focus on portability and years of maintenance
- MIT folks - for MIT License
- Me - for assembling this example
Enjoy!