What is the best way to handle multiple Flex/Bison parsers inside a project?
I wrote a parser and now I need a second one in the same project. So far in the third section of parser1.y
I inserted the main(..)
method and called yyparse
from there.
What I want to obtain is having two different parsers (parser1.y
and parser2.y
) and be able to use them from an external function (let's assume main
in main.cpp
).
Which precautions should I use to export yyparse
functions outside .y
files and how should I handle two parsers?
PS. I'm using g++ to compile but not the C++ versions of Flex and Bison and I would like to keep it this way (so avoiding encapsulating the parser inside an object).
Note that Bison provides the '-p zz' option to prefix symbols with 'zz' instead of 'yy'.
Similarly, Flex provides the '-P zz' option to prefix symbols with 'zz' instead of 'yy'. It uses '-p' for performance reporting. 'Tis a pity they are not consistent with each other.
If you use Bison 3.0 or better, then have a look at
%define api.prefix {foo_}
, which replaces allyy
andYY
prefixes withfoo_
andFOO_
.See the Documentation about Multiple Parsers.
Between Bison 2.6 and 3.0, there used to be no braces:
%define api.prefix foo_
.In addition to what was already stated, if you use a '%define api.prefix {PREFIX}' it will also rename yytext && yyparse to PREFIXtext and PREFIXparse. Don't forget the {} around the prefix !
The same applies to '%option prefix="PREFIX"' in lex, your lexer will be renamed to PREFIXlex.
The api.prefix variable is not working for me anymore (it's producing a compilation error)
I had to use the following syntax
In addition to Leffler's answer, I'd like to provide another approach here:
In the
.lex
file you could use%option prefix="PREFIX"
, and in the.y
file you could use%define api.prefix PREFIX
, which does the same thing as passing-p PREFIX
to Bison and-P PREFIX
to Flex.Notice after the overriding of the default prefix
yy
, you can access internal names via BOTH the originalyy*
and your overriddenPREFIX*
, while obviously for external names you MUST use yourPREFIX*
to access them.