Search code examples
c++parsingc++14boost-spiritboost-spirit-x3

parsing into structs with boolean or enum members with boost spirit x3


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?


Solution

  • 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.)