Chris@16
|
1 // Copyright (c) 2001-2011 Joel de Guzman
|
Chris@16
|
2 // Copyright (c) 2001-2011 Hartmut Kaiser
|
Chris@16
|
3 //
|
Chris@16
|
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 #if !defined(BOOST_SPIRIT_KARMA_POSITIVE_MAR_03_2007_0945PM)
|
Chris@16
|
8 #define BOOST_SPIRIT_KARMA_POSITIVE_MAR_03_2007_0945PM
|
Chris@16
|
9
|
Chris@16
|
10 #if defined(_MSC_VER)
|
Chris@16
|
11 #pragma once
|
Chris@16
|
12 #endif
|
Chris@16
|
13
|
Chris@16
|
14 #include <boost/spirit/home/karma/domain.hpp>
|
Chris@16
|
15 #include <boost/spirit/home/karma/generator.hpp>
|
Chris@16
|
16 #include <boost/spirit/home/karma/meta_compiler.hpp>
|
Chris@16
|
17 #include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
|
Chris@16
|
18 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
|
Chris@16
|
19 #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
|
Chris@16
|
20 #include <boost/spirit/home/karma/detail/pass_container.hpp>
|
Chris@16
|
21 #include <boost/spirit/home/karma/detail/fail_function.hpp>
|
Chris@16
|
22 #include <boost/spirit/home/support/info.hpp>
|
Chris@16
|
23 #include <boost/spirit/home/support/unused.hpp>
|
Chris@16
|
24 #include <boost/spirit/home/support/container.hpp>
|
Chris@16
|
25 #include <boost/spirit/home/support/has_semantic_action.hpp>
|
Chris@16
|
26 #include <boost/spirit/home/support/handles_container.hpp>
|
Chris@16
|
27 #include <boost/spirit/home/karma/detail/attributes.hpp>
|
Chris@16
|
28
|
Chris@16
|
29 #include <boost/type_traits/add_const.hpp>
|
Chris@16
|
30
|
Chris@16
|
31 namespace boost { namespace spirit
|
Chris@16
|
32 {
|
Chris@16
|
33 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
34 // Enablers
|
Chris@16
|
35 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
36 template <>
|
Chris@16
|
37 struct use_operator<karma::domain, proto::tag::unary_plus> // enables +g
|
Chris@16
|
38 : mpl::true_ {};
|
Chris@16
|
39 }}
|
Chris@16
|
40
|
Chris@16
|
41 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
42 namespace boost { namespace spirit { namespace karma
|
Chris@16
|
43 {
|
Chris@16
|
44 template <typename Subject, typename Strict, typename Derived>
|
Chris@16
|
45 struct base_plus : unary_generator<Derived>
|
Chris@16
|
46 {
|
Chris@16
|
47 private:
|
Chris@16
|
48 // Ignore return value in relaxed mode (failing subject generators
|
Chris@16
|
49 // are just skipped). This allows to selectively generate items in
|
Chris@16
|
50 // the provided attribute.
|
Chris@16
|
51 template <typename F, typename Attribute>
|
Chris@16
|
52 bool generate_subject(F f, Attribute const&, bool& result, mpl::false_) const
|
Chris@16
|
53 {
|
Chris@16
|
54 bool r = !f(subject);
|
Chris@16
|
55 if (r)
|
Chris@16
|
56 result = true;
|
Chris@16
|
57 else if (!f.is_at_end())
|
Chris@16
|
58 f.next();
|
Chris@16
|
59 return true;
|
Chris@16
|
60 }
|
Chris@16
|
61
|
Chris@16
|
62 template <typename F, typename Attribute>
|
Chris@16
|
63 bool generate_subject(F f, Attribute const&, bool& result, mpl::true_) const
|
Chris@16
|
64 {
|
Chris@16
|
65 bool r = !f(subject);
|
Chris@16
|
66 if (r)
|
Chris@16
|
67 result = true;
|
Chris@16
|
68 return r;
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 // There is no way to distinguish a failed generator from a
|
Chris@16
|
72 // generator to be skipped. We assume the user takes responsibility
|
Chris@16
|
73 // for ending the loop if no attribute is specified.
|
Chris@16
|
74 template <typename F>
|
Chris@16
|
75 bool generate_subject(F f, unused_type, bool& result, mpl::false_) const
|
Chris@16
|
76 {
|
Chris@16
|
77 bool r = f(subject);
|
Chris@16
|
78 if (!r)
|
Chris@16
|
79 result = true;
|
Chris@16
|
80 return !r;
|
Chris@16
|
81 }
|
Chris@16
|
82
|
Chris@16
|
83 // template <typename F>
|
Chris@16
|
84 // bool generate_subject(F f, unused_type, bool& result, mpl::true_) const
|
Chris@16
|
85 // {
|
Chris@16
|
86 // bool r = f(subject);
|
Chris@16
|
87 // if (!r)
|
Chris@16
|
88 // result = true;
|
Chris@16
|
89 // return !r;
|
Chris@16
|
90 // }
|
Chris@16
|
91
|
Chris@16
|
92 public:
|
Chris@16
|
93 typedef Subject subject_type;
|
Chris@16
|
94 typedef typename subject_type::properties properties;
|
Chris@16
|
95
|
Chris@16
|
96 // Build a std::vector from the subjects attribute. Note
|
Chris@16
|
97 // that build_std_vector may return unused_type if the
|
Chris@16
|
98 // subject's attribute is an unused_type.
|
Chris@16
|
99 template <typename Context, typename Iterator>
|
Chris@16
|
100 struct attribute
|
Chris@16
|
101 : traits::build_std_vector<
|
Chris@16
|
102 typename traits::attribute_of<subject_type, Context, Iterator>::type
|
Chris@16
|
103 >
|
Chris@16
|
104 {};
|
Chris@16
|
105
|
Chris@16
|
106 base_plus(Subject const& subject)
|
Chris@16
|
107 : subject(subject) {}
|
Chris@16
|
108
|
Chris@16
|
109 template <
|
Chris@16
|
110 typename OutputIterator, typename Context, typename Delimiter
|
Chris@16
|
111 , typename Attribute>
|
Chris@16
|
112 bool generate(OutputIterator& sink, Context& ctx
|
Chris@16
|
113 , Delimiter const& d, Attribute const& attr) const
|
Chris@16
|
114 {
|
Chris@16
|
115 typedef detail::fail_function<
|
Chris@16
|
116 OutputIterator, Context, Delimiter> fail_function;
|
Chris@16
|
117
|
Chris@16
|
118 typedef typename traits::container_iterator<
|
Chris@16
|
119 typename add_const<Attribute>::type
|
Chris@16
|
120 >::type iterator_type;
|
Chris@16
|
121
|
Chris@16
|
122 typedef
|
Chris@16
|
123 typename traits::make_indirect_iterator<iterator_type>::type
|
Chris@16
|
124 indirect_iterator_type;
|
Chris@16
|
125 typedef detail::pass_container<
|
Chris@16
|
126 fail_function, Attribute, indirect_iterator_type, mpl::false_>
|
Chris@16
|
127 pass_container;
|
Chris@16
|
128
|
Chris@16
|
129 iterator_type it = traits::begin(attr);
|
Chris@16
|
130 iterator_type end = traits::end(attr);
|
Chris@16
|
131
|
Chris@16
|
132 // plus fails if the parameter is empty
|
Chris@16
|
133 if (traits::compare(it, end))
|
Chris@16
|
134 return false;
|
Chris@16
|
135
|
Chris@16
|
136 pass_container pass(fail_function(sink, ctx, d),
|
Chris@16
|
137 indirect_iterator_type(it), indirect_iterator_type(end));
|
Chris@16
|
138
|
Chris@16
|
139 // from now on plus fails if the underlying output fails or overall
|
Chris@16
|
140 // no subject generators succeeded
|
Chris@16
|
141 bool result = false;
|
Chris@16
|
142 while (!pass.is_at_end())
|
Chris@16
|
143 {
|
Chris@16
|
144 if (!generate_subject(pass, attr, result, Strict()))
|
Chris@16
|
145 break;
|
Chris@16
|
146 }
|
Chris@16
|
147 return result && detail::sink_is_good(sink);
|
Chris@16
|
148 }
|
Chris@16
|
149
|
Chris@16
|
150 template <typename Context>
|
Chris@16
|
151 info what(Context& context) const
|
Chris@16
|
152 {
|
Chris@16
|
153 return info("plus", subject.what(context));
|
Chris@16
|
154 }
|
Chris@16
|
155
|
Chris@16
|
156 Subject subject;
|
Chris@16
|
157 };
|
Chris@16
|
158
|
Chris@16
|
159 template <typename Subject>
|
Chris@16
|
160 struct plus
|
Chris@16
|
161 : base_plus<Subject, mpl::false_, plus<Subject> >
|
Chris@16
|
162 {
|
Chris@16
|
163 typedef base_plus<Subject, mpl::false_, plus> base_plus_;
|
Chris@16
|
164
|
Chris@16
|
165 plus(Subject const& subject)
|
Chris@16
|
166 : base_plus_(subject) {}
|
Chris@16
|
167 };
|
Chris@16
|
168
|
Chris@16
|
169 template <typename Subject>
|
Chris@16
|
170 struct strict_plus
|
Chris@16
|
171 : base_plus<Subject, mpl::true_, strict_plus<Subject> >
|
Chris@16
|
172 {
|
Chris@16
|
173 typedef base_plus<Subject, mpl::true_, strict_plus> base_plus_;
|
Chris@16
|
174
|
Chris@16
|
175 strict_plus(Subject const& subject)
|
Chris@16
|
176 : base_plus_(subject) {}
|
Chris@16
|
177 };
|
Chris@16
|
178
|
Chris@16
|
179 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
180 // Generator generators: make_xxx function (objects)
|
Chris@16
|
181 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
182 namespace detail
|
Chris@16
|
183 {
|
Chris@16
|
184 template <typename Elements, bool strict_mode = false>
|
Chris@16
|
185 struct make_plus
|
Chris@16
|
186 : make_unary_composite<Elements, plus>
|
Chris@16
|
187 {};
|
Chris@16
|
188
|
Chris@16
|
189 template <typename Elements>
|
Chris@16
|
190 struct make_plus<Elements, true>
|
Chris@16
|
191 : make_unary_composite<Elements, strict_plus>
|
Chris@16
|
192 {};
|
Chris@16
|
193 }
|
Chris@16
|
194
|
Chris@16
|
195 template <typename Elements, typename Modifiers>
|
Chris@16
|
196 struct make_composite<proto::tag::unary_plus, Elements, Modifiers>
|
Chris@16
|
197 : detail::make_plus<Elements, detail::get_stricttag<Modifiers>::value>
|
Chris@16
|
198 {};
|
Chris@16
|
199 }}}
|
Chris@16
|
200
|
Chris@16
|
201 namespace boost { namespace spirit { namespace traits
|
Chris@16
|
202 {
|
Chris@16
|
203 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
204 template <typename Subject>
|
Chris@16
|
205 struct has_semantic_action<karma::plus<Subject> >
|
Chris@16
|
206 : unary_has_semantic_action<Subject> {};
|
Chris@16
|
207
|
Chris@16
|
208 template <typename Subject>
|
Chris@16
|
209 struct has_semantic_action<karma::strict_plus<Subject> >
|
Chris@16
|
210 : unary_has_semantic_action<Subject> {};
|
Chris@16
|
211
|
Chris@16
|
212 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
213 template <typename Subject, typename Attribute, typename Context
|
Chris@16
|
214 , typename Iterator>
|
Chris@16
|
215 struct handles_container<karma::plus<Subject>, Attribute
|
Chris@16
|
216 , Context, Iterator>
|
Chris@16
|
217 : mpl::true_ {};
|
Chris@16
|
218
|
Chris@16
|
219 template <typename Subject, typename Attribute, typename Context
|
Chris@16
|
220 , typename Iterator>
|
Chris@16
|
221 struct handles_container<karma::strict_plus<Subject>, Attribute
|
Chris@16
|
222 , Context, Iterator>
|
Chris@16
|
223 : mpl::true_ {};
|
Chris@16
|
224 }}}
|
Chris@16
|
225
|
Chris@16
|
226 #endif
|