Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Click here to view the latest version of this page.
PrevUpHomeNext

Spirit FAQ

I'm getting multiple symbol definition errors while using Visual C++. Anything I could do about that?

Do you see strange multiple symbol definition linker errors mentioning boost::mpl::failed and boost::spirit::qi::rule? Then this FAQ entry might be for you.

Boost.Mpl implements a macro BOOST_MPL_ASSERT_MSG() which essentially is a more powerful version of static_assert. Unfortunately under certain circumstances using this macro may lead to the aforementioned linker errors.

Spirit allows you to define a preprocessor constant disabling the usage of BOOST_MPL_ASSERT_MSG(), while switching to BOOST_STATIC_ASSERT() instead. For that you need define BOOST_SPIRIT_DONT_USE_MPL_ASSERT_MSG=1. Do this by adding

-DBOOST_SPIRIT_DONT_USE_MPL_ASSERT_MSG=1

on the compiler command line or by inserting a

#define BOOST_SPIRIT_DONT_USE_MPL_ASSERT_MSG 1 

into your code before any Spirit headers get included.

Using this trick has no adverse effects on any of the functionality of Spirit. The only change you might see while using this workaround is less verbose error messages generated from static_assert.

I'm very confused about the header hell in my boost/spirit directory. What's all this about?

The boost/spirit directory currently holds two versions of the Spirit library: Spirit.Classic (former V1.8.x) and SpiritV2. Both are completely independent and usually not used at the same time. Do not mix these two in the same grammar.

Spirit.Classic evolved over years in a fairly complex directory structure:

boost/spirit/actor
boost/spirit/attribute
boost/spirit/core
boost/spirit/debug
boost/spirit/dynamic
boost/spirit/error_handling
boost/spirit/iterator
boost/spirit/meta
boost/spirit/symbols
boost/spirit/tree
boost/spirit/utility

While introducing Spirit V2 we restructured the directory structure in order to accommodate two versions at the same time. All of Spirit.Classic now lives in the directory

boost/spirit/home/classic 

where the directories above contain forwarding headers to the new location allowing to maintain application compatibility. The forwarding headers issue a warning (starting with Boost V1.38) telling the user to change their include paths. Please expect the above directories/forwarding headers to go away soon.

This explains the need for the directory

boost/spirit/include

which contains forwarding headers as well. But this time the headers won't go away. We encourage application writers to use only the includes contained in this directory. This allows us to restructure the directories underneath if needed without worrying application compatibility. Please use those files in your application only. If it turns out that some forwarding file is missing, please report this as a bug.

Spirit V2 is not about parsing only anymore (as Spirit.Classic). It now consists out of 3 parts (sub-libraries): Spirit.Qi, Spirit.Karma, and Spirit.Lex. The header files for those live in

boost/spirit/home/qi
boost/spirit/home/karma
boost/spirit/home/lex

and have forwarding headers in

boost/spirit/include

Spirit.Qi is the direct successor to Spirit.Classic as it implements a DSEL (domain specific embedded language) allowing to write parsers using the syntax of C++ itself (parsers in the sense turning a sequence of bytes into an internal data structure). It is not compatible with Spirit.Classic, the main concepts are similar, though.

Spirit.Karma is the counterpart to Spirit.Qi. It implements a similar DSEL but for writing generators (i.e. the things turning internal data structures into a sequence of bytes, most of the time - strings). Spirit.Karma is the Yang to Spirit.Qi's Yin, it's almost like a mirrored picture.

Spirit.Lex is (as the name implies) a library allowing to write lexical analyzers. These are either usable stand alone or can be used as a front end for Spirit.Qi parsers. If you know flex you shouldn't have problems understanding Spirit.Lex. This library actually doesn't implement the lexer itself. All it does is to provide an interface to pre-existing lexical analyzers. Currently it's using Ben Hansons excellent Lexertl library (proposed for a Boost review, BTW) as its underlying workhorse.

Again, don't use any of the header files underneath the boost/spirit/home directory directly, always include files from the boost/spirit/include directory.

The last bit missing is Boost.Phoenix (which currently still lives under the Spirit umbrella, but already has been accepted as a Boost library, so it will move away). Boost.Phoenix is a library allowing to write functional style C++, which is interesting in itself, but as it initially has been developed for Spirit, it is nicely integrated and very useful when it comes to writing semantic actions. I think using the boost/spirit/include/phoenix_... headers will be safe in the future as well, as we will probably redirect to the Boost.Phoenix headers as soon as these are available.

Why doesn't my symbol table work in a no_case directive?

In order to perform case-insensitive parsing (using no_case) with a symbol table (i.e. use a symbols<> parser in a no_case directive), that symbol table needs to be filled with all-lowercase contents. Entries containing one or more uppercase characters will not match any input.

I'm getting a compilation error mentioning boost::function and/or boost::function4. What does this mean?

If you are using Visual C++ and have an error like:

error C2664: 'bool boost::function4<R,T0,T1,T2,T3>::operator ()(T0,T1,T2,T3) const' :
    cannot convert parameter 4 from '...' to '...'

or you are using GCC and have an error like:

error: no match for call to '(const boost::function<bool ()(...)>) (...)'
note: candidates are: ... boost::function4<R,T1,T2,T3,T4>::operator()(T0,T1,T2,T3) const [with ...]

then this FAQ entry may help you.

The definition of a Rule or Grammar may contain a skip parser type. If it does, it means that non-terminal can only be used with a skip parser of a compatible type. The error above arises when this is not the case, i.e.:

[Note] Note

The same applies to Spirit.Karma, replacing 'skip parser' and lexeme by 'delimit generator' and verbatim. Similarily, corresponding error messages in Spirit.Karma reference boost::function3 and the 3rd parameter (instead of the 4th).


PrevUpHomeNext