2

I am interested in if there is a way to parse into a set using boost spirit x3. the background is I have a string of tokens, each token represents a enum value, now i want to create a parser which parses if every every token is at most once in the string, it would be a charm if I could get all the parsed tokens into a std::set while parsing. To get the enums back from the parsed string I am using a symbol_table:

enum class foo{bar, baz, bla, huh};

    struct enum_table : x3::symbols<foo> {
        enum_table() {
            add("bar", foo::bar)
                    ("baz", foo::baz)
                    ("huh", foo::huh);
        }
    } const enum_parser;
ildjarn
  • 62,044
  • 9
  • 127
  • 211
Exagon
  • 4,798
  • 6
  • 25
  • 53

1 Answers1

4

I am interested in if there is a way to parse into a set using boost spirit x3.

Spirit can parse into std::set<> out of the box (at least as of Boost 1.61.0), so the following already works with the types you've shown:

std::set<foo> foos;
x3::phrase_parse(
    input.begin(), input.end(),
    +enum_parser,
    x3::space,
    foos
);

Online Demo

To get your parser to fail upon encountering duplicates, this is most easily accomplished with semantic actions:

std::set<foo> foos;
auto insert_foo_or_fail = [&foos](auto& ctx) {
    _pass(ctx) = foos.insert(_attr(ctx)).second;
};
x3::phrase_parse(
    input.begin(), input.end(),
    +x3::omit[enum_parser[insert_foo_or_fail]],
    x3::space
);

Online Demo

ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • oh wow didnt knew it can parse into a set out of the box. thanks for the trick with the semantic action – Exagon Jun 22 '16 at 09:06
  • 1
    this doesnt work with boost version 1.60.0 I am getting an error: `»class std::set« has no member named »push_back«` so this realy works since with boost version 1.61.0 – Exagon Jun 22 '16 at 13:00