1 // Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <boost/metaparse/sequence_apply.hpp>
7 #include <boost/metaparse/is_error.hpp>
8 #include <boost/metaparse/start.hpp>
9 #include <boost/metaparse/get_result.hpp>
10 #include <boost/metaparse/always.hpp>
11 #include <boost/metaparse/one_char.hpp>
12 
13 #include "common.hpp"
14 
15 #include <boost/mpl/equal_to.hpp>
16 #include <boost/mpl/list.hpp>
17 #include <boost/mpl/at.hpp>
18 #include <boost/mpl/vector_c.hpp>
19 #include <boost/mpl/vector.hpp>
20 #include <boost/mpl/assert.hpp>
21 #include <boost/mpl/char.hpp>
22 
23 #include <boost/type_traits/is_same.hpp>
24 
25 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
26 #include <boost/preprocessor/repetition/enum_params.hpp>
27 #include <boost/preprocessor/repetition/enum.hpp>
28 #include <boost/preprocessor/tuple/eat.hpp>
29 #include <boost/preprocessor/cat.hpp>
30 
31 #include "test_case.hpp"
32 
33 namespace
34 {
35 #ifdef BOOST_METAPARSE_C_VALUE
36 #  error BOOST_METAPARSE_C_VALUE already defined
37 #endif
38 #define BOOST_METAPARSE_C_VALUE(z, n, unused) BOOST_PP_CAT(C, n)::value
39 
40 #ifdef BOOST_METAPARSE_TEMPLATE
41 #  error BOOST_METAPARSE_TEMPLATE already defined
42 #endif
43 #define BOOST_METAPARSE_TEMPLATE(z, n, unused) \
44   template <BOOST_PP_ENUM(n, char BOOST_PP_TUPLE_EAT(3), ~)> \
45   struct BOOST_PP_CAT(template_c, n) \
46   { \
47     typedef BOOST_PP_CAT(template_c, n) type; \
48   }; \
49   \
50   template <BOOST_PP_ENUM_PARAMS(n, class C)> \
51   struct BOOST_PP_CAT(template, n) \
52   { \
53     typedef \
54       BOOST_PP_CAT(template_c, n)< \
55         BOOST_PP_ENUM(n, BOOST_METAPARSE_C_VALUE, ~) \
56       > \
57       type; \
58   };
59 
60   BOOST_PP_REPEAT_FROM_TO(1, 4, BOOST_METAPARSE_TEMPLATE, ~)
61 
62 #undef BOOST_METAPARSE_TEMPLATE
63 #undef BOOST_METAPARSE_C_VALUE
64 
65   template <class T> struct has_no_type {};
66 
67   // "is_same<T::type::type, double_eval<T>::type>" - helper tool to avoid
68   // writing type::type (which is interpreted as the constructor of ::type by
69   // msvc-7.1)
70   template <class T> struct double_eval : T::type {};
71 }
72 
BOOST_METAPARSE_TEST_CASE(sequence_apply)73 BOOST_METAPARSE_TEST_CASE(sequence_apply)
74 {
75   using boost::metaparse::get_result;
76   using boost::metaparse::sequence_apply1;
77   using boost::metaparse::sequence_apply2;
78   using boost::metaparse::sequence_apply3;
79   using boost::metaparse::start;
80   using boost::metaparse::is_error;
81   using boost::metaparse::always;
82   using boost::metaparse::one_char;
83 
84   using boost::mpl::list;
85   using boost::mpl::equal_to;
86   using boost::mpl::at_c;
87   using boost::mpl::vector_c;
88   using boost::mpl::vector;
89   using boost::mpl::char_;
90 
91   using boost::is_same;
92 
93   typedef always<one_char, int> always_int;
94 
95   // test_one_parser
96   BOOST_MPL_ASSERT((
97     is_same<
98       template_c1<'h'>,
99       double_eval<
100         get_result<
101           sequence_apply1<template1, lit_h>::apply<str_hello, start>
102         >
103       >::type
104     >
105   ));
106 
107   // test_one_failing_parser
108   BOOST_MPL_ASSERT((
109     is_error<sequence_apply1<template1, lit_e>::apply<str_hello, start> >
110   ));
111 
112   // test_two_chars
113   BOOST_MPL_ASSERT((
114     is_same<
115       template_c2<'h', 'e'>,
116       double_eval<
117         get_result<
118           sequence_apply2<template2, lit_h, lit_e>::apply<str_hello, start>
119         >
120       >::type
121     >
122   ));
123 
124   // test_first_fails
125   BOOST_MPL_ASSERT((
126     is_error<sequence_apply2<template2, lit_x, lit_e>::apply<str_hello, start> >
127   ));
128 
129   // test_second_fails
130   BOOST_MPL_ASSERT((
131     is_error<sequence_apply2<template2, lit_h, lit_x>::apply<str_hello, start> >
132   ));
133 
134   // test_empty_input
135   BOOST_MPL_ASSERT((
136     is_error<sequence_apply2<template2, lit_h, lit_e>::apply<str_,start> >
137   ));
138 
139   // test_three_chars
140   BOOST_MPL_ASSERT((
141     is_same<
142       template_c3<'h', 'e', 'l'>,
143       double_eval<
144         get_result<
145           sequence_apply3<template3, lit_h, lit_e, lit_l>
146             ::apply<str_hello, start>
147         >
148       >::type
149     >
150   ));
151 
152   // test_no_extra_evaluation
153   BOOST_MPL_ASSERT((
154     is_same<
155       has_no_type<int>,
156       get_result<
157         sequence_apply1<has_no_type, always_int>::apply<str_ca, start>
158       >::type
159     >
160   ));
161 }
162 
163