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