If I have a struct:
struct person{
bool is_male;
std::string name;
std::vector<std::string> friends;
}
or
enum class gender_t{male, female}
struct person{
gender_t gender;
std::string name;
std::vector<std::string> friends;
}
how can I parse into this struct using boost.spirit X3? how would a rule look like to parse a string like "alice male bob" and the parser returning a object with name alice, which is male and has one friend bob. How would it look like if the gender is only explicit said if the person isnt female?
This is exactly what Spirit's symbol table is for – indeed, it is one of the primary tutorials in the Spirit documentation (Spirit.X3: Roman Numerals).
First you need to adapt your type appropriately:
struct person {
std::string name;
gender_t gender;
std::vector<std::string> friends;
};
BOOST_FUSION_ADAPT_STRUCT(person, name, gender, friends)
N.b. I've changed the order of the members – since we want to parse name -> gender -> friends, it's easiest if we structure our type that way as well. Now, the parsing:
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;
}
(If you don't want to change the order of your data members to accommodate ease of parsing, then here is one approach to make all of this non-intrusive.)