c++ - 如何使用 boost::spirit 将文本解析为结构?

标签 c++ parsing boost boost-spirit boost-spirit-qi

我在学习boost::spirit ,我正在尝试读取一些文本并将其解析为一个结构。

例如,"2: 4.6"被解析为 int 2和双4.6在我的 TestStruct下面:

#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;

struct TestStruct {
  int myint;
  double mydouble;
  TestStruct() {}
  TestStruct(std::pair<int,double> p) : myint(p.first), mydouble(p.second) {}
};

template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> {
  MyGrammar() : MyGrammar::base_type(mystruct) {
    mystruct0 = qi::int_ >> ":" >> qi::double_;
    mystruct = mystruct0;
  }
  qi::rule<Iterator, std::pair<int,double>(), Skipper> mystruct0;
  qi::rule<Iterator, TestStruct(), Skipper> mystruct;
};

int main() {
  typedef boost::spirit::istream_iterator It;
  std::cin.unsetf(std::ios::skipws);
  It it(std::cin), end; // input example: "2: 3.4"                                                                              

  MyGrammar<It, qi::space_type> gr;
  TestStruct ts;
  if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end)
    std::cout << ts.myint << ", " << ts.mydouble << std::endl;
  return 0;
}

它工作得很好,但我想知道如何简化这段代码?

例如,我想去掉 mystruct0语法规则,仅用于标记类型 std::pair<int,double> ,然后用于自动构造 TestStruct来自 mystruct 的对象规则。

我还希望能够摆脱 TestStruct来自 std::pair 的构造函数,如果可能的话。

那么,下面的代码能以某种方式被编译吗?那将是一个更好的解决方案:

struct TestStruct {
  int myint;
  double mydouble;
  TestStruct() {}
  TestStruct(int i, double d) : myint(i), mydouble(d) {}
};

template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> {
  MyGrammar() : MyGrammar::base_type(mystruct) {
    mystruct = qi::int_ >> ":" >> qi::double_;
  }
  qi::rule<Iterator, TestStruct(), Skipper> mystruct;
};

int main() {
  typedef boost::spirit::istream_iterator It;
  std::cin.unsetf(std::ios::skipws);
  It it(std::cin), end; // input example: "2: 3.4"                                                                              

  MyGrammar<It, qi::space_type> gr;
  TestStruct ts;
  if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end)
    std::cout << ts.myint << ", " << ts.mydouble << std::endl;
  return 0;
}

不幸的是,编译器说:

boost_1_49_0/include/boost/spirit/home/qi/detail/assign_to.hpp:123: 
error: no matching function for call to ‘TestStruct::TestStruct(const int&)’

最佳答案

为了能够将值“按顺序”解析为结构,您需要将其转换为 fusion 元组,如here所述.

在您的情况下,这意味着您需要

  1. 包含必要的标题

    #include <boost/fusion/adapted/struct/adapt_struct.hpp>
    
  2. 使用 fusion-adapt 结构宏。最好将它放在 TestStruct 声明之后:

    BOOST_FUSION_ADAPT_STRUCT(
            TestStruct,
            (int,myint)
            (double,mydouble)
         )
    

通过这两项更改,您的简化版本可以编译并产生所需的结果。不确定现在是否真的更简单了——但如果您打算向结构中添加更多成员,这是一个很好的起点,因为它可能有助于简化 future 的事情。

我看不到您可以做出任何其他重大更改来简化程序。

关于c++ - 如何使用 boost::spirit 将文本解析为结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10457605/

相关文章:

c++ - vs2010 上的 Boost Process 错误

c++ - 如何将 boost 库添加到 Visual Studio Linux 项目中?

c++ - 如何解析来自 EDID 的数字数据

c++ - 访问 stringstream 对象的关联字符串

c++ - 为什么 std::bitset 的位顺序相反?

c++ - C4838 警告与 const char* 数组的数组初始化

Java SimpleDatetime 解析

parsing - 将 yaml 字段动态解析为 Go 中的一组有限结构之一

时间:2019-03-17 标签:c++boosticlcontainersinsharedmemory

c++ - 抽象派生类