如何在Boost.Spirit中创建类似于double_的自己的解析器?

时间:2012-01-18 10:04:16

标签: c++ boost-spirit

我尝试了解Boost.Spirit的工作原理。不幸的是,文档对我来说太简陋了,我无法弄清楚它是如何工作的。

所以,让我们转向我的问题。我尝试为std::complex类型编写解析器,它将以与内置解析器相同的方式工作,例如int_double_。我希望它以不同的形式解析复杂的数字,例如1.2+2i3-i*45*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规则(以及realdouble()参数,而不是Complex()。它不应该使占位符为double - 等效类型吗?如果没有,那么为什么甚至在规则中设置类型?以及如何正确使用它们?

1 个答案:

答案 0 :(得分:1)

您可以使用boost::phoenix::construct

#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <complex>
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix.hpp>

namespace qi = boost::spirit::qi;
using namespace boost::spirit::qi;
namespace phx = boost::phoenix;

typedef std::complex<double> Complex;
typedef std::string::iterator Iterator;

struct complex_parser : qi::grammar<Iterator, Complex(), ascii::space_type>
{
    complex_parser() : complex_parser::base_type(value)
    {
        real = (
            double_[_val = _1]
        );

        imaginary = (
            ( double_[_val = phx::construct<Complex>(0.0, _1)] >> -(lit('*')) >> 'i' )
          | ( 'i' >> -(lit('*')) >> double_[_val = phx::construct<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, Complex(), ascii::space_type> imaginary;
};
相关问题