(question tirée de Liste de diffusion Spirit-general )
Bonjour,
Je travaille dans un parseur avec spirit qi. La grammaire fonctionne bien, mais j'ai quelques problèmes pour remplir mon instance struct avec des actions sémantiques.
Avec les attributs directs de la structure, comme "Request.id" et "Request.url", le code fonctionne. Mais je ne sais pas comment remplir les attributs dans la structure imbriquée "Info", ni comment pousser les valeurs dans "Request.list".
Voici mon code (la chaîne à analyser peut avoir les valeurs dans n'importe quel ordre) :
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <vector>
#include <string>
struct Request
{
std::string id;
std::string url;
std::vector<std::string> list;
struct Info
{
std::string id;
std::string desc;
};
Info info;
};
BOOST_FUSION_ADAPT_STRUCT(
Request,
(std::string, id)
)
template <typename Iterator>
struct request_parser : boost::spirit::qi::grammar<Iterator, Request(), boost::spirit::ascii::space_type>
{
request_parser() : request_parser::base_type(start)
{
using namespace boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
start %=
BR_OP
>>((DQUOTE >> lit(INFO) >> DQUOTE >> COLON
>> BR_OP
>> ((DQUOTE >> lit(DESC) >> DQUOTE >> COLON >> quoted_string)
^ (DQUOTE >> lit(ID) >> DQUOTE >> COLON >> quoted_string)) % COMMA
>> BR_CL)
^(DQUOTE >> lit(ID) >> DQUOTE >> COLON >> quoted_string[phx::bind(&Request::id, _val) = _1])
^(DQUOTE >> lit(URL) >> DQUOTE >> COLON >> quoted_string[phx::bind(&Request::url, _val) = _1])
^(DQUOTE >> lit(LIST) >> DQUOTE >> COLON
>> SQ_OP
>> quoted_string % COMMA
>> SQ_CL)) % COMMA
>>
BR_CL
;
}
boost::spirit::qi::rule<Iterator, std::string(), boost::spirit::ascii::space_type> quoted_string;
boost::spirit::qi::rule<Iterator, Request(), boost::spirit::ascii::space_type> start;
char BR_OP = '{';
char BR_CL = '}';
char DQUOTE = '"';
char COLON = ':';
char SQ_OP = '[';
char SQ_CL = ']';
char COMMA = ',';
const char* LIST = "list";
const char* ID = "id";
const char* URL = "url";
const char* INFO = "info";
const char* DESC = "desc";
};
int main()
{
typedef std::string::iterator iterator_type;
typedef request_parser<iterator_type> requester_parser;
std::string str = "{\"list\":[\"data1\",\"data2\"],\"info\":{\"desc\":\"description\",\"id\":\"23\"},\"id\":\"1234\",\"url\":\"ok.com\"}";
Request rqst;
requester_parser parser;
using boost::spirit::ascii::space;
boost::spirit::qi::phrase_parse(str.begin(), str.end(), parser, space, rqst);
using std::cout;
using std::endl;
cout << rqst.id << endl;
cout << rqst.url << endl;
cout << rqst.list.size() << endl;
cout << rqst.info.id << endl;
cout << rqst.info.desc << endl;
}
Merci ! Emiliano