2

If the inherited attributes are used in semantic actions, we can use x3::with directive.

What if we want to use the attributes as part of the parser? For example a simple parser matches 1 or more alphabet characters except the character is from a parameter char set.

qi::rule<std::string::const_iterator, qi::unused_type(char const*)> rule =
    +(qi::alpha - qi::char_(qi::_r1));

Or the parameter char set could be used as a lazy parser.

qi::rule<std::string::const_iterator, qi::unused_type(char const*)> rule =
    +(qi::alpha - qi::lazy(qi::_r1));

x3::with directive put this local value in the context. I'm not sure if we could use this context outside a semantic action and eventually generate a parser.

wanghan02
  • 1,227
  • 7
  • 14

1 Answers1

4

Simply let go of the old habit of rule-ifying everything.

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

namespace x3 = boost::spirit::x3;

template <typename... Args>
auto negate(Args&&... p) {
    return +(x3::char_ - x3::char_(std::forward<Args>(p)...));
};

int main() {
    std::string input("all the king's men and all the king's horses"), parsed;
    if (parse(input.begin(), input.end(), negate("horse"), parsed))
        std::cout << "'" << input << "' -> '" << parsed << "'\n";
}

Live On Coliru, prints:

'all the king's men and all the king's horses' -> 'all t'

Second flavour:

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

namespace x3 = boost::spirit::x3;

template <typename Sub>
auto negate(Sub p) {
    return +(x3::char_ - x3::as_parser(p));
};

int main() {
    std::string input("all the king's men and all the king's horses"), parsed;
    if (parse(input.begin(), input.end(), negate("horse"), parsed))
        std::cout << "'" << input << "' -> '" << parsed << "'\n";
}

Live On Coliru, prints:

'all the king's men and all the king's horses' -> 'all the king's men and all the king's '

More complicated stuff

You can also aggregate sub parsers in a custom parser:

If you need resursive rules with passing around, I'd suggest x3::with<> (although I'm not sure the contexts build re-entrant state for the with<>, you need to test the precise semantics unless you can find documentation for it)

sehe
  • 374,641
  • 47
  • 450
  • 633