通过自定义属性解析 boost Spirit 规则

标签 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

我希望此语法生成一个 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/

相关文章:

c++ - 使用用户定义的比较器 boost bimap set_of

c++ - 使用 socketio-client-c++ 和 boost asio io_service 时访问冲突异常

jquery - attr ('defaultValue' )使用 jQuery 1.6.3 返回未定义

c# - 以编程方式向验证器添加属性

c++ - 如何使用 Boost 的 vf2_subgraph_iso 检测 multimap 上的子图同构?

ios - 无法链接胖iOS静态库

ruby - Ruby 中的方法和属性有什么区别?

c++ - 具有相同简单改编结构属性的 boost::spirit::qi 规则会产生编译错误

c++ - 使用boost Spirit解析带有二进制信封的文本文件

c++ - 使用 boost::spirit 在 C++ 中读取二维数组