I try to learn how Boost.Spirit works. Unfortunately, the documentation is too laconic for me and I can't figure out, how it really works.
So, let's move to my problem. I try to write parser for std::complex
type, that will work in the same way like built-in parsers, e.g. int_
or double_
. I want it to parse complex number in different forms, like 1.2+2i
, 3-i*4
, 5*i
, etc. And, to be honest, I stuck and don't know, what to do. I have tried this approach:
typedef std::complex<double> Complex;
struct complex_parser : qi::grammar<Iterator, Complex(), ascii::space_type>
{
complex_parser() : complex_parser::base_type(value)
{
real = (
double_[_val = _1]
);
imaginary = (
( double_[_val = Complex(0.0, _1)] >> -(lit('*')) >> 'i' )
| ( 'i' >> -(lit('*')) >> double_[_val = Complex(0.0, _1)] )
);
value = (
imaginary[_val = _1]
| real[_val = _1] >> -('+' >> imaginary[_val += _1])
| real[_val = _1] >> -('-' >> imaginary[_val -= _1])
);
}
qi::rule<Iterator, Complex(), ascii::space_type> value;
qi::rule<Iterator, double(), ascii::space_type> real;
qi::rule<Iterator, double(), ascii::space_type> imaginary;
};
But it does not work. Doesn't even compile, because when imaginary
is parsed, placeholder _1
is not double
type:
error C2665: 'std::complex::complex' : none of the 6 overloads could convert all the argument types [...] while trying to match the argument list '(double, const boost::spirit::_1_type)'
But why? I gave in imaginary
rule (as well as in real
) double()
parameter, instead of Complex()
. Shouldn't it make placeholder be of double
-equivalent type? If not, then why even set the type in rules? And how to use them properly?