我尝试了解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
- 等效类型吗?如果没有,那么为什么甚至在规则中设置类型?以及如何正确使用它们?
答案 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;
};