Exagon Exagon - 1 year ago 58
C++ Question

parsing a single value into an ast node with a container

My problem is the following. I have an ast node which is defined as like the following:

struct foo_node{
std::vector<std::string> value;

and I have a parser like this for parsing into the struct, which works fine:

typedef x3::rule<struct foo_node_class, foo_node> foo_node_type;
const foo_node_type foo_node = "foo_node";
auto const foo_node_def = "(" >> +x3::string("bar") >> ")";

Now I want to achieve that the parser also parses
, without brackets, but only if its a single bar. I tried to do it like this:

auto const foo_node_def = x3::string("bar")
| "(" > +x3::string("bar") > ")";

but this gives me a compile time error, since
returns a string and not a
My question is, how can I achieve, that the
parser (and every other parser which returns a string) parses into a vector?

Answer Source

The way to parse a single element and expose it as a single-element container attribute is x3::repeat(1) [ p ]:

Live On Coliru

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>

namespace x3 = boost::spirit::x3;

struct foo_node {
    std::vector<std::string> value;


namespace rules {
    auto const bar 
        = x3::string("bar");

    auto const foo_node
        = '(' >> +bar >> ')'
        | x3::repeat(1) [ +bar ]

int main() {
    for (std::string const input : {
        auto f = input.begin(), l = input.end();

        foo_node data;
        bool ok = x3::parse(f, l, rules::foo_node, data);

        if (ok) {
            std::cout << "Parse success: " << data.value.size() << " elements\n";
        } else {
            std::cout << "Parse failed\n";

        if (f != l)
            std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";


Parse success: 1 elements
Parse success: 1 elements
Parse success: 2 elements
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download