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_DELIMIT_MAR_02_2007_0217PM) 7 #define BOOST_SPIRIT_KARMA_DELIMIT_MAR_02_2007_0217PM 8 9 #if defined(_MSC_VER) 10 #pragma once 11 #endif 12 13 #include <boost/spirit/home/karma/meta_compiler.hpp> 14 #include <boost/spirit/home/karma/generator.hpp> 15 #include <boost/spirit/home/karma/domain.hpp> 16 #include <boost/spirit/home/karma/detail/unused_delimiter.hpp> 17 #include <boost/spirit/home/karma/delimit_out.hpp> 18 #include <boost/spirit/home/karma/auxiliary/lazy.hpp> 19 #include <boost/spirit/home/support/unused.hpp> 20 #include <boost/spirit/home/support/common_terminals.hpp> 21 #include <boost/spirit/home/support/has_semantic_action.hpp> 22 #include <boost/spirit/home/support/handles_container.hpp> 23 #include <boost/spirit/home/karma/detail/attributes.hpp> 24 #include <boost/spirit/home/support/info.hpp> 25 #include <boost/fusion/include/at.hpp> 26 #include <boost/fusion/include/vector.hpp> 27 28 namespace boost { namespace spirit 29 { 30 /////////////////////////////////////////////////////////////////////////// 31 // Enablers 32 /////////////////////////////////////////////////////////////////////////// 33 template <> 34 struct use_directive<karma::domain, tag::delimit> // enables delimit[] 35 : mpl::true_ {}; 36 37 // enables delimit(d)[g], where d is a generator 38 template <typename T> 39 struct use_directive<karma::domain 40 , terminal_ex<tag::delimit, fusion::vector1<T> > > 41 : boost::spirit::traits::matches<karma::domain, T> {}; 42 43 // enables *lazy* delimit(d)[g] 44 template <> 45 struct use_lazy_directive<karma::domain, tag::delimit, 1> 46 : mpl::true_ {}; 47 48 }} 49 50 namespace boost { namespace spirit { namespace karma 51 { 52 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 53 using spirit::delimit; 54 #endif 55 using spirit::delimit_type; 56 57 /////////////////////////////////////////////////////////////////////////// 58 // The redelimit_generator generator is used for delimit[...] directives. 59 /////////////////////////////////////////////////////////////////////////// 60 template <typename Subject> 61 struct redelimit_generator : unary_generator<redelimit_generator<Subject> > 62 { 63 typedef Subject subject_type; 64 65 typedef typename subject_type::properties properties; 66 67 template <typename Context, typename Iterator> 68 struct attribute 69 : traits::attribute_of<subject_type, Context, Iterator> 70 {}; 71 redelimit_generatorboost::spirit::karma::redelimit_generator72 redelimit_generator(Subject const& subject) 73 : subject(subject) {} 74 75 template <typename OutputIterator, typename Context, typename Delimiter 76 , typename Attribute> generateboost::spirit::karma::redelimit_generator77 bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d 78 , Attribute const& attr) const 79 { 80 // The delimit_space generator simply dispatches to the embedded 81 // generator while supplying either the delimiter which has been 82 // used before a surrounding verbatim[] directive or a single 83 // space as the new delimiter to use (if no surrounding verbatim[] 84 // was specified). 85 return subject.generate(sink, ctx 86 , detail::get_delimiter(d, compile<karma::domain>(' ')), attr); 87 } 88 89 template <typename Context> whatboost::spirit::karma::redelimit_generator90 info what(Context& context) const 91 { 92 return info("delimit", subject.what(context)); 93 } 94 95 Subject subject; 96 }; 97 98 /////////////////////////////////////////////////////////////////////////// 99 // The delimit_generator is used for delimit(d)[...] directives. 100 /////////////////////////////////////////////////////////////////////////// 101 template <typename Subject, typename Delimiter> 102 struct delimit_generator 103 : unary_generator<delimit_generator<Subject, Delimiter> > 104 { 105 typedef Subject subject_type; 106 typedef Delimiter delimiter_type; 107 108 typedef typename subject_type::properties properties; 109 110 template <typename Context, typename Iterator> 111 struct attribute 112 : traits::attribute_of<subject_type, Context, Iterator> 113 {}; 114 delimit_generatorboost::spirit::karma::delimit_generator115 delimit_generator(Subject const& subject, Delimiter const& delimiter) 116 : subject(subject), delimiter(delimiter) {} 117 118 template <typename OutputIterator, typename Context 119 , typename Delimiter_, typename Attribute> generateboost::spirit::karma::delimit_generator120 bool generate(OutputIterator& sink, Context& ctx, Delimiter_ const& 121 , Attribute const& attr) const 122 { 123 // the delimit generator simply dispatches to the embedded 124 // generator while supplying it's argument as the new delimiter 125 // to use 126 return subject.generate(sink, ctx, delimiter, attr); 127 } 128 129 template <typename Context> whatboost::spirit::karma::delimit_generator130 info what(Context& context) const 131 { 132 return info("delimit", subject.what(context)); 133 } 134 135 Subject subject; 136 Delimiter delimiter; 137 }; 138 139 /////////////////////////////////////////////////////////////////////////// 140 // Generator generators: make_xxx function (objects) 141 /////////////////////////////////////////////////////////////////////////// 142 template <typename Subject, typename Modifiers> 143 struct make_directive<tag::delimit, Subject, Modifiers> 144 { 145 typedef redelimit_generator<Subject> result_type; operator ()boost::spirit::karma::make_directive146 result_type operator()(unused_type, Subject const& subject 147 , unused_type) const 148 { 149 return result_type(subject); 150 } 151 }; 152 153 template <typename Delimiter, typename Subject, typename Modifiers> 154 struct make_directive< 155 terminal_ex<tag::delimit, fusion::vector1<Delimiter> > 156 , Subject, Modifiers> 157 { 158 typedef typename 159 result_of::compile<karma::domain, Delimiter, Modifiers>::type 160 delimiter_type; 161 162 typedef delimit_generator<Subject, delimiter_type> result_type; 163 164 template <typename Terminal> operator ()boost::spirit::karma::make_directive165 result_type operator()(Terminal const& term, Subject const& subject 166 , unused_type) const 167 { 168 return result_type(subject 169 , compile<karma::domain>(fusion::at_c<0>(term.args))); 170 } 171 }; 172 173 }}} 174 175 namespace boost { namespace spirit { namespace traits 176 { 177 /////////////////////////////////////////////////////////////////////////// 178 template <typename Subject> 179 struct has_semantic_action<karma::redelimit_generator<Subject> > 180 : unary_has_semantic_action<Subject> {}; 181 182 template <typename Subject, typename Delimiter> 183 struct has_semantic_action<karma::delimit_generator<Subject, Delimiter> > 184 : unary_has_semantic_action<Subject> {}; 185 186 /////////////////////////////////////////////////////////////////////////// 187 template <typename Subject, typename Attribute 188 , typename Context, typename Iterator> 189 struct handles_container<karma::redelimit_generator<Subject>, Attribute 190 , Context, Iterator> 191 : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 192 193 template <typename Subject, typename Delimiter, typename Attribute 194 , typename Context, typename Iterator> 195 struct handles_container<karma::delimit_generator<Subject, Delimiter> 196 , Attribute, Context, Iterator> 197 : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 198 }}} 199 200 #endif 201