如何将字符串解析为具有增强精神的元组向量? [英] How to parse a string into vector of tuples with boost spirit?

查看:67
本文介绍了如何将字符串解析为具有增强精神的元组向量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>

#include <string>
#include <iostream>
#include <tuple>
#include <vector>

using tpl = std::tuple<int, double, std::string>;

boost::spirit::qi::rule<std::string::iterator, tpl> parse_into_tuple = 
    boost::spirit::qi::int_ >> ',' >> 
    boost::spirit::qi::double_ >> ',' >>
    boost::spirit::lexeme[+boost::spirit::qi::char_ - ';'];

boost::spirit::qi::rule<std::string::iterator, std::vector<tpl>> 
    parse_into_vec = parse_into_tuple % ';';


int main()
{
    std::string s = "1,5.4,abc xyz;2,91.05,qwe jkl";    
    std::vector<tpl> v;
    bool b = boost::spirit::qi::parse(
    s.begin(), s.end(), parse_into_vec, v, boost::spirit::qi::space);
    std::cout << std::boolalpha << b << '\n';
    std::cout << v.size() << '\n';
    for(const auto& t: v)
    {
        std::cout << std::get<0>(t) << ", " << std::get<1>(t) << ", " << std::get<2>(t) << '\n';
    }
}

现在输出为"true"和0(向量的大小).我的预期输出是大小2.此外,如果我使用phrase_parse而不是parse,它将无法编译.我的错误是什么?如何达到预期的效果?

The output now is "true" and 0 (size of the vector). My expected output is size 2. Furthemore, if I use phrase_parse instead of parse, it doesn't compile. What is my mistake and how do I achieve the expected result?

推荐答案

修复规则定义,以将属性签名正确定义为 tpl()而不是 tpl :

Fix the rule definition to correctly define the attribute signature as tpl() instead of tpl:

在Coliru上直播

#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>

#include <iostream>
#include <string>
#include <tuple>
#include <vector>

using tpl = std::tuple<int, double, std::string>;

boost::spirit::qi::rule<std::string::iterator, tpl()> parse_into_tuple =
    boost::spirit::qi::int_ >> ',' >> boost::spirit::qi::double_ >> ',' >>
    boost::spirit::lexeme[+boost::spirit::qi::char_ - ';'];

boost::spirit::qi::rule<std::string::iterator, std::vector<tpl>() > parse_into_vec = parse_into_tuple % ';';

int main() {
    std::string s = "1,5.4,abc xyz;2,91.05,qwe jkl";
    std::vector<tpl> v;
    bool b = boost::spirit::qi::parse(s.begin(), s.end(), parse_into_vec, v);
    std::cout << std::boolalpha << b << '\n';
    std::cout << v.size() << '\n';
    for (const auto &t : v) {
        std::cout << std::get<0>(t) << ", " << std::get<1>(t) << ", " << std::get<2>(t) << '\n';
    }
}

打印

true
1
1, 5.4, abc xyz;2,91.05,qwe jkl

奖金

  • 解决了以您可能期望的方式跳过空格的问题(请参阅 Boost spirit队长问题)
  • 隐藏语法中的船长选择
  • 添加调试支持
  • 简化调试输出
  • 错误检查(在语法/解析表达式中还要考虑>> qi :: eoi )
  • 在Coliru上直播

    //#define BOOST_SPIRIT_DEBUG
    #include <boost/fusion/adapted/std_tuple.hpp>
    #include <boost/spirit/include/qi.hpp>
    namespace qi = boost::spirit::qi;
    
    using tpl = std::tuple<int, double, std::string>;
    using tpls = std::vector<tpl>;
    
    template <typename It = std::string::const_iterator>
    struct grammar : qi::grammar<It, tpls()> {
        grammar() : grammar::base_type(start) {
            using namespace qi;
    
            tuple_ = int_ >> ',' >> double_ >> ',' >> lexeme[+~char_(';')];
            vec_   = tuple_ % ';';
    
            start  = skip(space) [ vec_ ];
    
            BOOST_SPIRIT_DEBUG_NODES((start)(vec_)(tuple_))
        }
      private:
        qi::rule<It, tpls()> start;
    
        using Skipper = qi::space_type;
        qi::rule<It, tpls(), Skipper> vec_;
        qi::rule<It, tpl(), Skipper> tuple_;
    };
    
    int main() {
        grammar<> const g;
        for(std::string const s : {
                "1,5.4,abc xyz;2,91.05,qwe jkl",
                "1,5.4,abc xyz;2,91.05,qwe jkl; trailing garbage",
                "1,    \n5.4, abc xyz;",
                })
        {
            auto f = s.begin(), l = s.end();
    
            std::vector<tpl> v;
            if (parse(f, l, g, v))
            {
                std::cout << v.size() << '\n';
                for (const auto &t : v) {
                    std::cout << boost::fusion::as_vector(t) << "\n";
                }
            } else {
                std::cout << "Parse failed\n";
            }
    
            if (f!=l) {
                std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
            }
        }
    }
    

    打印

    2
    (1 5.4 abc xyz)
    (2 91.05 qwe jkl)
    2
    (1 5.4 abc xyz)
    (2 91.05 qwe jkl)
    Remaining unparsed: '; trailing garbage'
    1
    (1 5.4 abc xyz)
    Remaining unparsed: ';'
    

    这篇关于如何将字符串解析为具有增强精神的元组向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆