Chris@16: // Copyright (c) 2001-2011 Hartmut Kaiser Chris@16: // Copyright (c) 2001-2011 Joel de Guzman Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #if !defined(BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM) Chris@16: #define BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM Chris@16: Chris@16: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace spirit Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Enablers Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct use_terminal > // enables phoenix actors Chris@16: : mpl::true_ {}; Chris@16: Chris@16: // forward declaration Chris@16: template Chris@16: struct lazy_terminal; Chris@16: Chris@16: }} Chris@16: Chris@16: namespace boost { namespace spirit { namespace karma Chris@16: { Chris@16: using spirit::lazy; Chris@16: typedef modify karma_modify; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: bool lazy_generate_impl(Generator const& g, OutputIterator& sink Chris@16: , Context& context, Delimiter const& delim Chris@16: , Attribute const& attr, mpl::false_) Chris@16: { Chris@16: return g.generate(sink, context, delim, attr); Chris@16: } Chris@16: Chris@16: template Chris@16: bool lazy_generate_impl(Generator const& g, OutputIterator& sink Chris@16: , Context& context, Delimiter const& delim Chris@16: , Attribute const& attr, mpl::true_) Chris@16: { Chris@16: // If DeducedAuto is false (semantic actions is present), the Chris@16: // component's attribute is unused. Chris@16: return g.generate(sink, context, delim, unused); Chris@16: } Chris@16: Chris@16: template Chris@16: bool lazy_generate_impl_main(Generator const& g, OutputIterator& sink Chris@16: , Context& context, Delimiter const& delim, Attribute const& attr) Chris@16: { Chris@16: // If DeducedAuto is true (no semantic action), we pass the parser's Chris@16: // attribute on to the component. Chris@16: typedef typename traits::has_semantic_action::type auto_rule; Chris@16: return lazy_generate_impl(g, sink, context, delim, attr, auto_rule()); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: struct lazy_generator : generator > Chris@16: { Chris@16: typedef mpl::int_ properties; Chris@16: Chris@16: template Chris@16: struct attribute Chris@16: { Chris@16: typedef typename Chris@16: boost::result_of::type Chris@16: modifier; Chris@16: Chris@16: typedef typename Chris@16: remove_reference< Chris@16: typename boost::result_of::type Chris@16: >::type Chris@16: expr_type; Chris@16: Chris@16: // If you got an error_invalid_expression error message here, Chris@16: // then the expression (expr_type) is not a valid spirit karma Chris@16: // expression. Chris@16: BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type); Chris@16: Chris@16: typedef typename Chris@16: result_of::compile::type Chris@16: generator_type; Chris@16: Chris@16: typedef typename Chris@16: traits::attribute_of::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: lazy_generator(Function const& func, Modifiers const& modifiers) Chris@16: : func(func), modifiers(modifiers) {} Chris@16: Chris@16: template < Chris@16: typename OutputIterator, typename Context, Chris@16: typename Delimiter, typename Attribute Chris@16: > Chris@16: bool generate(OutputIterator& sink, Context& context, Chris@16: Delimiter const& d, Attribute const& attr) const Chris@16: { Chris@16: return detail::lazy_generate_impl_main( Chris@16: compile(func(unused, context) Chris@16: , karma_modify()(tag::lazy_eval(), modifiers)) Chris@16: , sink, context, d, attr); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context& context) const Chris@16: { Chris@16: return info("lazy" Chris@16: , compile(func(unused, context) Chris@16: , karma_modify()(tag::lazy_eval(), modifiers)) Chris@16: .what(context) Chris@16: ); Chris@16: } Chris@16: Chris@16: Function func; Chris@16: Modifiers modifiers; Chris@16: Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: lazy_generator& operator= (lazy_generator const&); Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct lazy_directive Chris@16: : unary_generator > Chris@16: { Chris@16: typedef mpl::int_ properties; Chris@16: Chris@16: typedef Subject subject_type; Chris@16: Chris@16: template Chris@16: struct attribute Chris@16: { Chris@16: typedef typename Chris@16: boost::result_of::type Chris@16: modifier; Chris@16: Chris@16: typedef typename Chris@16: remove_reference< Chris@16: typename boost::result_of::type Chris@16: >::type Chris@16: directive_expr_type; Chris@16: Chris@16: typedef typename Chris@16: proto::result_of::make_expr< Chris@16: proto::tag::subscript Chris@16: , directive_expr_type Chris@16: , Subject Chris@16: >::type Chris@16: expr_type; Chris@16: Chris@16: // If you got an error_invalid_expression error message here, Chris@16: // then the expression (expr_type) is not a valid spirit karma Chris@16: // expression. Chris@16: BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type); Chris@16: Chris@16: typedef typename Chris@16: result_of::compile::type Chris@16: generator_type; Chris@16: Chris@16: typedef typename Chris@16: traits::attribute_of::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: lazy_directive(Function const& function, Subject const& subject Chris@16: , Modifiers const& modifiers) Chris@16: : function(function), subject(subject), modifiers(modifiers) {} Chris@16: Chris@16: template Chris@16: bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d Chris@16: , Attribute const& attr) const Chris@16: { Chris@16: return detail::lazy_generate_impl_main(compile( Chris@16: proto::make_expr( Chris@16: function(unused, ctx), subject) Chris@16: , karma_modify()(tag::lazy_eval(), modifiers)) Chris@16: , sink, ctx, d, attr); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context& ctx) const Chris@16: { Chris@16: return info("lazy-directive" Chris@16: , compile( Chris@16: proto::make_expr( Chris@16: function(unused, ctx), subject) Chris@16: , karma_modify()(tag::lazy_eval(), modifiers)) Chris@16: .what(ctx) Chris@16: ); Chris@16: } Chris@16: Chris@16: Function function; Chris@16: Subject subject; Chris@16: Modifiers modifiers; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Generator generators: make_xxx function (objects) Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct make_primitive, Modifiers> Chris@16: { Chris@16: typedef lazy_generator, Modifiers> result_type; Chris@16: result_type operator()(phoenix::actor const& f Chris@16: , Modifiers const& modifiers) const Chris@16: { Chris@16: return result_type(f, modifiers); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_primitive, Modifiers> Chris@16: { Chris@16: typedef lazy_generator result_type; Chris@16: result_type operator()( Chris@16: lazy_terminal const& lt Chris@16: , Modifiers const& modifiers) const Chris@16: { Chris@16: return result_type(lt.actor, modifiers); Chris@16: } Chris@16: }; Chris@16: Chris@16: template < Chris@16: typename Terminal, typename Actor, int Arity, typename Subject Chris@16: , typename Modifiers> Chris@16: struct make_directive Chris@16: , Subject, Modifiers> Chris@16: { Chris@16: typedef lazy_directive result_type; Chris@16: result_type operator()( Chris@16: lazy_terminal const& lt Chris@16: , Subject const& subject, Modifiers const& modifiers) const Chris@16: { Chris@16: return result_type(lt.actor, subject, modifiers); Chris@16: } Chris@16: }; Chris@16: Chris@16: }}} Chris@16: Chris@16: #endif