简体   繁体   English

如何使用boost :: spirit从字符串中提取多个结构

[英]How to extract multiple structures from a string with boost::spirit

I have some complicated structures and i want to extract their data from a text using boost::spirit library (I've selected this one for efficiency purpose). 我有一些复杂的结构,我想使用boost :: spirit库从文本中提取数据(出于效率考虑,我选择了这个库)。

but i will ask my question in simpler way. 但是我会以更简单的方式问我的问题。

assume, we have two structures like these: 假设,我们有两个这样的结构:

struct person 
{
   std::string name;
   uint8_t age; 
};

and

struct fruit
{
   std::string color;
   std::double average_weight;
};

and our text that included these data is presented below: 包含这些数据的文字如下所示:

"... (jane, 23) (david, 19) (mary, 30) [yello,100] [green, 60.6] [red, 30.5]" “ ...(jane,23)(david,19)(mary,30)[yello,100] [绿色,60.6] [红色,30.5]”

now, the problem is "extracting these data in suitable format" 现在的问题是“以适当的格式提取这些数据”

for example by call handler for each struct or push_back them on vector. 例如,通过针对每个结构的调用处理程序或将它们推入vector。

any help would be greatly appreciated! 任何帮助将不胜感激!

is there any code sample about that?! 是否有任何有关此的代码示例?

call handlers for parsed structures. 解析结构的调用处理程序。

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

PS Not all compiler can build that code because of lambdas in semantic actions. PS并非所有编译器都可以构建该代码,因为语义动作中存在lambda。 (msvs don't) In this case you have to use something else (phoenix::bind for example) (msvs不需要)在这种情况下,您必须使用其他内容(例如phoenix :: bind)

store parsed structures in a vector 将解析的结构存储在向量中

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM