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