summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/metaparse/example/constexpr_parser/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/metaparse/example/constexpr_parser/main.cpp')
-rw-r--r--src/boost/libs/metaparse/example/constexpr_parser/main.cpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/src/boost/libs/metaparse/example/constexpr_parser/main.cpp b/src/boost/libs/metaparse/example/constexpr_parser/main.cpp
new file mode 100644
index 000000000..4fe291b07
--- /dev/null
+++ b/src/boost/libs/metaparse/example/constexpr_parser/main.cpp
@@ -0,0 +1,318 @@
+// 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
+