| Home | Libraries | People | FAQ | More

#### Parser Basics

###### Lazy Argument

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

    p(a1, a2,..., aN)

where `p` is a parser. 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 parser'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 parsers need to know which character set a `char` or `wchar_t` is operating on. For example, the `alnum` parser works differently with ISO8859.1 and ASCII encodings. Where necessary, Spirit encodes (tags) the parser 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 parsers such as `alnum`, `space` etc.

Example:

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

Namespaces:

- boost::spirit::ascii
- boost::spirit::iso8859_1
- boost::spirit::standard
- boost::spirit::standard_wide

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

- boost::spirit::qi::ascii
- boost::spirit::qi::iso8859_1
- boost::spirit::qi::standard
- boost::spirit::qi::standard_wide

###### 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/support_utree.hpp>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/phoenix/core.hpp>
    #include <boost/phoenix/operator.hpp>
    #include <boost/fusion/include/adapt_struct.hpp>
    #include <boost/assert.hpp>
    #include <boost/predef/other/endian.h>
    #include <boost/proto/deep_copy.hpp>
    #include <iostream>
    #include <string>
    #include <cstdlib>

Our test functions:

These functions test the parsers without attributes.

    template <typename P>
    void test_parser(
        char const* input, P const& p, bool full_match = true)
    {
        using boost::spirit::qi::parse;

        char const* f(input);
        char const* l(f + strlen(f));
        if (parse(f, l, p) && (!full_match || (f == l)))
            std::cout << "ok" << std::endl;
        else
            std::cout << "fail" << std::endl;
    }

    template <typename P>
    void test_phrase_parser(
        char const* input, P const& p, bool full_match = true)
    {
        using boost::spirit::qi::phrase_parse;
        using boost::spirit::qi::ascii::space;

        char const* f(input);
        char const* l(f + strlen(f));
        if (phrase_parse(f, l, p, space) && (!full_match || (f == l)))
            std::cout << "ok" << std::endl;
        else
            std::cout << "fail" << std::endl;
    }

These functions test the parsers with user supplied attributes.

    template <typename P, typename T>
    void test_parser_attr(
        char const* input, P const& p, T& attr, bool full_match = true)
    {
        using boost::spirit::qi::parse;

        char const* f(input);
        char const* l(f + strlen(f));
        if (parse(f, l, p, attr) && (!full_match || (f == l)))
            std::cout << "ok" << std::endl;
        else
            std::cout << "fail" << std::endl;
    }

    template <typename P, typename T>
    void test_phrase_parser_attr(
        char const* input, P const& p, T& attr, bool full_match = true)
    {
        using boost::spirit::qi::phrase_parse;
        using boost::spirit::qi::ascii::space;

        char const* f(input);
        char const* l(f + strlen(f));
        if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
            std::cout << "ok" << std::endl;
        else
            std::cout << "fail" << std::endl;
    }

The `print_info` utility function prints information contained in the `info` class.

    struct printer
    {
        typedef boost::spirit::utf8_string string;

        void element(string const& tag, string const& value, int depth) const
        {
            for (int i = 0; i < (depth*4); ++i) // indent to depth
                std::cout << ' ';

            std::cout << "tag: " << tag;
            if (value != "")
                std::cout << ", value: " << value;
            std::cout << std::endl;
        }
    };

    void print_info(boost::spirit::info const& what)
    {
        using boost::spirit::basic_info_walker;

        printer pr;
        basic_info_walker<printer> walker(pr, what.tag, 0);
        boost::apply_visitor(walker, what.value);
    }

###### String

###### Header

    // forwards to <boost/spirit/home/support/string_traits.hpp>
    #include <boost/spirit/support_string_traits.hpp>

A string can be any object `s`, of type, `S`, that satisfies the following expression traits:

Expression | Semantics
--- | ---
`boost::spirit::traits::is_string<S>` | Metafunction that evaluates to `mpl::true_` if a certain type, `S` is a string, `mpl::false_` otherwise (See MPL Boolean Constant).
`boost::spirit::traits::char_type_of<S>` | Metafunction that returns the underlying char type of a string type, `S`.
`boost::spirit::traits::get_c_string(s)` | Function that returns the underlying raw C-string from `s`.
`boost::spirit::traits::get_begin(s)` | Function that returns an STL iterator from `s` that points to the beginning the string.
`boost::spirit::traits::get_end(s)` | Function that returns an STL iterator from `s` that points to the end of the string.

###### Models

Predefined models include:

- any literal string, e.g. "Hello, World",
- a pointer/reference to a null-terminated array of characters
- a `std::basic_string<Char>`

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