gpt4 book ai didi

c++ - Boost.Spirit.x3 避免将相同类型的两个连续属性 fold 成一个 vector

转载 作者:可可西里 更新时间:2023-11-01 16:39:19 26 4
gpt4 key购买 nike

我正在尝试学习 Boost.Spirit,但我发现了一个困难。

我正在尝试将字符串解析为以下结构:

struct employee {
std::string name;
std::string location;
};

并且似乎当两个具有相同类型的属性背靠背时,它们(逻辑上) fold 成一个std::vector。那种类型的。由于该规则,以下解析器

+x3::ascii::alnum >>
+x3::space >>
+x3::ascii::alnum

将具有 std::vector<std::string> 的属性.

但我正在尝试将其解析为struct ,这意味着对我来说理想的属性是 boost::fusion::tuple<std::string, std::string> ,所以我可以调整我的结构。

无效代码的完整版本(上面引用):

// Example program
#include <iostream>
#include <string>

#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>


struct employee {
std::string name;
std::string location;
};

BOOST_FUSION_ADAPT_STRUCT(employee,
(std::string, name),
(std::string, location)
)

namespace x3 = boost::spirit::x3;

x3::rule<struct parse_emp_id, employee> const parse_emp = "Employee Parser";
auto parse_emp_def =
+x3::ascii::alnum >>
+x3::space >>
+x3::ascii::alnum
;
BOOST_SPIRIT_DEFINE(parse_emp);

int main()
{
std::string input = "Joe Fairbanks";

employee ret;

x3::parse(input.begin(), input.end(), parse_emp, ret);

std::cout << "Name: " << ret.name << "\tLocation: " << ret.location << std::endl;
}

See it live

此代码会触发 static_assert告诉我我的属性不正确:

error: static_assert failed "Attribute does not have the expected size."

随着命令

clang++ -std=c++14 test.cpp

(它在 GCC 下也失败)。

我尝试过的

我找到了解决这个问题的方法,但它很乱,我不敢相信这是最干净的方法:

// Example program
#include <iostream>
#include <string>

#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>


struct employee {
std::string name;
std::string location;
};

namespace x3 = boost::spirit::x3;

x3::rule<struct parse_emp_id, employee> const parse_emp = "Employee Parser";
auto parse_emp_def =
x3::eps [
([](auto& ctx) {
x3::_val(ctx) = employee{};
})
]>>
(+x3::ascii::alnum)[
([](auto& ctx) {
x3::_val(ctx).name = x3::_attr(ctx);
})
]>>
+x3::space >>
(+x3::ascii::alnum)[
([](auto& ctx) {
x3::_val(ctx).location = x3::_attr(ctx);
})
]
;
BOOST_SPIRIT_DEFINE(parse_emp);

int main()
{
std::string input = "Joe Fairbanks";

employee ret;

x3::parse(input.begin(), input.end(), parse_emp, ret);

std::cout << "Name: " << ret.name << "\tLocation: " << ret.location << std::endl;
}

See it live

我真的不喜欢这个解决方案:它有点破坏 spirit 的惊人表现力并使其变得非常丑陋,如果我想在 employee 中添加新字段也是如此。结构,那么我必须添加一个额外的 lambda,而不是仅仅更新我的 BOOST_FUSION_ADAPT_STRUCT ,这就容易多了。

所以问题是:有没有办法(希望)从 std::vector 中干净地拆分两个相同类型的连续属性?并进入 boost::fusion::vector

预先感谢您走到这一步 ;)。

最佳答案

问题在于,与字 rune 字不同,x3::space 有一个属性。因此,您没有由空格分隔的两个单独字符序列的属性,而是包含空格的一个大字符序列的属性。

The omit directive就是您所追求的,并且通过一次添加,您的“无效代码”就可以工作。 :-]

// Example program
#include <string>
#include <iostream>

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/home/x3.hpp>

namespace x3 = boost::spirit::x3;

struct employee {
std::string name;
std::string location;
};
BOOST_FUSION_ADAPT_STRUCT(employee, name, location)

x3::rule<struct parse_emp_id, employee> const parse_emp = "Employee Parser";
auto parse_emp_def
= +x3::ascii::alnum
>> x3::omit[+x3::space]
>> +x3::ascii::alnum
;
BOOST_SPIRIT_DEFINE(parse_emp)

int main()
{
std::string const input = "Joe Fairbanks";

employee ret;
x3::parse(input.begin(), input.end(), parse_emp, ret);

std::cout << "Name: " << ret.name << "\tLocation: " << ret.location << '\n';
}

Online Demo

关于c++ - Boost.Spirit.x3 避免将相同类型的两个连续属性 fold 成一个 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37128649/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com