1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 // Copyright (c) 2001-2011 Joel de Guzman
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)
7 #if !defined(BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM)
8 #define BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM
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/spirit/include/phoenix_core.hpp>
22 #include <boost/fusion/include/at.hpp>
23 #include <boost/utility/result_of.hpp>
24 #include <boost/type_traits/remove_reference.hpp>
25 #include <boost/mpl/not.hpp>
27 namespace boost
{ namespace spirit
29 ///////////////////////////////////////////////////////////////////////////
31 ///////////////////////////////////////////////////////////////////////////
32 template <typename Eval
>
33 struct use_terminal
<karma::domain
, phoenix::actor
<Eval
> > // enables phoenix actors
36 // forward declaration
37 template <typename Terminal
, typename Actor
, int Arity
>
42 namespace boost
{ namespace spirit
{ namespace karma
45 typedef modify
<karma::domain
> karma_modify
;
49 template <typename Generator
, typename OutputIterator
, typename Context
50 , typename Delimiter
, typename Attribute
>
51 bool lazy_generate_impl(Generator
const& g
, OutputIterator
& sink
52 , Context
& context
, Delimiter
const& delim
53 , Attribute
const& attr
, mpl::false_
)
55 return g
.generate(sink
, context
, delim
, attr
);
58 template <typename Generator
, typename OutputIterator
, typename Context
59 , typename Delimiter
, typename Attribute
>
60 bool lazy_generate_impl(Generator
const& g
, OutputIterator
& sink
61 , Context
& context
, Delimiter
const& delim
62 , Attribute
const& attr
, mpl::true_
)
64 // If DeducedAuto is false (semantic actions is present), the
65 // component's attribute is unused.
66 return g
.generate(sink
, context
, delim
, unused
);
69 template <typename Generator
, typename OutputIterator
, typename Context
70 , typename Delimiter
, typename Attribute
>
71 bool lazy_generate_impl_main(Generator
const& g
, OutputIterator
& sink
72 , Context
& context
, Delimiter
const& delim
, Attribute
const& attr
)
74 // If DeducedAuto is true (no semantic action), we pass the parser's
75 // attribute on to the component.
76 typedef typename
traits::has_semantic_action
<Generator
>::type auto_rule
;
77 return lazy_generate_impl(g
, sink
, context
, delim
, attr
, auto_rule());
81 template <typename Function
, typename Modifiers
>
82 struct lazy_generator
: generator
<lazy_generator
<Function
, Modifiers
> >
84 typedef mpl::int_
<generator_properties::all_properties
> properties
;
86 template <typename Context
, typename Iterator
>
90 boost::result_of
<karma_modify(tag::lazy_eval
, Modifiers
)>::type
95 typename
boost::result_of
<Function(unused_type
, Context
)>::type
99 // If you got an error_invalid_expression error message here,
100 // then the expression (expr_type) is not a valid spirit karma
102 BOOST_SPIRIT_ASSERT_MATCH(karma::domain
, expr_type
);
105 result_of::compile
<karma::domain
, expr_type
, modifier
>::type
109 traits::attribute_of
<generator_type
, Context
, Iterator
>::type
113 lazy_generator(Function
const& func
, Modifiers
const& modifiers
)
114 : func(func
), modifiers(modifiers
) {}
117 typename OutputIterator
, typename Context
,
118 typename Delimiter
, typename Attribute
120 bool generate(OutputIterator
& sink
, Context
& context
,
121 Delimiter
const& d
, Attribute
const& attr
) const
123 return detail::lazy_generate_impl_main(
124 compile
<karma::domain
>(func(unused
, context
)
125 , karma_modify()(tag::lazy_eval(), modifiers
))
126 , sink
, context
, d
, attr
);
129 template <typename Context
>
130 info
what(Context
& context
) const
133 , compile
<karma::domain
>(func(unused
, context
)
134 , karma_modify()(tag::lazy_eval(), modifiers
))
143 // silence MSVC warning C4512: assignment operator could not be generated
144 lazy_generator
& operator= (lazy_generator
const&);
147 ///////////////////////////////////////////////////////////////////////////
148 template <typename Function
, typename Subject
, typename Modifiers
>
149 struct lazy_directive
150 : unary_generator
<lazy_directive
<Function
, Subject
, Modifiers
> >
152 typedef mpl::int_
<generator_properties::all_properties
> properties
;
154 typedef Subject subject_type
;
156 template <typename Context
, typename Iterator
>
160 boost::result_of
<karma_modify(tag::lazy_eval
, Modifiers
)>::type
165 typename
boost::result_of
<Function(unused_type
, Context
)>::type
170 proto::result_of::make_expr
<
171 proto::tag::subscript
172 , directive_expr_type
177 // If you got an error_invalid_expression error message here,
178 // then the expression (expr_type) is not a valid spirit karma
180 BOOST_SPIRIT_ASSERT_MATCH(karma::domain
, expr_type
);
183 result_of::compile
<karma::domain
, expr_type
, modifier
>::type
187 traits::attribute_of
<generator_type
, Context
, Iterator
>::type
191 lazy_directive(Function
const& function
, Subject
const& subject
192 , Modifiers
const& modifiers
)
193 : function(function
), subject(subject
), modifiers(modifiers
) {}
195 template <typename OutputIterator
, typename Context
, typename Delimiter
196 , typename Attribute
>
197 bool generate(OutputIterator
& sink
, Context
& ctx
, Delimiter
const& d
198 , Attribute
const& attr
) const
200 return detail::lazy_generate_impl_main(compile
<karma::domain
>(
201 proto::make_expr
<proto::tag::subscript
>(
202 function(unused
, ctx
), subject
)
203 , karma_modify()(tag::lazy_eval(), modifiers
))
204 , sink
, ctx
, d
, attr
);
207 template <typename Context
>
208 info
what(Context
& ctx
) const
210 return info("lazy-directive"
211 , compile
<karma::domain
>(
212 proto::make_expr
<proto::tag::subscript
>(
213 function(unused
, ctx
), subject
)
214 , karma_modify()(tag::lazy_eval(), modifiers
))
224 ///////////////////////////////////////////////////////////////////////////
225 // Generator generators: make_xxx function (objects)
226 ///////////////////////////////////////////////////////////////////////////
227 template <typename Eval
, typename Modifiers
>
228 struct make_primitive
<phoenix::actor
<Eval
>, Modifiers
>
230 typedef lazy_generator
<phoenix::actor
<Eval
>, Modifiers
> result_type
;
231 result_type
operator()(phoenix::actor
<Eval
> const& f
232 , Modifiers
const& modifiers
) const
234 return result_type(f
, modifiers
);
238 template <typename Terminal
, typename Actor
, int Arity
, typename Modifiers
>
239 struct make_primitive
<lazy_terminal
<Terminal
, Actor
, Arity
>, Modifiers
>
241 typedef lazy_generator
<Actor
, Modifiers
> result_type
;
242 result_type
operator()(
243 lazy_terminal
<Terminal
, Actor
, Arity
> const& lt
244 , Modifiers
const& modifiers
) const
246 return result_type(lt
.actor
, modifiers
);
251 typename Terminal
, typename Actor
, int Arity
, typename Subject
252 , typename Modifiers
>
253 struct make_directive
<lazy_terminal
<Terminal
, Actor
, Arity
>
254 , Subject
, Modifiers
>
256 typedef lazy_directive
<Actor
, Subject
, Modifiers
> result_type
;
257 result_type
operator()(
258 lazy_terminal
<Terminal
, Actor
, Arity
> const& lt
259 , Subject
const& subject
, Modifiers
const& modifiers
) const
261 return result_type(lt
.actor
, subject
, modifiers
);