Как извлечь несколько структур из строки с помощью boost:: spirit
У меня есть несколько сложных структур, и я хочу извлечь их данные из текста с помощью boost:: spirit library (я выбрал эту библиотеку для повышения эффективности).
Но я задам свой вопрос более простым способом. Предположим, что у нас есть две структуры, подобные этим:struct person
{
std::string name;
uint8_t age;
};
И
struct fruit
{
std::string color;
std::double average_weight;
};
И наш текст, который включал эти данные, представлен ниже:
"... (Джейн, 23) (Дэвид, 19) (Мэри, 30) [Йелло, 100] [зеленый, 60,6] [красный, 30,5] "
Итак, проблема в том, что "извлечение этих данных в соответствующем формате"
Например путем вызова обработчика для каждой структуры или push_back их по вектору.
Любая помощь будет очень признательна!
Есть ли какой-нибудь пример кода об этом?!
1 ответ:
Вызов обработчиков для проанализированных структур.
P.S. Не все компиляторы могут построить такой код из-за лямбд в семантических действиях. (msvs не делают) в этом случае вы должны использовать что-то другое (phoenix::bind например)#include <string> #define BOOST_RESULT_OF_USE_DECLTYPE #include <boost/fusion/adapted.hpp> #include <boost/spirit/home/qi.hpp> namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace phoenix = boost::phoenix; namespace fusion = boost::fusion; struct person { std::string name; uint8_t age; }; BOOST_FUSION_ADAPT_STRUCT ( person, (std::string, name) (uint8_t, age) ); struct fruit { std::string color; double average_weight; }; BOOST_FUSION_ADAPT_STRUCT ( fruit, (std::string, color) (double, average_weight) ); template <typename _Iterator> struct parser : qi::grammar<_Iterator, void(), ascii::space_type> { parser() : parser::base_type(main) { main = *( _person[ ([](const person &person_) { // Add handler here }) ] | _fruit[ ([](const fruit &fruit_) { // Add handler here }) ] ); _person = qi::lit('(') >> *(qi::char_ - ',') >> ',' >> qi::ushort_ >> ')'; _fruit = qi::lit('[') >> *(qi::char_ - ',') >> ',' >> qi::double_ >> ']'; } qi::rule<_Iterator, void(), ascii::space_type> main; qi::rule<_Iterator, person(), ascii::space_type> _person; qi::rule<_Iterator, fruit(), ascii::space_type> _fruit; }; int main() { typedef std::string::const_iterator iterator; std::string input_ = "(jane, 23000) (david, 19) (mary, 30) [yello,100] [green, 60.6] [red, 30.5]"; iterator iterator_ = std::begin(input_); bool result_ = qi::phrase_parse(iterator_, iterator(std::end(input_)), parser<iterator>(), ascii::space) && iterator_ == std::end(input_); return 0; }
Хранить разбираемые структуры в векторе
typedef boost::variant < person, fruit > variant; template <typename _Iterator> struct parser : qi::grammar<_Iterator, std::vector < variant > (), ascii::space_type> { parser() : parser::base_type(main) { main = *(_person | _fruit); _person = qi::lit('(') >> *(qi::char_ - ',') >> ',' >> qi::ushort_ >> ')'; _fruit = qi::lit('[') >> *(qi::char_ - ',') >> ',' >> qi::double_ >> ']'; } qi::rule<_Iterator, std::vector < variant > (), ascii::space_type> main; qi::rule<_Iterator, person(), ascii::space_type> _person; qi::rule<_Iterator, fruit(), ascii::space_type> _fruit; };