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_KLEENE_MAR_03_2007_0337AM)
8#define BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM
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/output_iterator.hpp>
18#include <boost/spirit/home/karma/detail/indirect_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/handles_container.hpp>
26#include <boost/spirit/home/karma/detail/attributes.hpp>
27#include <boost/proto/operators.hpp>
28#include <boost/proto/tags.hpp>
29#include <boost/type_traits/add_const.hpp>
30
31namespace boost { namespace spirit
32{
33 ///////////////////////////////////////////////////////////////////////////
34 // Enablers
35 ///////////////////////////////////////////////////////////////////////////
36 template <>
37 struct use_operator<karma::domain, proto::tag::dereference> // enables *g
38 : mpl::true_ {};
39}}
40
41///////////////////////////////////////////////////////////////////////////////
42namespace boost { namespace spirit { namespace karma
43{
44 template <typename Subject, typename Strict, typename Derived>
45 struct base_kleene : 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&, mpl::false_) const
53 {
54 bool r = !f(subject);
55 if (!r && !f.is_at_end())
56 f.next();
57 return true;
58 }
59
60 template <typename F, typename Attribute>
61 bool generate_subject(F f, Attribute const&, mpl::true_) const
62 {
63 return !f(subject);
64 }
65
66 // There is no way to distinguish a failed generator from a
67 // generator to be skipped. We assume the user takes responsibility
68 // for ending the loop if no attribute is specified.
69 template <typename F>
70 bool generate_subject(F f, unused_type, mpl::false_) const
71 {
72 return !f(subject);
73 }
74
75// template <typename F>
76// bool generate_subject(F f, unused_type, mpl::true_) const
77// {
78// return !f(subject);
79// }
80
81 public:
82 typedef Subject subject_type;
83 typedef typename subject_type::properties properties;
84
85 // Build a std::vector from the subject's attribute. Note
86 // that build_std_vector may return unused_type if the
87 // subject's attribute is an unused_type.
88 template <typename Context, typename Iterator>
89 struct attribute
90 : traits::build_std_vector<
91 typename traits::attribute_of<Subject, Context, Iterator>::type
92 >
93 {};
94
95 base_kleene(Subject const& subject)
96 : subject(subject) {}
97
98 template <
99 typename OutputIterator, typename Context, typename Delimiter
100 , typename Attribute>
101 bool generate(OutputIterator& sink, Context& ctx
102 , Delimiter const& d, Attribute const& attr) const
103 {
104 typedef detail::fail_function<
105 OutputIterator, Context, Delimiter> fail_function;
106
107 typedef typename traits::container_iterator<
108 typename add_const<Attribute>::type
109 >::type iterator_type;
110
111 typedef
112 typename traits::make_indirect_iterator<iterator_type>::type
113 indirect_iterator_type;
114 typedef detail::pass_container<
115 fail_function, Attribute, indirect_iterator_type, mpl::false_>
116 pass_container;
117
118 iterator_type it = traits::begin(attr);
119 iterator_type end = traits::end(attr);
120
121 pass_container pass(fail_function(sink, ctx, d),
122 indirect_iterator_type(it), indirect_iterator_type(end));
123
124 // kleene fails only if the underlying output fails
125 while (!pass.is_at_end())
126 {
127 if (!generate_subject(pass, attr, Strict()))
128 break;
129 }
130 return detail::sink_is_good(sink);
131 }
132
133 template <typename Context>
134 info what(Context& context) const
135 {
136 return info("kleene", subject.what(context));
137 }
138
139 Subject subject;
140 };
141
142 template <typename Subject>
143 struct kleene
144 : base_kleene<Subject, mpl::false_, kleene<Subject> >
145 {
146 typedef base_kleene<Subject, mpl::false_, kleene> base_kleene_;
147
148 kleene(Subject const& subject)
149 : base_kleene_(subject) {}
150 };
151
152 template <typename Subject>
153 struct strict_kleene
154 : base_kleene<Subject, mpl::true_, strict_kleene<Subject> >
155 {
156 typedef base_kleene<Subject, mpl::true_, strict_kleene> base_kleene_;
157
158 strict_kleene(Subject const& subject)
159 : base_kleene_(subject) {}
160 };
161
162 ///////////////////////////////////////////////////////////////////////////
163 // Generator generators: make_xxx function (objects)
164 ///////////////////////////////////////////////////////////////////////////
165 namespace detail
166 {
167 template <typename Subject, bool strict_mode = false>
168 struct make_kleene
169 : make_unary_composite<Subject, kleene>
170 {};
171
172 template <typename Subject>
173 struct make_kleene<Subject, true>
174 : make_unary_composite<Subject, strict_kleene>
175 {};
176 }
177
178 template <typename Subject, typename Modifiers>
179 struct make_composite<proto::tag::dereference, Subject, Modifiers>
180 : detail::make_kleene<Subject, detail::get_stricttag<Modifiers>::value>
181 {};
182}}}
183
184namespace boost { namespace spirit { namespace traits
185{
186 ///////////////////////////////////////////////////////////////////////////
187 template <typename Subject>
188 struct has_semantic_action<karma::kleene<Subject> >
189 : unary_has_semantic_action<Subject> {};
190
191 template <typename Subject>
192 struct has_semantic_action<karma::strict_kleene<Subject> >
193 : unary_has_semantic_action<Subject> {};
194
195 ///////////////////////////////////////////////////////////////////////////
196 template <typename Subject, typename Attribute, typename Context
197 , typename Iterator>
198 struct handles_container<karma::kleene<Subject>, Attribute
199 , Context, Iterator>
200 : mpl::true_ {};
201
202 template <typename Subject, typename Attribute, typename Context
203 , typename Iterator>
204 struct handles_container<karma::strict_kleene<Subject>, Attribute
205 , Context, Iterator>
206 : mpl::true_ {};
207}}}
208
209#endif
210

source code of boost/libs/spirit/include/boost/spirit/home/karma/operator/kleene.hpp