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;
}
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