#include #include #include #include namespace boost { namespace spirit { namespace x3 { template struct parser { Derived const& derived() const { return *static_cast(this); } }; template struct char_parser : parser> { char_parser(Char ch) : ch(ch) {} template bool parse(Iterator& first, Iterator last, Context const& ctx) const { if (first != last && *first == ch) { ++first; return true; } return false; } Char ch; }; template inline char_parser char_(Char ch) { return char_parser(ch); }; template struct sequence_parser : parser> { sequence_parser(Left left, Right right) : left(left), right(right) {} template bool parse(Iterator& first, Iterator last, Context const& ctx) const { return left.parse(first, last, ctx) && right.parse(first, last, ctx); } Left left; Right right; }; template inline sequence_parser operator>>( parser const& left, parser const& right) { return sequence_parser( left.derived(), right.derived()); } template struct alternative_parser : parser> { alternative_parser(Left left, Right right) : left(left), right(right) {} template bool parse(Iterator& first, Iterator last, Context const& ctx) const { if (left.parse(first, last, ctx)) return true; return right.parse(first, last, ctx); } Left left; Right right; }; template inline alternative_parser operator|( parser const& left, parser const& right) { return alternative_parser( left.derived(), right.derived()); } template struct context { context(T const& val, NextContext const& next_ctx) : val(val), next_ctx(next_ctx) {} T const& get(mpl::identity) const { return val; } template decltype(std::declval().get(Identity())) get(Identity id) const { return next_ctx.get(id); } T const& val; NextContext const& next_ctx; }; struct empty_context { struct undefined {}; template undefined get(ID) const { return undefined(); } }; template struct rule_definition : parser> { rule_definition(RHS rhs) : rhs(rhs) {} template bool parse(Iterator& first, Iterator last, Context const& ctx) const { context this_ctx(rhs, ctx); return rhs.parse(first, last, this_ctx); } RHS rhs; }; template struct rule : parser> { template rule_definition operator=(parser const& definition) const { return rule_definition(definition.derived()); } template bool parse(Iterator& first, Iterator last, Context const& ctx) const { return ctx.get(mpl::identity()).parse(first, last, ctx); } }; template inline bool parse(parser const& p, Iterator& first, Iterator last) { empty_context ctx; return p.derived().parse(first, last, ctx); } }}} /////////////////////////////////////////////////////////////////////////////// // test code template bool test_parse(Parser const& p, char const* in) { return parse(p, in, in + std::strlen(in)); } namespace parser { using namespace boost::spirit::x3; namespace g_definition { auto const x = rule(); auto const ax = char_('a') >> x; auto const g = x = char_('x') | ax; } using g_definition::g; } int main() { { // a non-recursive parser using namespace boost::spirit::x3; auto abc = char_('a') >> char_('b') >> char_('c'); std::cout << test_parse(abc, "abc") << std::endl; std::cout << test_parse(abc, "abx") << std::endl; std::cout << "==========================================" << std::endl; } { // a recursive rule using namespace boost::spirit::x3; auto const x = rule(); auto const ax = char_('a') >> x; auto const start = (x = char_('x') | ax); std::cout << test_parse(start, "x") << std::endl; std::cout << test_parse(start, "ax") << std::endl; std::cout << test_parse(start, "aaaaax") << std::endl; std::cout << test_parse(start, "aaz") << std::endl; std::cout << "==========================================" << std::endl; } { // a grammar ( gcc and clang only: see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3582.html ) using namespace boost::spirit::x3; auto g = []() { rule x; auto ax = char_('a') >> x; return x = char_('x') | ax; }(); std::cout << test_parse(g, "x") << std::endl; std::cout << test_parse(g, "ax") << std::endl; std::cout << test_parse(g, "aaaaax") << std::endl; std::cout << test_parse(g, "aaz") << std::endl; std::cout << "==========================================" << std::endl; } { // another grammar using namespaces (standard c++, see grammar g definition above in namespace parser.) using parser::g; std::cout << test_parse(g, "x") << std::endl; std::cout << test_parse(g, "ax") << std::endl; std::cout << test_parse(g, "aaaaax") << std::endl; std::cout << test_parse(g, "aaz") << std::endl; std::cout << "==========================================" << std::endl; } return 0; }