]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | Copyright (c) 2011 Bryce Lelbach | |
4 | ||
5 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
6 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ==============================================================================*/ | |
8 | #if !defined(BOOST_SPIRIT_REAL_APRIL_18_2006_0850AM) | |
9 | #define BOOST_SPIRIT_REAL_APRIL_18_2006_0850AM | |
10 | ||
11 | #if defined(_MSC_VER) | |
12 | #pragma once | |
13 | #endif | |
14 | ||
15 | #include <boost/spirit/home/qi/skip_over.hpp> | |
16 | #include <boost/spirit/home/qi/detail/enable_lit.hpp> | |
17 | #include <boost/spirit/home/qi/meta_compiler.hpp> | |
18 | #include <boost/spirit/home/qi/parser.hpp> | |
19 | #include <boost/spirit/home/qi/numeric/real_policies.hpp> | |
20 | #include <boost/spirit/home/qi/numeric/numeric_utils.hpp> | |
21 | #include <boost/spirit/home/qi/numeric/detail/real_impl.hpp> | |
22 | #include <boost/spirit/home/support/common_terminals.hpp> | |
23 | #include <boost/type_traits/is_same.hpp> | |
24 | ||
25 | namespace boost { namespace spirit | |
26 | { | |
27 | namespace qi | |
28 | { | |
29 | /////////////////////////////////////////////////////////////////////// | |
30 | // forward declaration only | |
31 | template <typename T> | |
32 | struct real_policies; | |
33 | ||
34 | /////////////////////////////////////////////////////////////////////// | |
35 | // This is the class that the user can instantiate directly in | |
36 | // order to create a customized real parser | |
37 | template <typename T = double, typename Policies = real_policies<T> > | |
38 | struct real_parser | |
39 | : spirit::terminal<tag::stateful_tag<Policies, tag::double_, T> > | |
40 | { | |
41 | typedef tag::stateful_tag<Policies, tag::double_, T> tag_type; | |
42 | ||
43 | real_parser() {} | |
44 | real_parser(Policies const& p) | |
45 | : spirit::terminal<tag_type>(p) {} | |
46 | }; | |
47 | } | |
48 | ||
49 | /////////////////////////////////////////////////////////////////////////// | |
50 | // Enablers | |
51 | /////////////////////////////////////////////////////////////////////////// | |
52 | template <> // enables float_ | |
53 | struct use_terminal<qi::domain, tag::float_> | |
54 | : mpl::true_ {}; | |
55 | ||
56 | template <> // enables double_ | |
57 | struct use_terminal<qi::domain, tag::double_> | |
58 | : mpl::true_ {}; | |
59 | ||
60 | template <> // enables long_double | |
61 | struct use_terminal<qi::domain, tag::long_double> | |
62 | : mpl::true_ {}; | |
63 | ||
64 | /////////////////////////////////////////////////////////////////////////// | |
65 | template <typename A0> // enables lit(n) | |
66 | struct use_terminal<qi::domain | |
67 | , terminal_ex<tag::lit, fusion::vector1<A0> > | |
68 | , typename enable_if<is_same<A0, float> >::type> | |
69 | : mpl::true_ {}; | |
70 | ||
71 | template <typename A0> // enables lit(n) | |
72 | struct use_terminal<qi::domain | |
73 | , terminal_ex<tag::lit, fusion::vector1<A0> > | |
74 | , typename enable_if<is_same<A0, double> >::type> | |
75 | : mpl::true_ {}; | |
76 | ||
77 | template <typename A0> // enables lit(n) | |
78 | struct use_terminal<qi::domain | |
79 | , terminal_ex<tag::lit, fusion::vector1<A0> > | |
80 | , typename enable_if<is_same<A0, long double> >::type> | |
81 | : mpl::true_ {}; | |
82 | ||
83 | /////////////////////////////////////////////////////////////////////////// | |
84 | template <typename A0> // enables float_(...) | |
85 | struct use_terminal<qi::domain | |
86 | , terminal_ex<tag::float_, fusion::vector1<A0> > | |
87 | > : mpl::true_ {}; | |
88 | ||
89 | template <typename A0> // enables double_(...) | |
90 | struct use_terminal<qi::domain | |
91 | , terminal_ex<tag::double_, fusion::vector1<A0> > | |
92 | > : mpl::true_ {}; | |
93 | ||
94 | template <typename A0> // enables long_double(...) | |
95 | struct use_terminal<qi::domain | |
96 | , terminal_ex<tag::long_double, fusion::vector1<A0> > | |
97 | > : mpl::true_ {}; | |
98 | ||
99 | template <> // enables *lazy* float_(...) | |
100 | struct use_lazy_terminal<qi::domain, tag::float_, 1> | |
101 | : mpl::true_ {}; | |
102 | ||
103 | template <> // enables *lazy* double_(...) | |
104 | struct use_lazy_terminal<qi::domain, tag::double_, 1> | |
105 | : mpl::true_ {}; | |
106 | ||
107 | template <> // enables *lazy* long_double_(...) | |
108 | struct use_lazy_terminal<qi::domain, tag::long_double, 1> | |
109 | : mpl::true_ {}; | |
110 | ||
111 | /////////////////////////////////////////////////////////////////////////// | |
112 | // enables custom real_parser | |
113 | template <typename T, typename Policies> | |
114 | struct use_terminal<qi::domain | |
115 | , tag::stateful_tag<Policies, tag::double_, T> > | |
116 | : mpl::true_ {}; | |
117 | ||
118 | // enables custom real_parser(...) | |
119 | template <typename T, typename Policies, typename A0> | |
120 | struct use_terminal<qi::domain | |
121 | , terminal_ex<tag::stateful_tag<Policies, tag::double_, T> | |
122 | , fusion::vector1<A0> > > | |
123 | : mpl::true_ {}; | |
124 | ||
125 | // enables *lazy* custom real_parser(...) | |
126 | template <typename T, typename Policies> | |
127 | struct use_lazy_terminal< | |
128 | qi::domain | |
129 | , tag::stateful_tag<Policies, tag::double_, T> | |
130 | , 1 // arity | |
131 | > : mpl::true_ {}; | |
132 | }} | |
133 | ||
134 | namespace boost { namespace spirit { namespace qi | |
135 | { | |
136 | #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
137 | using spirit::float_; | |
138 | using spirit::double_; | |
139 | using spirit::long_double; | |
140 | using spirit::lit; // lit(1.0) is equivalent to 1.0 | |
141 | #endif | |
142 | ||
143 | using spirit::float_type; | |
144 | using spirit::double_type; | |
145 | using spirit::long_double_type; | |
146 | using spirit::lit_type; | |
147 | ||
148 | /////////////////////////////////////////////////////////////////////////// | |
149 | // This is the actual real number parser | |
150 | /////////////////////////////////////////////////////////////////////////// | |
151 | template <typename T, typename RealPolicies = real_policies<T> > | |
152 | struct any_real_parser | |
153 | : primitive_parser<any_real_parser<T, RealPolicies> > | |
154 | { | |
155 | template <typename Context, typename Iterator> | |
156 | struct attribute | |
157 | { | |
158 | typedef T type; | |
159 | }; | |
160 | ||
161 | template <typename Iterator, typename Context, typename Skipper> | |
162 | bool parse(Iterator& first, Iterator const& last | |
163 | , Context& /*context*/, Skipper const& skipper | |
164 | , T& attr_) const | |
165 | { | |
166 | typedef detail::real_impl<T, RealPolicies> extract; | |
167 | qi::skip_over(first, last, skipper); | |
168 | return extract::parse(first, last, attr_, RealPolicies()); | |
169 | } | |
170 | ||
171 | template <typename Iterator, typename Context | |
172 | , typename Skipper, typename Attribute> | |
173 | bool parse(Iterator& first, Iterator const& last | |
174 | , Context& context, Skipper const& skipper | |
175 | , Attribute& attr_param) const | |
176 | { | |
177 | // this case is called when Attribute is not T | |
178 | T attr_; | |
179 | if (parse(first, last, context, skipper, attr_)) | |
180 | { | |
181 | traits::assign_to(attr_, attr_param); | |
182 | return true; | |
183 | } | |
184 | return false; | |
185 | } | |
186 | ||
187 | template <typename Context> | |
188 | info what(Context& /*context*/) const | |
189 | { | |
190 | return info("real"); | |
191 | } | |
192 | }; | |
193 | ||
194 | template <typename T, typename RealPolicies = real_policies<T> | |
195 | , bool no_attribute = true> | |
196 | struct literal_real_parser | |
197 | : primitive_parser<literal_real_parser<T, RealPolicies, no_attribute> > | |
198 | { | |
199 | template <typename Value> | |
200 | literal_real_parser(Value const& n) : n_(n) {} | |
201 | ||
202 | template <typename Context, typename Iterator> | |
203 | struct attribute | |
204 | : mpl::if_c<no_attribute, unused_type, T> | |
205 | {}; | |
206 | ||
207 | template <typename Iterator, typename Context | |
208 | , typename Skipper, typename Attribute> | |
209 | bool parse(Iterator& first, Iterator const& last | |
210 | , Context&, Skipper const& skipper | |
211 | , Attribute& attr_param) const | |
212 | { | |
213 | typedef detail::real_impl<T, RealPolicies> extract; | |
214 | qi::skip_over(first, last, skipper); | |
215 | ||
216 | Iterator save = first; | |
217 | T attr_; | |
218 | ||
219 | if (extract::parse(first, last, attr_, RealPolicies()) && | |
220 | (attr_ == n_)) | |
221 | { | |
222 | traits::assign_to(attr_, attr_param); | |
223 | return true; | |
224 | } | |
225 | ||
226 | first = save; | |
227 | return false; | |
228 | } | |
229 | ||
230 | template <typename Context> | |
231 | info what(Context& /*context*/) const | |
232 | { | |
233 | return info("real"); | |
234 | } | |
235 | ||
236 | T n_; | |
237 | }; | |
238 | ||
239 | /////////////////////////////////////////////////////////////////////////// | |
240 | // Parser generators: make_xxx function (objects) | |
241 | /////////////////////////////////////////////////////////////////////////// | |
242 | template <typename T, typename Policies = real_policies<T> > | |
243 | struct make_real | |
244 | { | |
245 | typedef any_real_parser<T, Policies> result_type; | |
246 | ||
247 | result_type operator()(unused_type, unused_type) const | |
248 | { | |
249 | return result_type(); | |
250 | } | |
251 | }; | |
252 | ||
253 | template <typename T, typename Policies = real_policies<T> > | |
254 | struct make_direct_real | |
255 | { | |
256 | typedef literal_real_parser<T, Policies, false> result_type; | |
257 | ||
258 | template <typename Terminal> | |
259 | result_type operator()(Terminal const& term, unused_type) const | |
260 | { | |
261 | return result_type(T(fusion::at_c<0>(term.args))); | |
262 | } | |
263 | }; | |
264 | ||
265 | template <typename T, typename Policies = real_policies<T> > | |
266 | struct make_literal_real | |
267 | { | |
268 | typedef literal_real_parser<T, Policies> result_type; | |
269 | ||
270 | template <typename Terminal> | |
271 | result_type operator()(Terminal const& term, unused_type) const | |
272 | { | |
273 | return result_type(fusion::at_c<0>(term.args)); | |
274 | } | |
275 | }; | |
276 | ||
277 | /////////////////////////////////////////////////////////////////////////// | |
278 | template <typename Modifiers, typename A0> | |
279 | struct make_primitive< | |
280 | terminal_ex<tag::lit, fusion::vector1<A0> > | |
281 | , Modifiers, typename enable_if<is_same<A0, float> >::type> | |
282 | : make_literal_real<float> {}; | |
283 | ||
284 | template <typename Modifiers, typename A0> | |
285 | struct make_primitive< | |
286 | terminal_ex<tag::lit, fusion::vector1<A0> > | |
287 | , Modifiers, typename enable_if<is_same<A0, double> >::type> | |
288 | : make_literal_real<double> {}; | |
289 | ||
290 | template <typename Modifiers, typename A0> | |
291 | struct make_primitive< | |
292 | terminal_ex<tag::lit, fusion::vector1<A0> > | |
293 | , Modifiers, typename enable_if<is_same<A0, long double> >::type> | |
294 | : make_literal_real<long double> {}; | |
295 | ||
296 | /////////////////////////////////////////////////////////////////////////// | |
297 | template <typename T, typename Policies, typename Modifiers> | |
298 | struct make_primitive< | |
299 | tag::stateful_tag<Policies, tag::double_, T>, Modifiers> | |
300 | : make_real<T, Policies> {}; | |
301 | ||
302 | template <typename T, typename Policies, typename A0, typename Modifiers> | |
303 | struct make_primitive< | |
304 | terminal_ex<tag::stateful_tag<Policies, tag::double_, T> | |
305 | , fusion::vector1<A0> >, Modifiers> | |
306 | : make_direct_real<T, Policies> {}; | |
307 | ||
308 | /////////////////////////////////////////////////////////////////////////// | |
309 | template <typename Modifiers> | |
310 | struct make_primitive<tag::float_, Modifiers> | |
311 | : make_real<float> {}; | |
312 | ||
313 | template <typename Modifiers, typename A0> | |
314 | struct make_primitive< | |
315 | terminal_ex<tag::float_ | |
316 | , fusion::vector1<A0> >, Modifiers> | |
317 | : make_direct_real<float> {}; | |
318 | ||
319 | /////////////////////////////////////////////////////////////////////////// | |
320 | template <typename Modifiers> | |
321 | struct make_primitive<tag::double_, Modifiers> | |
322 | : make_real<double> {}; | |
323 | ||
324 | template <typename Modifiers, typename A0> | |
325 | struct make_primitive< | |
326 | terminal_ex<tag::double_ | |
327 | , fusion::vector1<A0> >, Modifiers> | |
328 | : make_direct_real<double> {}; | |
329 | ||
330 | /////////////////////////////////////////////////////////////////////////// | |
331 | template <typename Modifiers> | |
332 | struct make_primitive<tag::long_double, Modifiers> | |
333 | : make_real<long double> {}; | |
334 | ||
335 | template <typename Modifiers, typename A0> | |
336 | struct make_primitive< | |
337 | terminal_ex<tag::long_double | |
338 | , fusion::vector1<A0> >, Modifiers> | |
339 | : make_direct_real<long double> {}; | |
340 | }}} | |
341 | ||
342 | #endif |