]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright Abel Sinkovics (abel@sinkovics.hu) 2012. |
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/repeated.hpp> | |
7 | #include <boost/metaparse/sequence.hpp> | |
8 | #include <boost/metaparse/lit_c.hpp> | |
9 | #include <boost/metaparse/last_of.hpp> | |
10 | #include <boost/metaparse/space.hpp> | |
11 | #include <boost/metaparse/int_.hpp> | |
12 | #include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp> | |
13 | #include <boost/metaparse/one_of.hpp> | |
14 | #include <boost/metaparse/get_result.hpp> | |
15 | #include <boost/metaparse/token.hpp> | |
16 | #include <boost/metaparse/entire_input.hpp> | |
17 | #include <boost/metaparse/string.hpp> | |
18 | #include <boost/metaparse/transform.hpp> | |
19 | #include <boost/metaparse/always.hpp> | |
20 | #include <boost/metaparse/build_parser.hpp> | |
21 | ||
22 | #include <boost/mpl/apply_wrap.hpp> | |
23 | #include <boost/mpl/front.hpp> | |
24 | #include <boost/mpl/back.hpp> | |
25 | #include <boost/mpl/plus.hpp> | |
26 | #include <boost/mpl/minus.hpp> | |
27 | #include <boost/mpl/times.hpp> | |
28 | #include <boost/mpl/divides.hpp> | |
29 | #include <boost/mpl/bool.hpp> | |
30 | #include <boost/mpl/equal_to.hpp> | |
31 | #include <boost/mpl/if.hpp> | |
32 | ||
33 | using boost::metaparse::sequence; | |
34 | using boost::metaparse::lit_c; | |
35 | using boost::metaparse::last_of; | |
36 | using boost::metaparse::space; | |
37 | using boost::metaparse::repeated; | |
38 | using boost::metaparse::build_parser; | |
39 | using boost::metaparse::int_; | |
40 | using boost::metaparse::foldl_reject_incomplete_start_with_parser; | |
41 | using boost::metaparse::get_result; | |
42 | using boost::metaparse::one_of; | |
43 | using boost::metaparse::token; | |
44 | using boost::metaparse::entire_input; | |
45 | using boost::metaparse::transform; | |
46 | using boost::metaparse::always; | |
47 | ||
48 | using boost::mpl::apply_wrap1; | |
49 | using boost::mpl::front; | |
50 | using boost::mpl::back; | |
51 | using boost::mpl::plus; | |
52 | using boost::mpl::minus; | |
53 | using boost::mpl::times; | |
54 | using boost::mpl::divides; | |
55 | using boost::mpl::if_; | |
56 | using boost::mpl::bool_; | |
57 | using boost::mpl::equal_to; | |
58 | ||
59 | /* | |
60 | * The grammar | |
61 | * | |
62 | * expression ::= plus_exp | |
63 | * plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)* | |
64 | * prod_exp ::= value_exp ((mult_token | div_token) value_exp)* | |
65 | * value_exp ::= int_token | '_' | |
66 | */ | |
67 | ||
68 | typedef token<lit_c<'+'> > plus_token; | |
69 | typedef token<lit_c<'-'> > minus_token; | |
70 | typedef token<lit_c<'*'> > mult_token; | |
71 | typedef token<lit_c<'/'> > div_token; | |
72 | ||
73 | typedef token<int_> int_token; | |
74 | typedef token<lit_c<'_'> > arg_token; | |
75 | ||
76 | template <class T, char C> | |
77 | struct is_c : bool_<T::type::value == C> {}; | |
78 | ||
79 | struct build_plus | |
80 | { | |
81 | template <class A, class B> | |
82 | struct _plus | |
83 | { | |
84 | typedef _plus type; | |
85 | ||
86 | template <class T> | |
87 | struct apply : | |
88 | plus<typename apply_wrap1<A, T>::type, typename apply_wrap1<B, T>::type> | |
89 | {}; | |
90 | }; | |
91 | ||
92 | template <class A, class B> | |
93 | struct _minus | |
94 | { | |
95 | typedef _minus type; | |
96 | ||
97 | template <class T> | |
98 | struct apply : | |
99 | minus<typename apply_wrap1<A, T>::type, typename apply_wrap1<B, T>::type> | |
100 | {}; | |
101 | }; | |
102 | ||
103 | template <class State, class C> | |
104 | struct apply : | |
105 | if_< | |
106 | typename is_c<front<C>, '+'>::type, | |
107 | _plus<State, typename back<C>::type>, | |
108 | _minus<State, typename back<C>::type> | |
109 | > | |
110 | {}; | |
111 | }; | |
112 | ||
113 | struct build_mult | |
114 | { | |
115 | template <class A, class B> | |
116 | struct _mult | |
117 | { | |
118 | typedef _mult type; | |
119 | ||
120 | template <class T> | |
121 | struct apply : | |
122 | times<typename apply_wrap1<A, T>::type, typename apply_wrap1<B, T>::type> | |
123 | {}; | |
124 | }; | |
125 | ||
126 | template <class A, class B> | |
127 | struct _div | |
128 | { | |
129 | typedef _div type; | |
130 | ||
131 | template <class T> | |
132 | struct apply : | |
133 | divides< | |
134 | typename apply_wrap1<A, T>::type, | |
135 | typename apply_wrap1<B, T>::type | |
136 | > | |
137 | {}; | |
138 | }; | |
139 | ||
140 | template <class State, class C> | |
141 | struct apply : | |
142 | if_< | |
143 | typename is_c<front<C>, '*'>::type, | |
144 | _mult<State, typename back<C>::type>, | |
145 | _div<State, typename back<C>::type> | |
146 | > | |
147 | {}; | |
148 | }; | |
149 | ||
150 | class build_value | |
151 | { | |
152 | private: | |
153 | template <class V> | |
154 | struct impl | |
155 | { | |
156 | typedef impl type; | |
157 | ||
158 | template <class T> | |
159 | struct apply : V {}; | |
160 | }; | |
161 | ||
162 | public: | |
163 | typedef build_value type; | |
164 | ||
165 | template <class V> | |
166 | struct apply : impl<typename V::type> {}; | |
167 | }; | |
168 | ||
169 | struct arg | |
170 | { | |
171 | typedef arg type; | |
172 | ||
173 | template <class T> | |
174 | struct apply | |
175 | { | |
176 | typedef T type; | |
177 | }; | |
178 | }; | |
179 | ||
180 | typedef | |
181 | one_of<transform<int_token, build_value>, always<arg_token, arg> > | |
182 | value_exp; | |
183 | ||
184 | typedef | |
185 | foldl_reject_incomplete_start_with_parser< | |
186 | sequence<one_of<mult_token, div_token>, value_exp>, | |
187 | value_exp, | |
188 | build_mult | |
189 | > | |
190 | prod_exp; | |
191 | ||
192 | typedef | |
193 | foldl_reject_incomplete_start_with_parser< | |
194 | sequence<one_of<plus_token, minus_token>, prod_exp>, | |
195 | prod_exp, | |
196 | build_plus | |
197 | > | |
198 | plus_exp; | |
199 | ||
200 | typedef last_of<repeated<space>, plus_exp> expression; | |
201 | ||
202 | typedef build_parser<entire_input<expression> > metafunction_parser; | |
203 | ||
b32b8144 | 204 | #if BOOST_METAPARSE_STD < 2011 |
7c673cae FG |
205 | |
206 | template <class Exp> | |
207 | struct meta_lambda : apply_wrap1<metafunction_parser, Exp> {}; | |
208 | ||
209 | int main() | |
210 | { | |
211 | using std::cout; | |
212 | using std::endl; | |
213 | using boost::metaparse::string; | |
214 | ||
215 | typedef meta_lambda<string<'1','3'> >::type metafunction_class_1; | |
216 | typedef meta_lambda<string<'2',' ','+',' ','3'> >::type metafunction_class_2; | |
217 | typedef meta_lambda<string<'2',' ','*',' ','2'> >::type metafunction_class_3; | |
218 | typedef | |
219 | meta_lambda<string<' ','1','+',' ','2','*','4','-','6','/','2'> >::type | |
220 | metafunction_class_4; | |
221 | typedef meta_lambda<string<'2',' ','*',' ','_'> >::type metafunction_class_5; | |
222 | ||
223 | typedef boost::mpl::int_<11> int11; | |
224 | ||
225 | cout | |
226 | << apply_wrap1<metafunction_class_1, int11>::type::value << endl | |
227 | << apply_wrap1<metafunction_class_2, int11>::type::value << endl | |
228 | << apply_wrap1<metafunction_class_3, int11>::type::value << endl | |
229 | << apply_wrap1<metafunction_class_4, int11>::type::value << endl | |
230 | << apply_wrap1<metafunction_class_5, int11>::type::value << endl | |
231 | ; | |
232 | } | |
233 | ||
234 | #else | |
235 | ||
236 | #ifdef META_LAMBDA | |
237 | #error META_LAMBDA already defined | |
238 | #endif | |
239 | #define META_LAMBDA(exp) \ | |
240 | apply_wrap1<metafunction_parser, BOOST_METAPARSE_STRING(#exp)>::type | |
241 | ||
242 | int main() | |
243 | { | |
244 | using std::cout; | |
245 | using std::endl; | |
246 | ||
247 | typedef META_LAMBDA(13) metafunction_class_1; | |
248 | typedef META_LAMBDA(2 + 3) metafunction_class_2; | |
249 | typedef META_LAMBDA(2 * 2) metafunction_class_3; | |
250 | typedef META_LAMBDA( 1+ 2*4-6/2) metafunction_class_4; | |
251 | typedef META_LAMBDA(2 * _) metafunction_class_5; | |
252 | ||
253 | typedef boost::mpl::int_<11> int11; | |
254 | ||
255 | cout | |
256 | << apply_wrap1<metafunction_class_1, int11>::type::value << endl | |
257 | << apply_wrap1<metafunction_class_2, int11>::type::value << endl | |
258 | << apply_wrap1<metafunction_class_3, int11>::type::value << endl | |
259 | << apply_wrap1<metafunction_class_4, int11>::type::value << endl | |
260 | << apply_wrap1<metafunction_class_5, int11>::type::value << endl | |
261 | ; | |
262 | } | |
263 | ||
264 | #endif | |
265 |