使用自定义属性解析来提升精神规则

时间:2010-06-27 16:06:40

标签: boost attributes boost-spirit boost-spirit-qi boost-phoenix

我正在编写一个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

我希望这个语法产生Paira等于double,b等于某个常量。我想做这样的事情:

pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator;

当然,上面没有编译。我尝试将构造函数添加到Pair,但我仍然遇到编译错误(没有匹配函数来调用'Pair :: Pair(const boost :: phoenix :: actor&gt;&amp;,double)' )。

1 个答案:

答案 0 :(得分:6)

首先,pairSequence的签名必须是:

qi::rule<Iterator, std::vector<Pair>()> pairSequence; 

作为列表运算符公开std::vector<Pair>作为其属性。

从语义动作中调用的所有函数都必须是“懒惰的”,所以你需要利用凤凰:

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序列进行调整。