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