如何将Boost.Spirit定制点与Nabialek结合使用?

时间:2019-05-14 03:44:58

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

首先,我正在使用MS Visual Studio 2017(v15.19.11),C ++ 14和Boost v1.65.1的默认C ++语言标准

我的输入文件格式如下:

IterName        SomeName
IterDesc        Some Description
COLUMNS fname.XCT               posn.detect.R           posn.source.z
        expt_KF000000.raw       0.0                     27.639320225002102
        expt_KF000180.raw       216.34457142857138      30.584848796430673
        expt_KF000360.raw       72.68914285714277       33.530377367859245

我正在尝试将其解析并加载到如下结构中:

struct Stax { std::string stage, axis; };
struct Configuration {
    std::map<std::string, std::string> filenames; // "expt_KF000000.raw": "XCT", "other_file.raw": "OCT"
    std::map<double, Stax> positions;  // 0.0: ["Detect", "R"], 27.639: ["Source", "Z"]
};
struct Iteration {
    std::string name;
    std::string descript;
    std::vector<Configuration> configs;
};

包含“ COLUMNS ”的行之后的每一行都应生成一个新的Configuration实例,并将其添加到Iteration.configs中。

如代码中的注释所暗示,某些列可能会丢失(在此示例中为“ fname.OCT ”)...但是列的顺序可能会有所不同(数量也会有所不同) ),因此我尝试使用本地规则状态来保存可变数量的解析器,每列对应一个解析器,如下所示:https://stackoverflow.com/a/31382602/1206102

Configuration.positions的元素由“ posn。”标题字符串后面的信息以及从单元格本身解析的所有内容组成。同样,Configuration.filenames的元素由标题中“ fname。”后面的任何内容以及单元格内容组成。因此,我必须以某种方式保存我从标头行中解析的信息,以便稍后在解析单元格时使用...因此我将其与单元格解析器一起存储在规则本地状态var中。

我已经尝试了各种方法,从规则局部变量到Phoenix封装的数据成员,从直接属性传播到融合适应的结构和“定制点”,甚至是attr_casttransform_attribute专业化...但尚未成功编译。我的尝试清单如下:

  1. https://wandbox.org/permlink/fU1WOazzxOVPbh9n
  2. https://wandbox.org/permlink/Itlq3HfydUByUSaH
  3. https://wandbox.org/permlink/96yDzVpCpI0K4ujs
  4. https://wandbox.org/permlink/u8iWv61jJSQv01bU

我的上一次尝试仍然会产生11个编译时错误,其中第一个错误('const_iterator': is not a member of 'Configuration'告诉我们:某事(Qi / Fusion / Phoenix)期望Configuration是可迭代的……可能因为填充它的解析类型是(元组的向量)。

这可能是我问题的症结所在:我正在尝试将已解析的可迭代对象填充到不可迭代*的复杂结构中:已解析向量中的某些元组将进入该结构的一个数据成员,而其他元组将进入将进入另一个数据成员。 (*我说不可迭代,是因为在Configuration上进行迭代是没有意义的,但是如果Qi / Fusion / Phoenix坚持我可以尝试适应。实际上,您会发现[注释]试图定义{ {1}的{1}}类型。)

如果可能的话,我想使用Boost.Spirit完成此操作...任何想法我做错了什么?

1 个答案:

答案 0 :(得分:1)

  1. &cell_stage的地址不为cell_stage,因为operator&已超载。使用boost/std::addressof获取地址。
  2. qi::rule<Iterator, Skipper, double()>*无法转换为qi::rule<Iterator, Skipper, boost::variant<std::string, double, bool>>*
  3. qi::eps[_offset = -1, px::ref(_ncols) = px::size(_tstore)]中,您只需在初始化时将-1分配给_offset,它就必须是px::ref(_offset) = -1
  4. qi::repeat(_ncols)不会重复_ncols次,而是重复_ncols在规则创建时包含的数字,该数字为零。
  5. qi::eps[_offset = ++_offset % _ncols]中,与之前的一样,您不会创建Phoenix lambda,而只会创建qi::eps[0]之类的东西。它必须是qi::eps[px::ref(_offset) = ++px::ref(_offset) % px::cref(_ncols)]
  6. 我没有挖掘qi::attr(_tstore[_offset]) >> *_pstore[_offset]应该做什么,但显然不是您的意思,可能是qi::lazy(px::cref(_tstore)[_offset]) >> qi::lazy(px::cref(_pstore)[_offset])

在这一点上,我不得不停下来问:您真的要使它正常工作吗?

请勿将Spirit用作Birmingham screwdriver。您不必被迫在单个Spirit解析器中完成所有操作。例如,您可以在一个普通的for循环中解析行,这将使编写和维护更加简单。