如何将Boost.Spirit自定义点与Nabialek相结合?

How to combine Boost.Spirit customization points with Nabialek?

本文关键字:Nabialek 相结合 自定义 Boost Spirit      更新时间:2023-10-16

首先要做的是:我使用的是MS Visual Studio 2017(v15.19.11),C++14的默认C++语言标准,以及Boost v1.65.1

我有一个格式如下的输入文件:

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."后面的任何内容加上单元格内容组成。 所以我必须以某种方式保存我从标题行解析的信息,以便以后解析单元格时使用......所以我把它与单元格解析器一起存储在规则本地状态变量中。

我尝试了各种各样的东西,从规则局部到凤凰城包装的数据成员,从直接属性传播到融合适应的结构和"自定义点",甚至是attr_cast具有transform_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 坚持,我可以尝试适应。 实际上,您会看到一个[注释掉的]尝试为Configuration定义const_iterator类型。

如果可能的话,我想使用 Boost.Spirit 来完成这个......知道我做错了什么吗?

  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]中,与以前的一样,您不会创建凤凰 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用作伯明翰螺丝刀。你不会被迫在一个精神解析器中制作所有的东西。例如,您可以在通常的 for 循环中解析行,编写和维护起来会简单得多。