我正在编写一个 Boost Spirit 语法来将文本解析为这些结构的向量:
struct Pair
{
double a;
double b;
};
BOOST_FUSION_ADAPT_STRUCT(
Pair,
(double, a)
(double, a)
)
这个语法有这样的规则:
qi::rule<Iterator, Pair()> pairSequence;
然而,pairSequence
的实际语法是这样的:
double_ % separator
我希望此语法生成一个 Pair
,其中 a
等于 double,b
等于某个常量。我想做这样的事情:
pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator;
当然,以上不会编译。我尝试向 Pair
添加一个构造函数,但我仍然遇到编译错误(没有匹配函数来调用 'Pair::Pair(const boost::phoenix::actor >&, double) ')。
最佳答案
首先是pairSequence
的签名需要:
qi::rule<Iterator, std::vector<Pair>()> pairSequence;
因为列表运算符公开了一个 std::vector<Pair>
作为它的属性。
从语义 Action 内部调用的所有函数都必须是“惰性”的,因此您需要利用 phoenix:
namespace phx = boost::phoenix;
pairSequence =
double_[
phx::push_back(_val,
phx::construct<Pair>(_1, phx::val(DEFAULT_B))
)
] % separator
;
另一种可能性是向 Pair
添加一个(非显式)构造函数:
struct Pair
{
Pair(double a) : a(a), b(DEFAULT_B) {}
double a;
double b;
};
这允许简化语法:
pairSequence = double_ % separator;
并且完全依赖于 Spirit 的内置属性传播规则。
顺便说一句,要使其中的任何一个起作用,您不需要调整 Pair
作为 fusion 序列。
关于通过自定义属性解析 boost Spirit 规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3127909/