1 // Copyright (c) 2001-2011 Hartmut Kaiser 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #if !defined(BOOST_SPIRIT_KARMA_ACTION_MAR_07_2007_0851AM) 7 #define BOOST_SPIRIT_KARMA_ACTION_MAR_07_2007_0851AM 8 9 #if defined(_MSC_VER) 10 #pragma once 11 #endif 12 13 #include <boost/spirit/home/karma/detail/attributes.hpp> 14 #include <boost/spirit/home/support/argument.hpp> 15 #include <boost/spirit/home/support/context.hpp> 16 #include <boost/spirit/home/support/unused.hpp> 17 #include <boost/spirit/home/support/info.hpp> 18 #include <boost/spirit/home/support/action_dispatch.hpp> 19 #include <boost/spirit/home/support/has_semantic_action.hpp> 20 #include <boost/spirit/home/support/handles_container.hpp> 21 #include <boost/spirit/home/karma/domain.hpp> 22 #include <boost/spirit/home/karma/meta_compiler.hpp> 23 #include <boost/spirit/home/karma/generator.hpp> 24 25 #include <boost/mpl/bool.hpp> 26 #include <boost/mpl/if.hpp> 27 #include <boost/type_traits/remove_const.hpp> 28 #include <boost/type_traits/is_same.hpp> 29 30 namespace boost { namespace spirit { namespace karma 31 { 32 /////////////////////////////////////////////////////////////////////////// 33 BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _) 34 35 template <typename Subject, typename Action> 36 struct action : unary_generator<action<Subject, Action> > 37 { 38 typedef Subject subject_type; 39 typedef typename subject_type::properties properties; 40 41 template <typename Context, typename Iterator> 42 struct attribute 43 : traits::attribute_of<Subject, Context, Iterator> 44 {}; 45 actionboost::spirit::karma::action46 action(Subject const& subject, Action f) 47 : subject(subject), f(f) {} 48 49 template < 50 typename OutputIterator, typename Context, typename Delimiter 51 , typename Attribute> generateboost::spirit::karma::action52 bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d 53 , Attribute const& attr_) const 54 { 55 typedef typename attribute<Context, unused_type>::type attr_type; 56 57 // create a attribute if none is supplied 58 // this creates a _copy_ of the attribute because the semantic 59 // action will likely change parts of this 60 typedef traits::transform_attribute< 61 Attribute const, attr_type, domain> transform; 62 63 attr_type attr = transform::pre(attr_); 64 65 // call the function, passing the attribute, the context and a bool 66 // flag that the client can set to false to fail generating. 67 return traits::action_dispatch<Subject>()(f, attr, ctx) && 68 subject.generate(sink, ctx, d, attr); 69 } 70 71 template <typename Context> whatboost::spirit::karma::action72 info what(Context& context) const 73 { 74 // the action is transparent (does not add any info) 75 return subject.what(context); 76 } 77 78 subject_type subject; 79 Action f; 80 }; 81 82 }}} 83 84 /////////////////////////////////////////////////////////////////////////////// 85 namespace boost { namespace spirit 86 { 87 /////////////////////////////////////////////////////////////////////////// 88 // Karma action meta-compiler 89 template <> 90 struct make_component<karma::domain, tag::action> 91 { 92 template <typename Sig> 93 struct result; 94 95 template <typename This, typename Elements, typename Modifiers> 96 struct result<This(Elements, Modifiers)> 97 { 98 typedef typename 99 remove_const<typename Elements::car_type>::type 100 subject_type; 101 102 typedef typename 103 remove_const<typename Elements::cdr_type::car_type>::type 104 action_type; 105 106 typedef karma::action<subject_type, action_type> type; 107 }; 108 109 template <typename Elements> 110 typename result<make_component(Elements, unused_type)>::type operator ()boost::spirit::make_component111 operator()(Elements const& elements, unused_type) const 112 { 113 typename result<make_component(Elements, unused_type)>::type 114 result(elements.car, elements.cdr.car); 115 return result; 116 } 117 }; 118 }} 119 120 namespace boost { namespace spirit { namespace traits 121 { 122 /////////////////////////////////////////////////////////////////////////// 123 template <typename Subject, typename Action> 124 struct has_semantic_action<karma::action<Subject, Action> > 125 : mpl::true_ {}; 126 127 /////////////////////////////////////////////////////////////////////////// 128 template <typename Subject, typename Action, typename Attribute 129 , typename Context, typename Iterator> 130 struct handles_container<karma::action<Subject, Action>, Attribute 131 , Context, Iterator> 132 : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 133 }}} 134 135 #endif 136