• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
204 #if BOOST_METAPARSE_STD < 2011
205 
206 template <class Exp>
207 struct meta_lambda : apply_wrap1<metafunction_parser, Exp> {};
208 
main()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 
main()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 
266