2016-10-11 4 views
1

J'ai implémenté un analyseur avec boost :: spirit qui doit générer une classe google :: protobuf générée en sortie.Spirit :: Qi: Liaison différée à google-protobuf

J'ai essayé de suivre le page comme arrière-plan. Malheureusement, je ne peux pas utiliser la grammaire d'attribut car les classes générées par google :: protobuf ne fournissent que des méthodes set/get. Donc, j'ai essayé defered lier avec boost :: Phoenix mais je ne suis pas sûr de savoir comment lier méthode add_param() de la classe A (voir ci-dessous le code et la ligne 99 avec un commentaire):

#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

Pour l'instant, j'ai 2 questions:

1) Est-ce que mon approche peut être implémentée avec la liaison différée en général?

2) Comment lier un attribut std :: vector <> à une méthode comme A :: add_param()?

-

Merci

Répondre