In addition to the "manual" approach suggested by Mike you can
- use a convenience wrapper rule
- use the
distinct
parser direetive from the Spirit Repository
1. Use a convenience wrapper
I just remembered, I once came up with this quick and dirty helper:
static const qi::rule<It, qi::unused_type(const char*)> kw
= qi::lit(qi::_r1) >> !qi::alnum;
Which you could use like (using +"lit"
to decay the array-ref into const char*
):
stmt =
kw(+"if") >> '(' >> expr >> ')' >> block
>> -(kw(+"else") >> block)
;
You can make it considerably more convenient
template <std::size_t N>
static auto kw(char const (&keyword)[N]) -> qi::rule<Iterator> {
// qi::lit has problems with char arrays, use pointer instead.
return qi::lit(+keyword) >> !qi::alnum;
}
So you can
kw_if = kw("if");
kw_then = kw("then");
kw_else = kw("else");
kw_and = kw("and");
kw_or = kw("or");
kw_not = kw("not");
2. Use the distinct
directive from the Spirit Repository
In addition to the "manual" approach suggested by Mike you can use the distinct
parser directive from the Spirit Repository:
int main()
{
using namespace spirit_test;
using namespace boost::spirit;
{
using namespace boost::spirit::ascii;
qi::rule<char const*, space_type> r;
r = distinct::keyword["description"] >> -lit(':') >> distinct::keyword["ident"];
BOOST_TEST(test("description ident", r, space));
BOOST_TEST(test("description:ident", r, space));
BOOST_TEST(test("description: ident", r, space));
BOOST_TEST(!test("descriptionident", r, space));
}
return boost::report_errors();
}