| Home | Libraries | People | FAQ | More

#### Complex - Our first complex parser

Well, not really a complex parser, but a parser that parses complex numbers. This time, we're using 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:

- One or two real numbers in parentheses, separated by comma (the second number is optional)
- OR a single real number.

This parser can parse complex numbers of the form:

    (123.45, 987.65)
    (123.45)
    123.45

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

                space);

            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
Those with experience using 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.