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

AJM*_*AJM 3 attributes boost boost-spirit boost-phoenix boost-spirit-qi

我正在编写一个Boost Spirit语法来将文本解析为这些结构的向量:

struct Pair
{
    double a;
    double b;
};

BOOST_FUSION_ADAPT_STRUCT(
    Pair,
    (double, a)
    (double, a)
)
Run Code Online (Sandbox Code Playgroud)

这个语法有这样的规则:

qi::rule<Iterator, Pair()> pairSequence;
Run Code Online (Sandbox Code Playgroud)

但是,实际的语法pairSequence是这样的:

double_ % separator
Run Code Online (Sandbox Code Playgroud)

我想这个语法产生一个Pair具有a等于双层并b等于某个常数.我想做这样的事情:

pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator;
Run Code Online (Sandbox Code Playgroud)

当然,上面没有编译.我尝试添加一个构造函数Pair,但我仍然得到编译错误(没有匹配函数调用'Pair :: Pair(const boost :: phoenix :: actor>&,double)').

hka*_*ser 6

首先,签名pairSequence需要:

qi::rule<Iterator, std::vector<Pair>()> pairSequence; 
Run Code Online (Sandbox Code Playgroud)

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

从语义动作中调用的所有函数都必须是"懒惰的",所以你需要使用phoenix:

namespace phx = boost::phoenix;

pairSequence = 
    double_[
        phx::push_back(_val, 
            phx::construct<Pair>(_1, phx::val(DEFAULT_B))
        )
    ] % separator
; 
Run Code Online (Sandbox Code Playgroud)

另一种可能性是将(非显式)构造函数添加到Pair:

struct Pair         
{         
    Pair(double a) : a(a), b(DEFAULT_B) {}

    double a;         
    double b;         
};         
Run Code Online (Sandbox Code Playgroud)

这允许简化语法:

pairSequence = double_ % separator; 
Run Code Online (Sandbox Code Playgroud)

并完全依赖Spirit的内置属性传播规则.

顺便说一句,对于任何这个工作,你不需要适应PairFusion序列.