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_AUTO_NOV_29_2009_0339PM) 7 #define BOOST_SPIRIT_KARMA_AUTO_NOV_29_2009_0339PM 8 9 #if defined(_MSC_VER) 10 #pragma once 11 #endif 12 13 #include <boost/spirit/home/support/common_terminals.hpp> 14 #include <boost/spirit/home/support/info.hpp> 15 #include <boost/spirit/home/support/container.hpp> 16 #include <boost/spirit/home/support/assert_msg.hpp> 17 #include <boost/spirit/home/support/detail/hold_any.hpp> 18 #include <boost/spirit/home/karma/domain.hpp> 19 #include <boost/spirit/home/karma/meta_compiler.hpp> 20 #include <boost/spirit/home/karma/delimit_out.hpp> 21 #include <boost/spirit/home/karma/generator.hpp> 22 #include <boost/spirit/home/karma/auto/create_generator.hpp> 23 #include <boost/mpl/bool.hpp> 24 25 /////////////////////////////////////////////////////////////////////////////// 26 namespace boost { namespace spirit 27 { 28 /////////////////////////////////////////////////////////////////////////// 29 // Enablers 30 /////////////////////////////////////////////////////////////////////////// 31 template <> 32 struct use_terminal<karma::domain, tag::auto_> // enables auto_ 33 : mpl::true_ {}; 34 35 template <typename A0> 36 struct use_terminal<karma::domain // enables auto_(...) 37 , terminal_ex<tag::auto_, fusion::vector1<A0> > 38 > : mpl::true_ {}; 39 40 template <> // enables auto_(f) 41 struct use_lazy_terminal< 42 karma::domain, tag::auto_, 1 /*arity*/ 43 > : mpl::true_ {}; 44 45 }} 46 47 /////////////////////////////////////////////////////////////////////////////// 48 namespace boost { namespace spirit { namespace karma 49 { 50 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 51 using spirit::auto_; 52 #endif 53 using spirit::auto_type; 54 55 /////////////////////////////////////////////////////////////////////////// 56 template <typename Modifiers> 57 struct auto_generator 58 : generator<auto_generator<Modifiers> > 59 { 60 typedef mpl::int_<generator_properties::all_properties> properties; 61 62 template <typename Context, typename Unused> 63 struct attribute 64 { 65 typedef spirit::basic_hold_any<char> type; 66 }; 67 auto_generatorboost::spirit::karma::auto_generator68 auto_generator(Modifiers const& modifiers) 69 : modifiers_(modifiers) {} 70 71 // auto_generator has an attached attribute 72 template < 73 typename OutputIterator, typename Context, typename Delimiter 74 , typename Attribute> generateboost::spirit::karma::auto_generator75 bool generate(OutputIterator& sink, Context& context 76 , Delimiter const& d, Attribute const& attr) const 77 { 78 return compile<karma::domain>(create_generator<Attribute>(), modifiers_) 79 .generate(sink, context, d, attr); 80 } 81 82 // this auto_generator has no attribute attached, it needs to have been 83 // initialized from a value/variable 84 template <typename OutputIterator, typename Context 85 , typename Delimiter> 86 static bool generateboost::spirit::karma::auto_generator87 generate(OutputIterator&, Context&, Delimiter const&, unused_type) 88 { 89 // It is not possible (doesn't make sense) to use auto_ generators 90 // without providing any attribute, as the generator doesn't 'know' 91 // what to output. The following assertion fires if this situation 92 // is detected in your code. 93 BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, auto_not_usable_without_attribute, ()); 94 return false; 95 } 96 97 template <typename Context> whatboost::spirit::karma::auto_generator98 info what(Context& /*context*/) const 99 { 100 return info("auto_"); 101 } 102 103 Modifiers modifiers_; 104 }; 105 106 /////////////////////////////////////////////////////////////////////////// 107 template <typename T, typename Modifiers> 108 struct lit_auto_generator 109 : generator<lit_auto_generator<T, Modifiers> > 110 { 111 typedef mpl::int_<generator_properties::all_properties> properties; 112 113 template <typename Context, typename Unused> 114 struct attribute 115 { 116 typedef unused_type type; 117 }; 118 lit_auto_generatorboost::spirit::karma::lit_auto_generator119 lit_auto_generator(typename add_reference<T>::type t, Modifiers const& modifiers) 120 : t_(t) 121 , generator_(compile<karma::domain>(create_generator<T>(), modifiers)) 122 {} 123 124 // auto_generator has an attached attribute 125 template < 126 typename OutputIterator, typename Context, typename Delimiter 127 , typename Attribute> generateboost::spirit::karma::lit_auto_generator128 bool generate(OutputIterator& sink, Context& context 129 , Delimiter const& d, Attribute const&) const 130 { 131 return generator_.generate(sink, context, d, t_); 132 } 133 134 template <typename Context> whatboost::spirit::karma::lit_auto_generator135 info what(Context& /*context*/) const 136 { 137 return info("auto_"); 138 } 139 140 typedef typename spirit::result_of::create_generator<T>::type 141 generator_type; 142 143 typedef typename spirit::result_of::compile< 144 karma::domain, generator_type, Modifiers>::type generator_impl_type; 145 146 T t_; 147 generator_impl_type generator_; 148 149 // silence MSVC warning C4512: assignment operator could not be generated 150 BOOST_DELETED_FUNCTION(lit_auto_generator& operator= (lit_auto_generator const&)) 151 }; 152 153 /////////////////////////////////////////////////////////////////////////// 154 // Generator generators: make_xxx function (objects) 155 /////////////////////////////////////////////////////////////////////////// 156 157 // auto_ 158 template <typename Modifiers> 159 struct make_primitive<tag::auto_, Modifiers> 160 { 161 typedef auto_generator<Modifiers> result_type; 162 operator ()boost::spirit::karma::make_primitive163 result_type operator()(unused_type, Modifiers const& modifiers) const 164 { 165 return result_type(modifiers); 166 } 167 }; 168 169 // auto_(...) 170 template <typename Modifiers, typename A0> 171 struct make_primitive< 172 terminal_ex<tag::auto_, fusion::vector1<A0> >, Modifiers> 173 { 174 typedef typename add_const<A0>::type const_attribute; 175 176 typedef lit_auto_generator<const_attribute, Modifiers> result_type; 177 178 template <typename Terminal> operator ()boost::spirit::karma::make_primitive179 result_type operator()(Terminal const& term, Modifiers const& modifiers) const 180 { 181 return result_type(fusion::at_c<0>(term.args), modifiers); 182 } 183 }; 184 185 }}} 186 187 #endif 188