Я пытаюсь узнать, как работает Boost.Spirit . К сожалению, документация для меня слишком лаконична, и я не могу понять, как она на самом деле работает.
Итак, давайте перейдем к моей проблеме. Я пытаюсь написать парсер для типа std::complex
, который будет работать так же, как встроенные парсеры, например int_
или double_
. Я хочу, чтобы он разбирал комплексное число в разных формах, таких как 1.2+2i
, 3-i*4
, 5*i
и т. Д. И, если честно, я застрял и не знаю, что делать. Я пробовал этот подход:
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;
};
Но это не работает. Даже не компилируется, потому что когда imaginary
анализируется, заполнитель _1
не является double
типом:
ошибка C2665: 'std :: complex :: complex': ни одна из 6 перегрузок не может преобразовать все типы аргументов [...] при попытке сопоставить список аргументов '(double, const boost :: spirit :: _1_type) '
Но почему? Я дал imaginary
правило (а также real
) double()
параметр вместо Complex()
. Разве это не должно сделать заполнитель double
-эквивалентного типа? Если нет, то зачем вообще устанавливать тип в правилах? И как правильно их использовать?