如何使用boost::xpressive在语义操作中使用结构填充向量

如何使用boost::xpressive在语义操作中使用结构填充向量,boost,boost-xpressive,Boost,Boost Xpressive,每次检测到匹配时,我都试图将数据结构插入到向量中,但编译都失败了。代码如下: #include <string> #include <boost/xpressive/xpressive.hpp> #include <boost/xpressive/regex_actions.hpp> using namespace boost::xpressive; struct Data { int integer; double real; s

每次检测到匹配时,我都试图将数据结构插入到向量中,但编译都失败了。代码如下:

#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>

using namespace boost::xpressive;

struct Data
{
    int integer;
    double real;
    std::string str;

    Data(const int _integer, const double _real, const std::string& _str) : integer(_integer), real(_real), str(_str) { }
};

int main()
{
    std::vector<Data> container;

    std::string input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";

    sregex parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
                    [::ref(container)->*push_back(Data(as<int>(s1), as<double>(s2), s3))];

    sregex_iterator cur(input.begin(), input.end(), parser);
    sregex_iterator end;

    for(; cur != end; ++cur)
        smatch const &what = *cur;

    return 0;
}
#包括
#包括
#包括
使用名称空间boost::xpressive;
结构数据
{
整数;
双实数;
std::字符串str;
数据(const int _integer,const double _real,const std::string&_str):integer(_integer),real(_real),str(_str){
};
int main()
{
载体容器;
std::string input=“Int:0-Real:18.8-Str:ABC-1005\nInt:0-Real:21.3-Str:BCD-1006\n”;
sregex解析器=((“Int:”>>(s1=|d)>>“-Real:”>>(s2=(repeat(|d)>>”.>>)>>“-Str:”>>(s3=+set[alnum |'-'))>\n)
[::ref(container)->*向后推(数据(as(s1)、as(s2)、s3));
sregex_迭代器cur(input.begin()、input.end()、解析器);
sregex_迭代器端;
对于(;cur!=end;++cur)
smatch const&what=*cur;
返回0;
}
它未能编译“push_back”语义操作,因为我在内部使用数据对象,而它不能懒洋洋地使用它(我想,我不是很确定)

拜托,有人能帮我吗

注意-我不幸地与MS VS 2010(不完全符合c++11)联系在一起,所以请不要使用可变模板和部署回解决方案。谢谢。

使用Xpressive 你应该让这个动作成为一个懒惰的演员。您的
数据
构造函数调用不可用

#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>

namespace bex = boost::xpressive;

struct Data {
    int integer;
    double real;
    std::string str;

    Data(int integer, double real, std::string str) : integer(integer), real(real), str(str) { }
};

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";

    using namespace bex;
    bex::sregex const parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
        [bex::ref(container)->*bex::push_back(bex::construct<Data>(as<int>(s1), as<double>(s2), s3))];

    bex::sregex_iterator cur(input.begin(), input.end(), parser), end;

    for (auto const& what : boost::make_iterator_range(cur, end)) {
        std::cout << what.str() << "\n";
    }

    for(auto& r : container) {
        std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
    }
}
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

#include <iostream>

int main() {
    std::vector<Data> container;
    using It = std::string::const_iterator;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    qi::rule<It, Data(), qi::blank_type> parser = qi::no_case[
            qi::lit("int") >> ':' >> qi::auto_ >> '-' 
            >> "real" >> ':' >> qi::auto_ >> '-' 
            >> "str" >> ':' >> +(qi::alnum|qi::char_('-')) >> +qi::eol
        ];

    It f = input.begin(), l = input.end();
    if (parse(f, l, qi::skip(qi::blank)[*parser], container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/struct.hpp>

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

namespace Parsers {
    using namespace boost::spirit::x3;

    static auto const data 
        = rule<struct Data_, ::Data> {} 
        = no_case[
            lit("int") >> ':' >> int_ >> '-' 
            >> "real" >> ':' >> double_ >> '-' 
            >> "str" >> ':' >> +(alnum|char_('-')) >> +eol
        ];

    static auto const datas = skip(blank)[*data];
}

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    auto f = input.begin(), l = input.end();
    if (parse(f, l, Parsers::datas, container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
使用酒精 我会用精神来做这个。Spirit具有直接解析底层数据类型的原语,因此不易出错,效率更高

灵气(V2) 使用Phoenix,情况非常相似:

#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>

namespace bex = boost::xpressive;

struct Data {
    int integer;
    double real;
    std::string str;

    Data(int integer, double real, std::string str) : integer(integer), real(real), str(str) { }
};

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";

    using namespace bex;
    bex::sregex const parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
        [bex::ref(container)->*bex::push_back(bex::construct<Data>(as<int>(s1), as<double>(s2), s3))];

    bex::sregex_iterator cur(input.begin(), input.end(), parser), end;

    for (auto const& what : boost::make_iterator_range(cur, end)) {
        std::cout << what.str() << "\n";
    }

    for(auto& r : container) {
        std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
    }
}
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

#include <iostream>

int main() {
    std::vector<Data> container;
    using It = std::string::const_iterator;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    qi::rule<It, Data(), qi::blank_type> parser = qi::no_case[
            qi::lit("int") >> ':' >> qi::auto_ >> '-' 
            >> "real" >> ':' >> qi::auto_ >> '-' 
            >> "str" >> ':' >> +(qi::alnum|qi::char_('-')) >> +qi::eol
        ];

    It f = input.begin(), l = input.end();
    if (parse(f, l, qi::skip(qi::blank)[*parser], container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/struct.hpp>

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

namespace Parsers {
    using namespace boost::spirit::x3;

    static auto const data 
        = rule<struct Data_, ::Data> {} 
        = no_case[
            lit("int") >> ':' >> int_ >> '-' 
            >> "real" >> ':' >> double_ >> '-' 
            >> "str" >> ':' >> +(alnum|char_('-')) >> +eol
        ];

    static auto const datas = skip(blank)[*data];
}

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    auto f = input.begin(), l = input.end();
    if (parse(f, l, Parsers::datas, container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
使用Fusion Adaption,它变得更有趣,也更简单:

#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>

namespace bex = boost::xpressive;

struct Data {
    int integer;
    double real;
    std::string str;

    Data(int integer, double real, std::string str) : integer(integer), real(real), str(str) { }
};

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";

    using namespace bex;
    bex::sregex const parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
        [bex::ref(container)->*bex::push_back(bex::construct<Data>(as<int>(s1), as<double>(s2), s3))];

    bex::sregex_iterator cur(input.begin(), input.end(), parser), end;

    for (auto const& what : boost::make_iterator_range(cur, end)) {
        std::cout << what.str() << "\n";
    }

    for(auto& r : container) {
        std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
    }
}
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

#include <iostream>

int main() {
    std::vector<Data> container;
    using It = std::string::const_iterator;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    qi::rule<It, Data(), qi::blank_type> parser = qi::no_case[
            qi::lit("int") >> ':' >> qi::auto_ >> '-' 
            >> "real" >> ':' >> qi::auto_ >> '-' 
            >> "str" >> ':' >> +(qi::alnum|qi::char_('-')) >> +qi::eol
        ];

    It f = input.begin(), l = input.end();
    if (parse(f, l, qi::skip(qi::blank)[*parser], container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/struct.hpp>

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

namespace Parsers {
    using namespace boost::spirit::x3;

    static auto const data 
        = rule<struct Data_, ::Data> {} 
        = no_case[
            lit("int") >> ':' >> int_ >> '-' 
            >> "real" >> ':' >> double_ >> '-' 
            >> "str" >> ':' >> +(alnum|char_('-')) >> +eol
        ];

    static auto const datas = skip(blank)[*data];
}

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    auto f = input.begin(), l = input.end();
    if (parse(f, l, Parsers::datas, container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
现在想象一下:

  • 您希望匹配不区分大小写的关键字
  • 你想让空白变得无关紧要
  • 您希望接受空行,但不接受中间的随机数据
在Xpressive中,您将如何做到这一点?下面是你如何用勇气做到这一点。请注意附加约束如何基本上不改变语法。与基于正则表达式的解析器相比

#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>

namespace bex = boost::xpressive;

struct Data {
    int integer;
    double real;
    std::string str;

    Data(int integer, double real, std::string str) : integer(integer), real(real), str(str) { }
};

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";

    using namespace bex;
    bex::sregex const parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
        [bex::ref(container)->*bex::push_back(bex::construct<Data>(as<int>(s1), as<double>(s2), s3))];

    bex::sregex_iterator cur(input.begin(), input.end(), parser), end;

    for (auto const& what : boost::make_iterator_range(cur, end)) {
        std::cout << what.str() << "\n";
    }

    for(auto& r : container) {
        std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
    }
}
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

#include <iostream>

int main() {
    std::vector<Data> container;
    using It = std::string::const_iterator;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    qi::rule<It, Data(), qi::blank_type> parser = qi::no_case[
            qi::lit("int") >> ':' >> qi::auto_ >> '-' 
            >> "real" >> ':' >> qi::auto_ >> '-' 
            >> "str" >> ':' >> +(qi::alnum|qi::char_('-')) >> +qi::eol
        ];

    It f = input.begin(), l = input.end();
    if (parse(f, l, qi::skip(qi::blank)[*parser], container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/struct.hpp>

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

namespace Parsers {
    using namespace boost::spirit::x3;

    static auto const data 
        = rule<struct Data_, ::Data> {} 
        = no_case[
            lit("int") >> ':' >> int_ >> '-' 
            >> "real" >> ':' >> double_ >> '-' 
            >> "str" >> ':' >> +(alnum|char_('-')) >> +eol
        ];

    static auto const datas = skip(blank)[*data];
}

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    auto f = input.begin(), l = input.end();
    if (parse(f, l, Parsers::datas, container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
进一步思考:你会怎么做

  • 解析科学符号?负数
  • 正确解析十进制数(假设您真的在解析财务金额,您可能不希望使用不精确的浮点表示)
烈酒X3 如果您可以使用c++14,那么Spirit X3会比Spirit Qi或Xpressive方法更高效,编译速度也会更快

#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>

namespace bex = boost::xpressive;

struct Data {
    int integer;
    double real;
    std::string str;

    Data(int integer, double real, std::string str) : integer(integer), real(real), str(str) { }
};

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";

    using namespace bex;
    bex::sregex const parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
        [bex::ref(container)->*bex::push_back(bex::construct<Data>(as<int>(s1), as<double>(s2), s3))];

    bex::sregex_iterator cur(input.begin(), input.end(), parser), end;

    for (auto const& what : boost::make_iterator_range(cur, end)) {
        std::cout << what.str() << "\n";
    }

    for(auto& r : container) {
        std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
    }
}
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

#include <iostream>

int main() {
    std::vector<Data> container;
    using It = std::string::const_iterator;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    qi::rule<It, Data(), qi::blank_type> parser = qi::no_case[
            qi::lit("int") >> ':' >> qi::auto_ >> '-' 
            >> "real" >> ':' >> qi::auto_ >> '-' 
            >> "str" >> ':' >> +(qi::alnum|qi::char_('-')) >> +qi::eol
        ];

    It f = input.begin(), l = input.end();
    if (parse(f, l, qi::skip(qi::blank)[*parser], container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/struct.hpp>

struct Data {
    int integer;
    double real;
    std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

namespace Parsers {
    using namespace boost::spirit::x3;

    static auto const data 
        = rule<struct Data_, ::Data> {} 
        = no_case[
            lit("int") >> ':' >> int_ >> '-' 
            >> "real" >> ':' >> double_ >> '-' 
            >> "str" >> ':' >> +(alnum|char_('-')) >> +eol
        ];

    static auto const datas = skip(blank)[*data];
}

#include <iostream>

int main() {
    std::vector<Data> container;

    std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

    auto f = input.begin(), l = input.end();
    if (parse(f, l, Parsers::datas, container)) {
        std::cout << "Parsed:\n";
        for(auto& r : container) {
            std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
        }
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}

我刚刚注意到你关于VS2010中c++11支持有限的评论。下面是最后一个Qi示例的完整C++03版本:非常感谢。令人敬畏的澄清和额外的信息。顺便说一句,我曾经使用boost::spirit,但由于它的分步学习曲线和缓慢的编译时间,我放弃了。也许我应该考虑在这个问题上再次使用它。我不知道Xpression的编译时间要低得多,尤其是在附加语义acion时