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


Complex - Our first complex parser

Well, not really a complex parser, but a parser that parses complex numbers. This time, we're using Boost.Phoenix to do the semantic actions.

Here's a simple parser expression for complex numbers:

    '(' >> double_ >> -(',' >> double_) >> ')'
|   double_

What's new? Well, we have:

  1. Alternates: e.g. a | b. Try a first. If it succeeds, good. If not, try the next alternative, b.
  2. Optionals: e.g. -p. Match the parser p zero or one time.

The complex parser presented above reads as:

This parser can parse complex numbers of the form:

(123.45, 987.65)

Here goes, this time with actions:

namespace client
    template <typename Iterator>
    bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
        using boost::spirit::qi::double_;
        using boost::spirit::qi::_1;
        using boost::spirit::qi::phrase_parse;
        using boost::spirit::ascii::space;
        using boost::phoenix::ref;

        double rN = 0.0;
        double iN = 0.0;
        bool r = phrase_parse(first, last,

            //  Begin grammar
                    '(' >> double_[ref(rN) = _1]
                        >> -(',' >> double_[ref(iN) = _1]) >> ')'
                |   double_[ref(rN) = _1]
            //  End grammar


        if (!r || first != last) // fail if we did not get a full match
            return false;
        c = std::complex<double>(rN, iN);
        return r;

The full cpp file for this example can be found here: ../../example/qi/complex_number.cpp

[Note] Note

Those with experience using Boost.Phoenix might be confused with the placeholders that we are using (i.e. _1, _2, etc.). Please be aware that we are not using the same placeholders supplied by Phoenix. Take note that we are pulling in the placeholders from namespace boost::spirit::qi. These placeholders are specifically tailored for Spirit.

The double_ parser attaches this action:

ref(n) = _1

This assigns the parsed result (actually, the attribute of double_) to n. ref(n) tells Phoenix that n is a mutable reference. _1 is a Phoenix placeholder for the parsed result attribute.