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 typedef traits::make_attribute<attr_type, Attribute> make_attribute; 57 58 // create a attribute if none is supplied 59 // this creates a _copy_ of the attribute because the semantic 60 // action will likely change parts of this 61 typedef traits::transform_attribute< 62 typename make_attribute::type, attr_type, domain> transform; 63 64 typename transform::type attr = 65 traits::pre_transform<domain, attr_type>(make_attribute::call(attr_)); 66 67 // call the function, passing the attribute, the context and a bool 68 // flag that the client can set to false to fail generating. 69 return traits::action_dispatch<Subject>()(f, attr, ctx) && 70 subject.generate(sink, ctx, d, attr); 71 } 72 73 template <typename Context> whatboost::spirit::karma::action74 info what(Context& context) const 75 { 76 // the action is transparent (does not add any info) 77 return subject.what(context); 78 } 79 80 subject_type subject; 81 Action f; 82 }; 83 84 }}} 85 86 /////////////////////////////////////////////////////////////////////////////// 87 namespace boost { namespace spirit 88 { 89 /////////////////////////////////////////////////////////////////////////// 90 // Karma action meta-compiler 91 template <> 92 struct make_component<karma::domain, tag::action> 93 { 94 template <typename Sig> 95 struct result; 96 97 template <typename This, typename Elements, typename Modifiers> 98 struct result<This(Elements, Modifiers)> 99 { 100 typedef typename 101 remove_const<typename Elements::car_type>::type 102 subject_type; 103 104 typedef typename 105 remove_const<typename Elements::cdr_type::car_type>::type 106 action_type; 107 108 typedef karma::action<subject_type, action_type> type; 109 }; 110 111 template <typename Elements> 112 typename result<make_component(Elements, unused_type)>::type operator ()boost::spirit::make_component113 operator()(Elements const& elements, unused_type) const 114 { 115 typename result<make_component(Elements, unused_type)>::type 116 result(elements.car, elements.cdr.car); 117 return result; 118 } 119 }; 120 }} 121 122 namespace boost { namespace spirit { namespace traits 123 { 124 /////////////////////////////////////////////////////////////////////////// 125 template <typename Subject, typename Action> 126 struct has_semantic_action<karma::action<Subject, Action> > 127 : mpl::true_ {}; 128 129 /////////////////////////////////////////////////////////////////////////// 130 template <typename Subject, typename Action, typename Attribute 131 , typename Context, typename Iterator> 132 struct handles_container<karma::action<Subject, Action>, Attribute 133 , Context, Iterator> 134 : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 135 }}} 136 137 #endif 138