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/bool.hpp>
26 #include <boost/mpl/if.hpp>
27
28 using boost::metaparse::sequence;
29 using boost::metaparse::lit_c;
30 using boost::metaparse::last_of;
31 using boost::metaparse::space;
32 using boost::metaparse::repeated;
33 using boost::metaparse::build_parser;
34 using boost::metaparse::int_;
35 using boost::metaparse::foldl_reject_incomplete_start_with_parser;
36 using boost::metaparse::get_result;
37 using boost::metaparse::one_of;
38 using boost::metaparse::token;
39 using boost::metaparse::entire_input;
40 using boost::metaparse::transform;
41 using boost::metaparse::always;
42
43 using boost::mpl::apply_wrap1;
44 using boost::mpl::front;
45 using boost::mpl::back;
46 using boost::mpl::if_;
47 using boost::mpl::bool_;
48
49 /*
50 * The grammar
51 *
52 * expression ::= plus_exp
53 * plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*
54 * prod_exp ::= value_exp ((mult_token | div_token) value_exp)*
55 * value_exp ::= int_token | '_'
56 */
57
58 typedef token<lit_c<'+'> > plus_token;
59 typedef token<lit_c<'-'> > minus_token;
60 typedef token<lit_c<'*'> > mult_token;
61 typedef token<lit_c<'/'> > div_token;
62
63 typedef token<int_> int_token;
64 typedef token<lit_c<'_'> > arg_token;
65
66 template <class T, char C>
67 struct is_c : bool_<T::type::value == C> {};
68
69 struct build_plus
70 {
71 template <class A, class B>
72 class _plus
73 {
74 public:
75 typedef _plus type;
76
77 template <class T>
operator ()(T t) const78 T operator()(T t) const
79 {
80 return _left(t) + _right(t);
81 }
82 private:
83 typename A::type _left;
84 typename B::type _right;
85 };
86
87 template <class A, class B>
88 class _minus
89 {
90 public:
91 typedef _minus type;
92
93 template <class T>
operator ()(T t) const94 T operator()(T t) const
95 {
96 return _left(t) - _right(t);
97 }
98 private:
99 typename A::type _left;
100 typename B::type _right;
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 class _mult
117 {
118 public:
119 typedef _mult type;
120
121 template <class T>
operator ()(T t) const122 T operator()(T t) const
123 {
124 return _left(t) * _right(t);
125 }
126 private:
127 typename A::type _left;
128 typename B::type _right;
129 };
130
131 template <class A, class B>
132 class _div
133 {
134 public:
135 typedef _div type;
136
137 template <class T>
operator ()(T t) const138 T operator()(T t) const
139 {
140 return _left(t) / _right(t);
141 }
142 private:
143 typename A::type _left;
144 typename B::type _right;
145 };
146
147 template <class State, class C>
148 struct apply :
149 if_<
150 typename is_c<front<C>, '*'>::type,
151 _mult<State, typename back<C>::type>,
152 _div<State, typename back<C>::type>
153 >
154 {};
155 };
156
157 struct build_value
158 {
159 typedef build_value type;
160
161 template <class V>
162 struct apply
163 {
164 typedef apply type;
165
166 template <class T>
operator ()build_value::apply167 int operator()(T) const
168 {
169 return V::type::value;
170 }
171 };
172 };
173
174 struct arg
175 {
176 typedef arg type;
177
178 template <class T>
operator ()arg179 T operator()(T t) const
180 {
181 return t;
182 }
183 };
184
185 typedef
186 one_of<transform<int_token, build_value>, always<arg_token, arg> >
187 value_exp;
188
189 typedef
190 foldl_reject_incomplete_start_with_parser<
191 sequence<one_of<mult_token, div_token>, value_exp>,
192 value_exp,
193 build_mult
194 >
195 prod_exp;
196
197 typedef
198 foldl_reject_incomplete_start_with_parser<
199 sequence<one_of<plus_token, minus_token>, prod_exp>,
200 prod_exp,
201 build_plus
202 >
203 plus_exp;
204
205 typedef last_of<repeated<space>, plus_exp> expression;
206
207 typedef build_parser<entire_input<expression> > function_parser;
208
209 #if BOOST_METAPARSE_STD < 2011
210
211 template <class Exp>
212 struct lambda : apply_wrap1<function_parser, Exp> {};
213
214 using boost::metaparse::string;
215
216 lambda<string<'1','3'> >::type f1;
217 lambda<string<'2',' ','+',' ','3'> >::type f2;
218 lambda<string<'2',' ','*',' ','2'> >::type f3;
219 lambda<string<' ','1','+',' ','2','*','4','-','6','/','2'> >::type f4;
220 lambda<string<'2',' ','*',' ','_'> >::type f5;
221
222 #else
223
224 #ifdef LAMBDA
225 #error LAMBDA already defined
226 #endif
227 #define LAMBDA(exp) apply_wrap1<function_parser, BOOST_METAPARSE_STRING(#exp)>::type
228
229 LAMBDA(13) f1;
230 LAMBDA(2 + 3) f2;
231 LAMBDA(2 * 2) f3;
232 LAMBDA( 1+ 2*4-6/2) f4;
233 LAMBDA(2 * _) f5;
234
235 #endif
236
main()237 int main()
238 {
239 using std::cout;
240 using std::endl;
241
242 cout
243 << f1(11) << endl
244 << f2(11) << endl
245 << f3(11) << endl
246 << f4(11) << endl
247 << f5(11) << endl
248 << f5(1.1) << endl
249 ;
250 }
251
252
253