如何以增强的精神将弦分析为元素的矢量

How to parse a string into vector of tuples with boost spirit?

本文关键字:元素 增强的      更新时间:2023-10-16
#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而不是解析,则不会编译。我的错误是什么,我如何实现预期的结果?

修复规则定义以正确定义属性签名为 tpl()而不是 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 Skipper问题(
  • 将船长的选择隐藏在语法中
  • 添加调试支持
  • 简化调试输出
  • 错误检查(也考虑语法/解析表达式中的>> 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 failedn";
        }
        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: ';'

从呼叫到解析中省略了boost::spirit::qi::space,您没有作为Semperator的空间。

您也可以删除lexeme[]指令,因为您没有跳过。

phrase_parse要求该规则具有兼容的Skipper,您没有