// Copyright Abel Sinkovics (abel@sinkovics.hu) 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if BOOST_METAPARSE_STD < 2011 int main() { std::cout << "This example focuses on constexpr, which is not supported" << std::endl; } #else using boost::metaparse::sequence; using boost::metaparse::lit_c; using boost::metaparse::build_parser; using boost::metaparse::foldl; using boost::metaparse::entire_input; using boost::metaparse::get_result; using boost::metaparse::start; using boost::metaparse::last_of; using boost::metaparse::iterate_c; using boost::metaparse::one_char; using boost::metaparse::return_; using boost::mpl::apply_wrap1; using boost::mpl::apply_wrap2; using boost::mpl::plus; using boost::mpl::int_; using boost::mpl::at_c; using boost::mpl::front; using boost::mpl::pop_front; using boost::mpl::size; using std::ostream; /* * The grammar * * S ::= a* b* a* */ struct parsed { template constexpr static parsed build() { return parsed( at_c::type::value, at_c::type::value, at_c::type::value ); } constexpr parsed(int a1, int b, int a2) : a_count1(a1), b_count(b), a_count2(a2) {}; int a_count1; int b_count; int a_count2; }; ostream& operator<<(ostream& o, const parsed& p) { return o << "(" << p.a_count1 << ", " << p.b_count << ", " << p.a_count2 << ")"; } // constexpr parser template struct const_list { T head; const_list tail; constexpr const_list(const T& h, const const_list& t) : head(h), tail(t) {} constexpr const_list push_front(const T& t) const { return const_list(t, *this); } constexpr T at(int n) const { return n == 0 ? head : tail.at(n - 1); } }; template struct const_list { constexpr const_list push_front(const T& t) const { return const_list(t, *this); } constexpr T at(int) const { return T(); } }; template struct to_list { static constexpr const_list run(const T (&s)[N]) { return const_list(s[from], to_list::run(s)); } }; template struct to_list { static constexpr const_list run(const T (&s)[N]) { return const_list(); } }; struct presult { int value; int remaining_from; constexpr presult(int v, int r) : value(v), remaining_from(r) {} constexpr presult incr() const { return presult(value + 1, remaining_from); } }; template constexpr presult parse_cs(const const_list& s, int from) { return from < N ? (s.at(from) == C ? parse_cs(s, from + 1).incr() : presult(0, from)) : presult(0, from); } template constexpr parsed parse_impl(const const_list& s) { return parsed( parse_cs<'a', N>(s, 0).value, parse_cs<'b', N>(s, parse_cs<'a', N>(s, 0).remaining_from).value, parse_cs<'a', N>( s, parse_cs<'b', N>( s, parse_cs<'a', N>(s, 0).remaining_from ).remaining_from ).value ); } template constexpr parsed parse(const char (&s)[N]) { return parse_impl(to_list::run(s)); } // TMP parser struct count { typedef count type; template struct apply : plus, State> {}; }; typedef foldl, int_<0>, count> as; typedef foldl, int_<0>, count> bs; typedef sequence s; typedef build_parser > parser; #ifdef P #error P already defined #endif #define P(x) \ parsed::build >() // Mixed parser template struct tmp_to_const_list_impl { constexpr static const_list run() { return const_list( front::type::value, tmp_to_const_list_impl< ValueType, typename pop_front::type, Len - 1 >::run() ); } }; template struct tmp_to_const_list_impl { constexpr static const_list run() { return const_list(); } }; template struct tmp_to_const_list : tmp_to_const_list_impl::type::value> {}; template struct parse_with_constexpr { typedef parse_with_constexpr type; template static constexpr presult impl() { return parse_cs::type::value>(tmp_to_const_list::run(), 0); } template struct apply : apply_wrap2< last_of< iterate_c().remaining_from>, return_().value> > >, S, Pos > {}; }; typedef parse_with_constexpr<'b'> bs_mixed; typedef sequence s_mixed; typedef build_parser > parser_mixed; #ifdef P_MIXED #error P_MIXED already defined #endif #define P_MIXED(x) \ parsed::build< \ boost::mpl::apply_wrap1 \ >() int main() { using std::cout; using std::endl; cout << "TMP only parsers:" << endl << P(aba) << endl << P(aaaaaaabbbbaaaa) << endl << endl << "constexpr only parsers:" << endl << parse("") << endl << parse("aba") << endl << parse("aaaaaaabbbbaaaa") << endl << endl << "mixed parsers:" << endl << P_MIXED(aba) << endl << P_MIXED(aaaaaaabbbbaaaa) << endl << endl ; } #endif