2

A simple parser as on Coliru. The parser -(+x3::alpha) should be able to propagate an attribute of type boost::optional<std::string> as Qi does. But it does not compile.

std::string const input = "abc";
boost::optional<std::string> attr;
if(x3::parse(boost::begin(input),boost::end(input),
    -(+x3::alpha),
    attr)) {
    std::cout<<"match!"<<std::endl;
}
else {
    std::cout<<"NOT match!"<<std::endl;
}
wanghan02
  • 1,227
  • 7
  • 14

1 Answers1

3

I don't think the normative claim "should be able [...] as Qi does" cuts wood. X3 is not an evolution of Qi, for very good reasons (such as this).

An oft recurring pattern is that type hints are required in more complicated propagation scenarios. The ugly verbose way could be like this:

    -(x3::rule<struct _, std::string> {} = +x3::alpha),

Live On Coliru

Or you can use the hack I described previously:

namespace {
    template <typename T>
    struct as_type {
        template <typename Expr>
            auto operator[](Expr&& expr) const {
                return x3::rule<struct _, T>{"as"} = x3::as_parser(std::forward<Expr>(expr));
            }
    };

    template <typename T> static const as_type<T> as = {};
}

Live On Coliru

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    Great solution! But I'm still wondering what is the reason why x3 does not support such an obvious compound attribute propagation? – wanghan02 Mar 29 '17 at 15:41
  • 2
    It's not obvious. It involves two nontrivial conversions. Container types have always been tricky (`-(a%b)` makes a lot of sense for just `vector ` and `-(a*)` is naturally equivalent to just `a*`. – sehe Mar 29 '17 at 16:36
  • 2
    What made it 'obvious enough' in Qi might be that the sub parsers internally prematurely held their attributes in the explicit synthesised type, leading to a lot of ineffeciency in copying attributes – sehe Mar 29 '17 at 16:39