(question lifted from Spirit-general mailing list)
Hello,
I'm working in a parser with spirit qi. The grammar is working good, but I have some problems to populate my struct instance with Semantic Actions.
With the direct struct attributes, like "Request.id" and "Request.url", the code is working. But I don't know how to populate the attributes inside the nested struct "Info", neither how to push values in "Request.list".
Here is my code (The string to parse could have the values in any order):
#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;
}
Thanks! Emiliano