1// Copyright (c) 2001-2011 Hartmut Kaiser
2// Copyright (c) 2001-2011 Joel de Guzman
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_LAZY_MARCH_27_2007_1231PM)
8#define BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM
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/delimit_out.hpp>
16#include <boost/spirit/home/karma/meta_compiler.hpp>
17#include <boost/spirit/home/karma/detail/attributes.hpp>
18#include <boost/spirit/home/support/unused.hpp>
19#include <boost/spirit/home/support/info.hpp>
20#include <boost/spirit/home/support/lazy.hpp>
21#include <boost/fusion/include/at.hpp>
22#include <boost/utility/result_of.hpp>
23#include <boost/proto/make_expr.hpp>
24#include <boost/type_traits/remove_reference.hpp>
25#include <boost/mpl/not.hpp>
26
27namespace boost { namespace phoenix
28{
29 template <typename Expr>
30 struct actor;
31}}
32
33namespace boost { namespace spirit
34{
35 ///////////////////////////////////////////////////////////////////////////
36 // Enablers
37 ///////////////////////////////////////////////////////////////////////////
38 template <typename Eval>
39 struct use_terminal<karma::domain, phoenix::actor<Eval> > // enables phoenix actors
40 : mpl::true_ {};
41
42 // forward declaration
43 template <typename Terminal, typename Actor, int Arity>
44 struct lazy_terminal;
45
46}}
47
48namespace boost { namespace spirit { namespace karma
49{
50 using spirit::lazy;
51 typedef modify<karma::domain> karma_modify;
52
53 namespace detail
54 {
55 template <typename Generator, typename OutputIterator, typename Context
56 , typename Delimiter, typename Attribute>
57 bool lazy_generate_impl(Generator const& g, OutputIterator& sink
58 , Context& context, Delimiter const& delim
59 , Attribute const& attr, mpl::false_)
60 {
61 return g.generate(sink, context, delim, attr);
62 }
63
64 template <typename Generator, typename OutputIterator, typename Context
65 , typename Delimiter, typename Attribute>
66 bool lazy_generate_impl(Generator const& g, OutputIterator& sink
67 , Context& context, Delimiter const& delim
68 , Attribute const& /* attr */, mpl::true_)
69 {
70 // If DeducedAuto is false (semantic actions is present), the
71 // component's attribute is unused.
72 return g.generate(sink, context, delim, unused);
73 }
74
75 template <typename Generator, typename OutputIterator, typename Context
76 , typename Delimiter, typename Attribute>
77 bool lazy_generate_impl_main(Generator const& g, OutputIterator& sink
78 , Context& context, Delimiter const& delim, Attribute const& attr)
79 {
80 // If DeducedAuto is true (no semantic action), we pass the parser's
81 // attribute on to the component.
82 typedef typename traits::has_semantic_action<Generator>::type auto_rule;
83 return lazy_generate_impl(g, sink, context, delim, attr, auto_rule());
84 }
85 }
86
87 template <typename Function, typename Modifiers>
88 struct lazy_generator : generator<lazy_generator<Function, Modifiers> >
89 {
90 typedef mpl::int_<generator_properties::all_properties> properties;
91
92 template <typename Context, typename Iterator>
93 struct attribute
94 {
95 typedef typename
96 boost::result_of<karma_modify(tag::lazy_eval, Modifiers)>::type
97 modifier;
98
99 typedef typename
100 remove_reference<
101 typename boost::result_of<Function(unused_type, Context)>::type
102 >::type
103 expr_type;
104
105 // If you got an error_invalid_expression error message here,
106 // then the expression (expr_type) is not a valid spirit karma
107 // expression.
108 BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type);
109
110 typedef typename
111 result_of::compile<karma::domain, expr_type, modifier>::type
112 generator_type;
113
114 typedef typename
115 traits::attribute_of<generator_type, Context, Iterator>::type
116 type;
117 };
118
119 lazy_generator(Function const& func, Modifiers const& modifiers)
120 : func(func), modifiers(modifiers) {}
121
122 template <
123 typename OutputIterator, typename Context,
124 typename Delimiter, typename Attribute
125 >
126 bool generate(OutputIterator& sink, Context& context,
127 Delimiter const& d, Attribute const& attr) const
128 {
129 return detail::lazy_generate_impl_main(
130 compile<karma::domain>(func(unused, context)
131 , karma_modify()(tag::lazy_eval(), modifiers))
132 , sink, context, d, attr);
133 }
134
135 template <typename Context>
136 info what(Context& context) const
137 {
138 return info("lazy"
139 , compile<karma::domain>(func(unused, context)
140 , karma_modify()(tag::lazy_eval(), modifiers))
141 .what(context)
142 );
143 }
144
145 Function func;
146 Modifiers modifiers;
147 };
148
149 ///////////////////////////////////////////////////////////////////////////
150 template <typename Function, typename Subject, typename Modifiers>
151 struct lazy_directive
152 : unary_generator<lazy_directive<Function, Subject, Modifiers> >
153 {
154 typedef mpl::int_<generator_properties::all_properties> properties;
155
156 typedef Subject subject_type;
157
158 template <typename Context, typename Iterator>
159 struct attribute
160 {
161 typedef typename
162 boost::result_of<karma_modify(tag::lazy_eval, Modifiers)>::type
163 modifier;
164
165 typedef typename
166 remove_reference<
167 typename boost::result_of<Function(unused_type, Context)>::type
168 >::type
169 directive_expr_type;
170
171 typedef typename
172 proto::result_of::make_expr<
173 proto::tag::subscript
174 , directive_expr_type
175 , Subject
176 >::type
177 expr_type;
178
179 // If you got an error_invalid_expression error message here,
180 // then the expression (expr_type) is not a valid spirit karma
181 // expression.
182 BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type);
183
184 typedef typename
185 result_of::compile<karma::domain, expr_type, modifier>::type
186 generator_type;
187
188 typedef typename
189 traits::attribute_of<generator_type, Context, Iterator>::type
190 type;
191 };
192
193 lazy_directive(Function const& function, Subject const& subject
194 , Modifiers const& modifiers)
195 : function(function), subject(subject), modifiers(modifiers) {}
196
197 template <typename OutputIterator, typename Context, typename Delimiter
198 , typename Attribute>
199 bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
200 , Attribute const& attr) const
201 {
202 return detail::lazy_generate_impl_main(compile<karma::domain>(
203 proto::make_expr<proto::tag::subscript>(
204 function(unused, ctx), subject)
205 , karma_modify()(tag::lazy_eval(), modifiers))
206 , sink, ctx, d, attr);
207 }
208
209 template <typename Context>
210 info what(Context& ctx) const
211 {
212 return info("lazy-directive"
213 , compile<karma::domain>(
214 proto::make_expr<proto::tag::subscript>(
215 function(unused, ctx), subject)
216 , karma_modify()(tag::lazy_eval(), modifiers))
217 .what(ctx)
218 );
219 }
220
221 Function function;
222 Subject subject;
223 Modifiers modifiers;
224 };
225
226 ///////////////////////////////////////////////////////////////////////////
227 // Generator generators: make_xxx function (objects)
228 ///////////////////////////////////////////////////////////////////////////
229 template <typename Eval, typename Modifiers>
230 struct make_primitive<phoenix::actor<Eval>, Modifiers>
231 {
232 typedef lazy_generator<phoenix::actor<Eval>, Modifiers> result_type;
233 result_type operator()(phoenix::actor<Eval> const& f
234 , Modifiers const& modifiers) const
235 {
236 return result_type(f, modifiers);
237 }
238 };
239
240 template <typename Terminal, typename Actor, int Arity, typename Modifiers>
241 struct make_primitive<lazy_terminal<Terminal, Actor, Arity>, Modifiers>
242 {
243 typedef lazy_generator<Actor, Modifiers> result_type;
244 result_type operator()(
245 lazy_terminal<Terminal, Actor, Arity> const& lt
246 , Modifiers const& modifiers) const
247 {
248 return result_type(lt.actor, modifiers);
249 }
250 };
251
252 template <
253 typename Terminal, typename Actor, int Arity, typename Subject
254 , typename Modifiers>
255 struct make_directive<lazy_terminal<Terminal, Actor, Arity>
256 , Subject, Modifiers>
257 {
258 typedef lazy_directive<Actor, Subject, Modifiers> result_type;
259 result_type operator()(
260 lazy_terminal<Terminal, Actor, Arity> const& lt
261 , Subject const& subject, Modifiers const& modifiers) const
262 {
263 return result_type(lt.actor, subject, modifiers);
264 }
265 };
266
267}}}
268
269#endif
270

source code of boost/libs/spirit/include/boost/spirit/home/karma/auxiliary/lazy.hpp