#include <iostream> #include <utility> #include <cstring> #include <boost/mpl/identity.hpp> namespace boost { namespace spirit { namespace x3 { template <typename Derived> struct parser { Derived const& derived() const { return *static_cast<Derived const*>(this); } }; template <typename Char> struct char_parser : parser<char_parser<Char>> { char_parser(Char ch) : ch(ch) {} template <typename Iterator, typename Context> bool parse(Iterator& first, Iterator last, Context const& ctx) const { if (first != last && *first == ch) { ++first; return true; } return false; } Char ch; }; template <typename Char> inline char_parser<Char> char_(Char ch) { return char_parser<Char>(ch); }; template <typename Left, typename Right> struct sequence_parser : parser<sequence_parser<Left, Right>> { sequence_parser(Left left, Right right) : left(left), right(right) {} template <typename Iterator, typename Context> 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 <typename Left, typename Right> inline sequence_parser<Left, Right> operator>>( parser<Left> const& left, parser<Right> const& right) { return sequence_parser<Left, Right>( left.derived(), right.derived()); } template <typename Left, typename Right> struct alternative_parser : parser<alternative_parser<Left, Right>> { alternative_parser(Left left, Right right) : left(left), right(right) {} template <typename Iterator, typename Context> 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 <typename Left, typename Right> inline alternative_parser<Left, Right> operator|( parser<Left> const& left, parser<Right> const& right) { return alternative_parser<Left, Right>( left.derived(), right.derived()); } template <typename ID, typename T, typename NextContext> struct context { context(T const& val, NextContext const& next_ctx) : val(val), next_ctx(next_ctx) {} T const& get(mpl::identity<ID>) const { return val; } template <typename Identity> decltype(std::declval<NextContext>().get(Identity())) get(Identity id) const { return next_ctx.get(id); } T const& val; NextContext const& next_ctx; }; struct empty_context { struct undefined {}; template <typename ID> undefined get(ID) const { return undefined(); } }; template <typename ID, typename RHS> struct rule_definition : parser<rule_definition<ID, RHS>> { rule_definition(RHS rhs) : rhs(rhs) {} template <typename Iterator, typename Context> bool parse(Iterator& first, Iterator last, Context const& ctx) const { context<ID, RHS, Context> this_ctx(rhs, ctx); return rhs.parse(first, last, this_ctx); } RHS rhs; }; template <typename ID> struct rule : parser<rule<ID>> { template <typename Derived> rule_definition<ID, Derived> operator=(parser<Derived> const& definition) const { return rule_definition<ID, Derived>(definition.derived()); } template <typename Iterator, typename Context> bool parse(Iterator& first, Iterator last, Context const& ctx) const { return ctx.get(mpl::identity<ID>()).parse(first, last, ctx); } }; template <typename Iterator, typename Derived> inline bool parse(parser<Derived> const& p, Iterator& first, Iterator last) { empty_context ctx; return p.derived().parse(first, last, ctx); } }}} /////////////////////////////////////////////////////////////////////////////// // test code template <typename Parser> 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<class x>(); 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<class x>(); 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<class x> 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; }