1 // Copyright (c) 2001-2011 Hartmut Kaiser 2 // Copyright (c) 2001-2011 Joel de Guzman 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 #if !defined(BOOST_SPIRIT_CHAR_GENERATOR_SEP_07_2009_0417PM) 8 #define BOOST_SPIRIT_CHAR_GENERATOR_SEP_07_2009_0417PM 9 10 #if defined(_MSC_VER) 11 #pragma once 12 #endif 13 14 #include <boost/spirit/home/karma/domain.hpp> 15 #include <boost/spirit/home/karma/generator.hpp> 16 #include <boost/spirit/home/karma/detail/generate_to.hpp> 17 #include <boost/spirit/home/karma/detail/extract_from.hpp> 18 #include <boost/spirit/home/karma/meta_compiler.hpp> 19 #include <boost/spirit/home/karma/delimit_out.hpp> 20 #include <boost/spirit/home/support/unused.hpp> 21 #include <boost/spirit/home/support/info.hpp> 22 #include <boost/spirit/home/support/container.hpp> 23 #include <boost/proto/operators.hpp> 24 #include <boost/proto/tags.hpp> 25 26 namespace boost { namespace spirit 27 { 28 /////////////////////////////////////////////////////////////////////////// 29 // Enablers 30 /////////////////////////////////////////////////////////////////////////// 31 template <> 32 struct use_operator<karma::domain, proto::tag::complement> // enables ~ 33 : mpl::true_ {}; 34 35 }} 36 37 namespace boost { namespace spirit { namespace traits // classification 38 { 39 namespace detail 40 { 41 BOOST_MPL_HAS_XXX_TRAIT_DEF(char_generator_id) 42 } 43 44 template <typename T> 45 struct is_char_generator : detail::has_char_generator_id<T> {}; 46 }}} 47 48 namespace boost { namespace spirit { namespace karma 49 { 50 /////////////////////////////////////////////////////////////////////////// 51 // The base char_parser 52 /////////////////////////////////////////////////////////////////////////// 53 template <typename Derived, typename CharEncoding, typename Tag 54 , typename Char = typename CharEncoding::char_type, typename Attr = Char> 55 struct char_generator : primitive_generator<Derived> 56 { 57 typedef CharEncoding char_encoding; 58 typedef Tag tag; 59 typedef Char char_type; 60 struct char_generator_id; 61 62 // if Attr is unused_type, Derived must supply its own attribute 63 // metafunction 64 template <typename Context, typename Unused> 65 struct attribute 66 { 67 typedef Attr type; 68 }; 69 70 template < 71 typename OutputIterator, typename Context, typename Delimiter 72 , typename Attribute> generateboost::spirit::karma::char_generator73 bool generate(OutputIterator& sink, Context& context, Delimiter const& d 74 , Attribute const& attr) const 75 { 76 if (!traits::has_optional_value(attr)) 77 return false; 78 79 Attr ch = Attr(); 80 if (!this->derived().test(traits::extract_from<Attr>(attr, context), ch, context)) 81 return false; 82 83 return karma::detail::generate_to(sink, ch, char_encoding(), tag()) && 84 karma::delimit_out(sink, d); // always do post-delimiting 85 } 86 87 // Requirement: g.test(attr, ch, context) -> bool 88 // 89 // attr: associated attribute 90 // ch: character to be generated (set by test()) 91 // context: enclosing rule context 92 }; 93 94 /////////////////////////////////////////////////////////////////////////// 95 // negated_char_generator handles ~cg expressions (cg is a char_generator) 96 /////////////////////////////////////////////////////////////////////////// 97 template <typename Positive> 98 struct negated_char_generator 99 : char_generator<negated_char_generator<Positive> 100 , typename Positive::char_encoding, typename Positive::tag> 101 { negated_char_generatorboost::spirit::karma::negated_char_generator102 negated_char_generator(Positive const& positive) 103 : positive(positive) {} 104 105 template <typename Attribute, typename CharParam, typename Context> testboost::spirit::karma::negated_char_generator106 bool test(Attribute const& attr, CharParam& ch, Context& context) const 107 { 108 return !positive.test(attr, ch, context); 109 } 110 111 template <typename Context> whatboost::spirit::karma::negated_char_generator112 info what(Context& context) const 113 { 114 return info("not", positive.what(context)); 115 } 116 117 Positive positive; 118 }; 119 120 /////////////////////////////////////////////////////////////////////////// 121 // Generator generators: make_xxx function (objects) 122 /////////////////////////////////////////////////////////////////////////// 123 namespace detail 124 { 125 template <typename Positive> 126 struct make_negated_char_generator 127 { 128 typedef negated_char_generator<Positive> result_type; operator ()boost::spirit::karma::detail::make_negated_char_generator129 result_type operator()(Positive const& positive) const 130 { 131 return result_type(positive); 132 } 133 }; 134 135 template <typename Positive> 136 struct make_negated_char_generator<negated_char_generator<Positive> > 137 { 138 typedef Positive result_type; operator ()boost::spirit::karma::detail::make_negated_char_generator139 result_type operator()(negated_char_generator<Positive> const& ncg) const 140 { 141 return ncg.positive; 142 } 143 }; 144 } 145 146 template <typename Elements, typename Modifiers> 147 struct make_composite<proto::tag::complement, Elements, Modifiers> 148 { 149 typedef typename 150 fusion::result_of::value_at_c<Elements, 0>::type 151 subject; 152 153 BOOST_SPIRIT_ASSERT_MSG(( 154 traits::is_char_generator<subject>::value 155 ), subject_is_not_negatable, (subject)); 156 157 typedef typename 158 detail::make_negated_char_generator<subject>::result_type 159 result_type; 160 operator ()boost::spirit::karma::make_composite161 result_type operator()(Elements const& elements, unused_type) const 162 { 163 return detail::make_negated_char_generator<subject>()( 164 fusion::at_c<0>(elements)); 165 } 166 }; 167 168 }}} 169 170 #endif 171