To parse expressions like follow:
"asd {img} {ref I}sdkflsdlk {img} wmrwerml"
I have code like this:
struct CMyTag
{
std::string tagName;
std::string tagData;
};
BOOST_FUSION_ADAPT_STRUCT(::CMyTag, (std::string, tagName) (std::string, tagData));
struct fillMyTag
{
template <typename A, typename B = boost::spirit::unused_type, typename C = boost::spirit::unused_type, typename D = boost::spirit::unused_type>
struct result { typedef void type; };
void operator()(::CMyTag& _tag, const std::string& _name, const std::string& _type) const
{
_tag.tagName = _name;
_tag.tagData = _type;
}
};
template <typename Iterator>
struct testTag_grammar : qi::grammar<Iterator, std::vector<CMyTag>()>
{
testTag_grammar() :
testTag_grammar::base_type(data)
{
data = (text | imgtag | vartag | inctag | blktag | reftag) >> *data;
imgtagraw %= '{' >> qi::lit("img") >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
imgtag = imgtagraw[op(qi::labels::_val, "img", boost::spirit::_1)];
vartagraw %= '{' >> qi::lit("var") >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
vartag = vartagraw[op(qi::labels::_val, "var", boost::spirit::_1)];
inctagraw %= '{' >> qi::lit("inc") >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
inctag = inctagraw[op(qi::labels::_val, "inc", boost::spirit::_1)];
blktagraw %= '{' >> qi::lit("blank") >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
blktag = blktagraw[op(qi::labels::_val, "blk", boost::spirit::_1)];
reftagraw %= '{' >> lexeme[("ref")] >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
reftag = reftagraw[op(qi::labels::_val, "ref", boost::spirit::_1)];
textraw %= lexeme[+(char_ - '{' - '}')];
text = textraw[op(qi::labels::_val, "text", boost::spirit::_1)];
}
qi::rule<Iterator, std::string()> imgtagraw, vartagraw, inctagraw, blktagraw, reftagraw, textraw;
qi::rule<Iterator, CMyTag()> imgtag, vartag, inctag, blktag, reftag, text;
qi::rule<Iterator, std::vector<CMyTag>()> data;
boost::phoenix::function<fillMyTag> op;
};
Usage of parser:
testTag_grammar<std::string::iterator> l_gramar;
std::string l_test = "asd {img} {ref I}sdkflsdlk {img} wmrwerml";
std::vector<CMyTag> l_result;
bool result = qi::parse(l_test.begin(), l_test.end(), l_gramar, l_result);
As a result I expect to get a list of CmyTag structs, but compilation of code failed:
Error 1 error C2440: 'static_cast' : cannot convert from 'const std::vector<CMyTag,std::allocator<_Ty>>' to 'CMyTag' d:\lib\boost\include\boost-1_57\boost\spirit\home\qi\detail\assign_to.hpp 152 1 TestSpiritParser
When I change data rule to follow:
data = ((text | imgtag | vartag | inctag | blktag | reftag)[opvec(qi::labels::_val, boost::spirit::_1)]) >> *data;
with definition of opvec:
struct fillMyVec
{
template <typename A, typename B = boost::spirit::unused_type, typename C = boost::spirit::unused_type, typename D = boost::spirit::unused_type>
struct result { typedef void type; };
void operator()(std::vector<CMyTag>& _tagvec, const CMyTag& _name) const
{
_tagvec.push_back(_name);
}
void operator()(std::vector<CMyTag>& _tagvec, std::vector<CMyTag>& _name) const
{
_tagvec.insert(_tagvec.end(), _name.begin(), _name.end());
}
};
boost::phoenix::function<fillMyVec> opvec;
Code begin compile success, but as result of run I got list with only one item in it. Also before modification, when CMytag type was only std::string, I got a std::string list with correct numbers of items in it,
Now I have no idea what wrong, and what to do for fix issue