• 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 #define BOOST_MPL_LIMIT_STRING_SIZE 64
7 #define BOOST_METAPARSE_LIMIT_STRING_SIZE BOOST_MPL_LIMIT_STRING_SIZE
8 
9 #include <boost/metaparse/grammar.hpp>
10 
11 #include <boost/metaparse/string.hpp>
12 #include <boost/metaparse/build_parser.hpp>
13 #include <boost/metaparse/token.hpp>
14 #include <boost/metaparse/entire_input.hpp>
15 #include <boost/metaparse/int_.hpp>
16 #include <boost/metaparse/transform.hpp>
17 
18 #include <boost/mpl/apply_wrap.hpp>
19 #include <boost/mpl/front.hpp>
20 #include <boost/mpl/back.hpp>
21 #include <boost/mpl/if.hpp>
22 #include <boost/mpl/bool.hpp>
23 #include <boost/mpl/fold.hpp>
24 
25 using boost::mpl::apply_wrap1;
26 using boost::mpl::front;
27 using boost::mpl::back;
28 using boost::mpl::if_;
29 using boost::mpl::bool_;
30 
31 using boost::metaparse::build_parser;
32 using boost::metaparse::token;
33 using boost::metaparse::entire_input;
34 using boost::metaparse::int_;
35 using boost::metaparse::grammar;
36 using boost::metaparse::transform;
37 
38 #if BOOST_METAPARSE_STD < 2011
main()39 int main()
40 {
41   std::cout << "Please use a compiler that supports constexpr" << std::endl;
42 }
43 #else
44 
45 #ifdef _STR
46 #  error _STR already defined
47 #endif
48 #define _STR BOOST_METAPARSE_STRING
49 
50 template <class T, char C>
51 struct is_c : bool_<T::type::value == C> {};
52 
53 struct build_plus_impl
54 {
55   template <class A, class B>
56   class _plus
57   {
58   public:
59     typedef _plus type;
60 
61     template <class T>
operator ()(T t) const62     T operator()(T t) const
63     {
64       return _left(t) + _right(t);
65     }
66   private:
67     typename A::type _left;
68     typename B::type _right;
69   };
70 
71   template <class A, class B>
72   class _minus
73   {
74   public:
75     typedef _minus 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 State, class C>
88   struct apply :
89     if_<
90       typename is_c<front<C>, '+'>::type,
91       _plus<State, typename back<C>::type>,
92       _minus<State, typename back<C>::type>
93     >
94   {};
95 };
96 
97 struct build_plus
98 {
99   typedef build_plus type;
100 
101   template <class Seq>
102   struct apply :
103     boost::mpl::fold<
104       typename back<Seq>::type,
105       typename front<Seq>::type,
106       build_plus_impl
107     >
108   {};
109 };
110 
111 struct build_mult_impl
112 {
113   template <class A, class B>
114   class _mult
115   {
116   public:
117     typedef _mult type;
118 
119     template <class T>
operator ()(T t) const120     T operator()(T t) const
121     {
122       return _left(t) * _right(t);
123     }
124   private:
125     typename A::type _left;
126     typename B::type _right;
127   };
128 
129   template <class A, class B>
130   class _div
131   {
132   public:
133     typedef _div type;
134 
135     template <class T>
operator ()(T t) const136     T operator()(T t) const
137     {
138       return _left(t) / _right(t);
139     }
140   private:
141     typename A::type _left;
142     typename B::type _right;
143   };
144 
145   template <class State, class C>
146   struct apply :
147     if_<
148       typename is_c<front<C>, '*'>::type,
149       _mult<State, typename back<C>::type>,
150       _div<State, typename back<C>::type>
151     >
152   {};
153 };
154 
155 struct build_mult
156 {
157   typedef build_mult type;
158 
159   template <class Seq>
160   struct apply :
161     boost::mpl::fold<
162       typename back<Seq>::type,
163       typename front<Seq>::type,
164       build_mult_impl
165     >
166   {};
167 };
168 
169 struct build_value
170 {
171   typedef build_value type;
172 
173   template <class V>
174   struct apply
175   {
176     typedef apply type;
177 
178     template <class T>
operator ()build_value::apply179     int operator()(T) const
180     {
181       return V::type::value;
182     }
183   };
184 };
185 
186 struct build_arg
187 {
188   typedef build_arg type;
189 
190   template <class>
191   struct apply
192   {
193     typedef apply type;
194 
195     template <class T>
operator ()build_arg::apply196     T operator()(T t) const
197     {
198       return t;
199     }
200   };
201 };
202 
203 struct keep_front
204 {
205   typedef keep_front type;
206 
207   template <class Seq>
208   struct apply : front<Seq> {};
209 };
210 
211 typedef
212   grammar<_STR("plus_exp")>
213     ::import<_STR("int_token"), token<transform<int_, build_value>>>::type
214 
215     ::rule<_STR("ws ::= (' ' | '\n' | '\r' | '\t')*")>::type
216     ::rule<_STR("plus_token ::= '+' ws"), keep_front>::type
217     ::rule<_STR("minus_token ::= '-' ws"), keep_front>::type
218     ::rule<_STR("mult_token ::= '*' ws"), keep_front>::type
219     ::rule<_STR("div_token ::= '/' ws"), keep_front>::type
220     ::rule<_STR("arg_token ::= '_' ws"), keep_front>::type
221 
222     ::rule<_STR("plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*"), build_plus>::type
223     ::rule<_STR("prod_exp ::= value_exp ((mult_token | div_token) value_exp)*"), build_mult>::type
224     ::rule<_STR("value_exp ::= int_token | arg_exp")>::type
225     ::rule<_STR("arg_exp ::= arg_token"), build_arg>::type
226   g;
227 
228 typedef build_parser<entire_input<g>> function_parser;
229 
230 #ifdef LAMBDA
231   #error LAMBDA already defined
232 #endif
233 #define LAMBDA(exp) apply_wrap1<function_parser, _STR(#exp)>::type
234 
235 LAMBDA(13) f1;
236 LAMBDA(2 + 3) f2;
237 LAMBDA(2 * 3) f3;
238 LAMBDA(1+ 2*4-6/2) f4;
239 LAMBDA(2 * _) f5;
240 
main()241 int main()
242 {
243   using std::cout;
244   using std::endl;
245 
246   cout
247     << f1(11) << endl
248     << f2(11) << endl
249     << f3(11) << endl
250     << f4(11) << endl
251     << f5(11) << endl
252     << f5(1.1) << endl
253     ;
254 }
255 
256 #endif
257 
258 
259