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

PrevUpHomeNext

Generator Basics

Lazy Argument

Some generators (e.g. primitives and non-terminals) may take in additional attributes. Such generators take the form:

g(a1, a2,..., aN)

where g is a generator. Each of the arguments (a1 ... aN) can either be an immediate value, or a function, f, with signature:

T f(Unused, Context)

where T, the function's return value, is compatible with the argument type expected and Context is the generator's Context type (The first argument is unused to make the Context the second argument. This is done for uniformity with Semantic Actions).

Character Encoding Namespace

Some generators need to know which character set a char or wchar_t is operating on. For example, the alnum generator works differently with ISO8859.1 and ASCII encodings. Where necessary, Spirit encodes (tags) the generator with the character set.

We have a namespace for each character set Spirit will be supporting. That includes ascii, iso8859_1, standard and standard_wide (and in the future, unicode). In each of the character encoding namespaces, we place tagged versions of generators such as alnum, space etc.

Example:

using boost::spirit::ascii::space; // use the ASCII space generator

Namespaces:

For ease of use, the components in this namespaces are also brought into the karma sub-namespaces with the same names:

Examples

All sections in the reference present some real world examples. The examples use a common test harness to keep the example code as minimal and direct to the point as possible. The test harness is presented below.

Some includes:

#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/support_utree.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <iostream>
#include <string>

The used output iterator:

typedef std::back_insert_iterator<std::string> output_iterator_type;

Our test functions:

This one tests the generators without attributes.

template <typename G>
void test_generator(char const* expected, G const& g)
{
    std::string s;
    std::back_insert_iterator<std::string> out(s);
    if (boost::spirit::karma::generate(out, g) && s == expected)
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

These test the generators with one or more user supplied attributes.

template <typename G, typename T>
void test_generator_attr(char const* expected, G const& g, T const& attr)
{
    std::string s;
    std::back_insert_iterator<std::string> out(s);
    if (boost::spirit::karma::generate(out, g, attr) && s == expected)
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

template <typename G, typename T1, typename T2>
void test_generator_attr(char const* expected, G const& g, T1 const& attr1,
    T2 const& attr2)
{
    std::string s;
    std::back_insert_iterator<std::string> out(s);
    if (boost::spirit::karma::generate(out, g, attr1, attr2) && s == expected)
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

This tests the generators with one attribute and while using delimited output.

template <typename G, typename Delimiter, typename T>
void test_generator_attr_delim(char const* expected, G const& g, Delimiter const& d, T const& attr)
{
    std::string s;
    std::back_insert_iterator<std::string> out(s);
    if (boost::spirit::karma::generate_delimited(out, g, d, attr) && s == expected)
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

The examples of the binary generators use one or more of the following tests.

template <typename G>
void test_binary_generator(char const* expected, std::size_t size, G const& g)
{
    std::string s;
    std::back_insert_iterator<std::string> out(s);
    if (boost::spirit::karma::generate(out, g) && !std::memcmp(s.c_str(), expected, size))
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

template <typename G, typename T>
void test_binary_generator_attr(char const* expected, std::size_t size, G const& g, T const& attr)
{
    std::string s;
    std::back_insert_iterator<std::string> out(s);
    if (boost::spirit::karma::generate(out, g, attr) && !std::memcmp(s.c_str(), expected, size))
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

Models

Predefined models include:

The namespace boost::spirit::traits is open for users to provide their own specializations. The customization points implemented by Spirit.Karma usable to customize the behavior of generators are described in the section Customization of Attribute Handling.


PrevUpHomeNext