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;
}
Online Demo
(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.)