• 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/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