使用boost精神x3解析为具有布尔或枚举成员的结构

Exa*_*gon 2 c++ parsing boost-spirit c++14 boost-spirit-x3

如果我有一个结构:

struct person{
    bool is_male;
    std::string name;
    std::vector<std::string> friends;
}
Run Code Online (Sandbox Code Playgroud)

要么

enum class gender_t{male, female}
struct person{
        gender_t gender;
        std::string name;
        std::vector<std::string> friends;
}
Run Code Online (Sandbox Code Playgroud)

如何使用boost.spirit X3解析此结构?规则如何解析“ alice male bob”之类的字符串,解析器将返回一个名称为alice的对象,该对象是male,并且有一个朋友bob。如果这个人不是女性,那么如果性别只是露骨的话,会是什么样?

ild*_*arn 5

这正是Spirit的符号表的用途–确实,它是Spirit文档(Spirit.X3:罗马数字)中的主要教程之一。

首先,您需要适当地调整您的类型:

struct person {
    std::string name;
    gender_t gender;
    std::vector<std::string> friends;
};
BOOST_FUSION_ADAPT_STRUCT(person, name, gender, friends)
Run Code Online (Sandbox Code Playgroud)

Nb我已经更改了成员的顺序-因为我们想解析名称->性别->朋友,所以如果我们也以这种方式构造类型,这是最简单的。现在,解析:

person parse_person(std::string const& str) {
    namespace x3 = boost::spirit::x3;

    struct gender_table : x3::symbols<gender_t> {
        gender_table() {
            add ("male"   , gender_t::male)
                ("female" , gender_t::female);
        }
    } const gender;
    auto const word = x3::lexeme[+~x3::space];
    auto const parser
      =    word                                  // name
        >> (gender | x3::attr(gender_t::female)) // gender
        >> *word;                                // friends

    person ret{};
    x3::phrase_parse(str.cbegin(), str.cend(), parser, x3::space, ret);
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

Online Demo

(如果您不想更改数据成员的顺序以简化解析,那么是一种使所有这些都不受干扰的方法。)

  • 我认为`parser = word &gt;&gt;(genders | x3 :: attr(gender_t :: female))&gt;&gt; + word`也可以工作。 (3认同)