0

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 "bar", 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 x3::string("bar") returns a string and not a std::vector<std::string>. My question is, how can I achieve, that the x3::string("bar") parser (and every other parser which returns a string) parses into a vector?

Exagon
  • 4,798
  • 6
  • 25
  • 53
  • 1
    please always post a [mcve] – m.s. Aug 21 '16 at 13:31
  • I completely concur with the requirement of a MCVE/SSCCE. In your case you had impossible naming conflicts and missing essential things (`SPIRIT_DEFINE`) that only the experts would know how to "guess" – sehe Aug 21 '16 at 19:03
  • I am realy sorry i wasnt online until now – Exagon Aug 21 '16 at 19:07

1 Answers1

2

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;
};

BOOST_FUSION_ADAPT_STRUCT(foo_node, 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 : {
            "bar",
            "(bar)",
            "(barbar)",
            })
    {
        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";
    }
}

Prints

Parse success: 1 elements
Parse success: 1 elements
Parse success: 2 elements
sehe
  • 374,641
  • 47
  • 450
  • 633