123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- // 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 <boost/metaparse/sequence.hpp>
- #include <boost/metaparse/lit_c.hpp>
- #include <boost/metaparse/foldl.hpp>
- #include <boost/metaparse/entire_input.hpp>
- #include <boost/metaparse/string.hpp>
- #include <boost/metaparse/build_parser.hpp>
- #include <boost/metaparse/get_result.hpp>
- #include <boost/metaparse/start.hpp>
- #include <boost/metaparse/last_of.hpp>
- #include <boost/metaparse/iterate_c.hpp>
- #include <boost/metaparse/one_char.hpp>
- #include <boost/metaparse/return_.hpp>
- #include <boost/mpl/apply_wrap.hpp>
- #include <boost/mpl/at.hpp>
- #include <boost/mpl/int.hpp>
- #include <boost/mpl/plus.hpp>
- #include <boost/mpl/front.hpp>
- #include <boost/mpl/pop_front.hpp>
- #include <boost/mpl/size.hpp>
- #include <iostream>
- #include <string>
- #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 <class T>
- constexpr static parsed build()
- {
- return
- parsed(
- at_c<typename T::type, 0>::type::value,
- at_c<typename T::type, 1>::type::value,
- at_c<typename T::type, 2>::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 <class T, int Len>
- struct const_list
- {
- T head;
- const_list<T, Len - 1> tail;
- constexpr const_list(const T& h, const const_list<T, Len - 1>& t) :
- head(h),
- tail(t)
- {}
- constexpr const_list<T, Len + 1> push_front(const T& t) const
- {
- return const_list<T, Len + 1>(t, *this);
- }
- constexpr T at(int n) const
- {
- return n == 0 ? head : tail.at(n - 1);
- }
- };
- template <class T>
- struct const_list<T, 0>
- {
- constexpr const_list<T, 1> push_front(const T& t) const
- {
- return const_list<T, 1>(t, *this);
- }
- constexpr T at(int) const
- {
- return T();
- }
- };
- template <class T, int N, int from = 0>
- struct to_list
- {
- static constexpr const_list<T, N - from> run(const T (&s)[N])
- {
- return const_list<T, N - from>(s[from], to_list<T, N, from + 1>::run(s));
- }
- };
- template <class T, int N>
- struct to_list<T, N, N>
- {
- static constexpr const_list<T, 0> run(const T (&s)[N])
- {
- return const_list<T, 0>();
- }
- };
- 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 <char C, int N>
- constexpr presult parse_cs(const const_list<char, N>& s, int from)
- {
- return
- from < N ?
- (s.at(from) == C ? parse_cs<C, N>(s, from + 1).incr() : presult(0, from)) :
- presult(0, from);
- }
- template <int N>
- constexpr parsed parse_impl(const const_list<char, N>& 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 <int N>
- constexpr parsed parse(const char (&s)[N])
- {
- return parse_impl(to_list<char, N>::run(s));
- }
- // TMP parser
- struct count
- {
- typedef count type;
- template <class State, class C>
- struct apply : plus<int_<1>, State> {};
- };
- typedef foldl<lit_c<'a'>, int_<0>, count> as;
- typedef foldl<lit_c<'b'>, int_<0>, count> bs;
- typedef sequence<as, bs, as> s;
- typedef build_parser<entire_input<s> > parser;
- #ifdef P
- #error P already defined
- #endif
- #define P(x) \
- parsed::build<boost::mpl::apply_wrap1<parser, BOOST_METAPARSE_STRING(#x)> >()
- // Mixed parser
- template <class ValueType, class L, int Len>
- struct tmp_to_const_list_impl
- {
- constexpr static const_list<ValueType, Len> run()
- {
- return
- const_list<ValueType, Len>(
- front<L>::type::value,
- tmp_to_const_list_impl<
- ValueType,
- typename pop_front<L>::type,
- Len - 1
- >::run()
- );
- }
- };
- template <class ValueType, class L>
- struct tmp_to_const_list_impl<ValueType, L, 0>
- {
- constexpr static const_list<ValueType, 0> run()
- {
- return const_list<ValueType, 0>();
- }
- };
- template <class ValueType, class L>
- struct tmp_to_const_list :
- tmp_to_const_list_impl<ValueType, L, size<L>::type::value>
- {};
- template <char C>
- struct parse_with_constexpr
- {
- typedef parse_with_constexpr type;
- template <class S>
- static constexpr presult impl()
- {
- return
- parse_cs<C, size<S>::type::value>(tmp_to_const_list<char, S>::run(), 0);
- }
- template <class S, class Pos>
- struct apply :
- apply_wrap2<
- last_of<
- iterate_c<one_char, impl<S>().remaining_from>,
- return_<int_<impl<S>().value> >
- >,
- S,
- Pos
- >
- {};
- };
- typedef parse_with_constexpr<'b'> bs_mixed;
- typedef sequence<as, bs_mixed, as> s_mixed;
- typedef build_parser<entire_input<s_mixed> > parser_mixed;
- #ifdef P_MIXED
- #error P_MIXED already defined
- #endif
- #define P_MIXED(x) \
- parsed::build< \
- boost::mpl::apply_wrap1<parser_mixed, BOOST_METAPARSE_STRING(#x)> \
- >()
- 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
|