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 27 namespace boost { namespace phoenix 28 { 29 template <typename Expr> 30 struct actor; 31 }} 32 33 namespace 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 48 namespace 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> lazy_generate_impl(Generator const & g,OutputIterator & sink,Context & context,Delimiter const & delim,Attribute const & attr,mpl::false_)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> lazy_generate_impl(Generator const & g,OutputIterator & sink,Context & context,Delimiter const & delim,Attribute const &,mpl::true_)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> lazy_generate_impl_main(Generator const & g,OutputIterator & sink,Context & context,Delimiter const & delim,Attribute const & attr)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 lazy_generatorboost::spirit::karma::lazy_generator119 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 > generateboost::spirit::karma::lazy_generator126 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> whatboost::spirit::karma::lazy_generator136 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 // silence MSVC warning C4512: assignment operator could not be generated 149 BOOST_DELETED_FUNCTION(lazy_generator& operator= (lazy_generator const&)) 150 }; 151 152 /////////////////////////////////////////////////////////////////////////// 153 template <typename Function, typename Subject, typename Modifiers> 154 struct lazy_directive 155 : unary_generator<lazy_directive<Function, Subject, Modifiers> > 156 { 157 typedef mpl::int_<generator_properties::all_properties> properties; 158 159 typedef Subject subject_type; 160 161 template <typename Context, typename Iterator> 162 struct attribute 163 { 164 typedef typename 165 boost::result_of<karma_modify(tag::lazy_eval, Modifiers)>::type 166 modifier; 167 168 typedef typename 169 remove_reference< 170 typename boost::result_of<Function(unused_type, Context)>::type 171 >::type 172 directive_expr_type; 173 174 typedef typename 175 proto::result_of::make_expr< 176 proto::tag::subscript 177 , directive_expr_type 178 , Subject 179 >::type 180 expr_type; 181 182 // If you got an error_invalid_expression error message here, 183 // then the expression (expr_type) is not a valid spirit karma 184 // expression. 185 BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type); 186 187 typedef typename 188 result_of::compile<karma::domain, expr_type, modifier>::type 189 generator_type; 190 191 typedef typename 192 traits::attribute_of<generator_type, Context, Iterator>::type 193 type; 194 }; 195 lazy_directiveboost::spirit::karma::lazy_directive196 lazy_directive(Function const& function, Subject const& subject 197 , Modifiers const& modifiers) 198 : function(function), subject(subject), modifiers(modifiers) {} 199 200 template <typename OutputIterator, typename Context, typename Delimiter 201 , typename Attribute> generateboost::spirit::karma::lazy_directive202 bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d 203 , Attribute const& attr) const 204 { 205 return detail::lazy_generate_impl_main(compile<karma::domain>( 206 proto::make_expr<proto::tag::subscript>( 207 function(unused, ctx), subject) 208 , karma_modify()(tag::lazy_eval(), modifiers)) 209 , sink, ctx, d, attr); 210 } 211 212 template <typename Context> whatboost::spirit::karma::lazy_directive213 info what(Context& ctx) const 214 { 215 return info("lazy-directive" 216 , compile<karma::domain>( 217 proto::make_expr<proto::tag::subscript>( 218 function(unused, ctx), subject) 219 , karma_modify()(tag::lazy_eval(), modifiers)) 220 .what(ctx) 221 ); 222 } 223 224 Function function; 225 Subject subject; 226 Modifiers modifiers; 227 }; 228 229 /////////////////////////////////////////////////////////////////////////// 230 // Generator generators: make_xxx function (objects) 231 /////////////////////////////////////////////////////////////////////////// 232 template <typename Eval, typename Modifiers> 233 struct make_primitive<phoenix::actor<Eval>, Modifiers> 234 { 235 typedef lazy_generator<phoenix::actor<Eval>, Modifiers> result_type; operator ()boost::spirit::karma::make_primitive236 result_type operator()(phoenix::actor<Eval> const& f 237 , Modifiers const& modifiers) const 238 { 239 return result_type(f, modifiers); 240 } 241 }; 242 243 template <typename Terminal, typename Actor, int Arity, typename Modifiers> 244 struct make_primitive<lazy_terminal<Terminal, Actor, Arity>, Modifiers> 245 { 246 typedef lazy_generator<Actor, Modifiers> result_type; operator ()boost::spirit::karma::make_primitive247 result_type operator()( 248 lazy_terminal<Terminal, Actor, Arity> const& lt 249 , Modifiers const& modifiers) const 250 { 251 return result_type(lt.actor, modifiers); 252 } 253 }; 254 255 template < 256 typename Terminal, typename Actor, int Arity, typename Subject 257 , typename Modifiers> 258 struct make_directive<lazy_terminal<Terminal, Actor, Arity> 259 , Subject, Modifiers> 260 { 261 typedef lazy_directive<Actor, Subject, Modifiers> result_type; operator ()boost::spirit::karma::make_directive262 result_type operator()( 263 lazy_terminal<Terminal, Actor, Arity> const& lt 264 , Subject const& subject, Modifiers const& modifiers) const 265 { 266 return result_type(lt.actor, subject, modifiers); 267 } 268 }; 269 270 }}} 271 272 #endif 273