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