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