c++ - Spirit::Qi :延迟绑定(bind)到 google-protobuf

标签 c++ boost-spirit boost-phoenix

我一直在用 boost::spirit 实现一个解析器,它需要在输出时生成 google::protobuf 生成的类。

我试图跟随 page作为背景。不幸的是,我不能使用属性语法,因为 google::protobuf 生成的类只提供 set/get 方法。因此,我尝试使用 boost::phoenix 进行延迟绑定(bind),但我不确定如何从 A 类绑定(bind) add_param() 方法(参见下面的代码和第 99 行的注释):

#define BOOST_SPIRIT_DEBUG

#include <string>
#include <iostream>
#include <sstream>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/std_pair.hpp>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

class A
{
public:
    A(): _i(0) {}
    A(int i) : _i(i) 
    {
        std::cout << "i=" << i << std::endl;
    }

    void set_i(int i) 
    { 
        _i = i; 
    }

    void add_param(const std::string& value)
    {
        _params.push_back(value);
    }

    std::string to_string() const
    {
        std::stringstream ss;
        ss << "_i=[" << _i << "], _params=[";
        for (auto& p : _params)
            ss << p << ",";
        ss << "]" << std::endl;
        return ss.str();
    }

private:
    int _i;
    std::vector < std::string > _params;
};

class B
{
public:
    B() : _id(), _av() {}
    B(int id, const std::vector<A>& av) : _id(id), _av(av) {}

    void set_id(int id)
    {
        _id = id;
    }

    void add_A(const A& a)
    {
        _av.push_back(a);
    }

    std::string to_string() const
    {
        std::stringstream ss;
        ss << "_id=[" << _id << "], _av=[";
        for (auto& av : _av)
            ss << av.to_string() << ",";
        ss << "]" << std::endl;
        return ss.str();
    }
private:
    int _id;
    std::vector<A> _av;
};

namespace Utils
{
    int mul2(int i) 
    { 
        return i * 2; 
    }
}

template <typename Iterator, typename Skipper>
struct grammar_B: qi::grammar<Iterator, Skipper>
{
    grammar_B(B& ctx) : grammar_B::base_type(start)
    {
        // A
        i_rule = qi::int_[ qi::_val = phx::bind(Utils::mul2, qi::_1) ];
        param_rule = *(qi::char_ - ',' - '!');

        a_rule = (qi::lit("$")
                  >> i_rule
                  >> qi::lit(":")
                  >> *(param_rule >> +(qi::lit(","))) // how to bind to A::add_param() ?
                  >> qi::lit("!")) [ qi::_val = phx::construct<A>(qi::_1) ];

        // B
        id_rule = qi::int_[ phx::bind(&B::set_id, phx::ref(ctx), qi::_1) ];     

        start %= id_rule >> qi::lit("=") >> a_rule;

        BOOST_SPIRIT_DEBUG_NODE(id_rule);
        BOOST_SPIRIT_DEBUG_NODE(i_rule);
        BOOST_SPIRIT_DEBUG_NODE(param_rule);
    }
private:
    qi::rule<Iterator, Skipper> start;

    qi::rule<Iterator, int, Skipper> i_rule;
    qi::rule<Iterator, std::string(), Skipper> param_rule;
    qi::rule<Iterator, A(), Skipper> a_rule;

    qi::rule<Iterator, int, Skipper> id_rule;
};

int main(int argc, char* argv[])
{

    std::string input = "1=$100:param1,param2!";
    B ctx;
    grammar_B<decltype(std::begin(input)), qi::space_type> p(ctx);

    auto f(std::begin(input)), l(std::end(input));

    if (qi::phrase_parse(f, l, p, qi::space))
        std::cout << "Success: " << ctx.to_string() << std::endl;
    else
        std::cout << "failed" << std::endl;

    return 0;
}

Coliru Example

现在,我有 2 个问题:

1) 我的方法是否可以通过一般的延迟绑定(bind)来实现?

2) 如何将 std::vector<> 生成的属性绑定(bind)到 A::add_param() 之类的方法?

--

谢谢

最佳答案

好的,我终于能够实现我需要的东西了: Coliry Example

关于c++ - Spirit::Qi :延迟绑定(bind)到 google-protobuf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39973024/

相关文章:

c++ - 对于 ~95% 写入/5% 读取线程安全的 unordered_map 是否有简单的解决方案?

c++ - 使用 Phoenix Bind 绑定(bind) boost 信号

c++ - 用精神解析成类?

c++ - 使用 boost::phoenix::val 的动机?

c++ - Boost phoenix 或 lambda 库问题:从 std::vector 中删除元素

c++ - 比较 vector 中的元素并返回对象的最佳方法

c# - 如何将 struct 从 C# managed 传递到 C++ unmanaged DLL 并获得 struct 结果?

c++ - 在类中封装多个 if 语句的最简单方法?

c++ - 是否可以使用 mpl::map 来初始化符号解析器?

c++ - Boost Binary Endian 解析器不工作?