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_CHAR_CLASS_AUG_10_2009_0720AM) 7 #define BOOST_SPIRIT_KARMA_CHAR_CLASS_AUG_10_2009_0720AM 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/string_traits.hpp> 15 #include <boost/spirit/home/support/info.hpp> 16 #include <boost/spirit/home/support/char_class.hpp> 17 #include <boost/spirit/home/support/detail/get_encoding.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/char/char_generator.hpp> 22 #include <boost/spirit/home/karma/auxiliary/lazy.hpp> 23 #include <boost/spirit/home/karma/detail/get_casetag.hpp> 24 #include <boost/spirit/home/karma/detail/generate_to.hpp> 25 26 /////////////////////////////////////////////////////////////////////////////// 27 namespace boost { namespace spirit 28 { 29 /////////////////////////////////////////////////////////////////////////// 30 // Enablers 31 /////////////////////////////////////////////////////////////////////////// 32 // enables alnum, alpha, graph, etc. 33 template <typename CharClass, typename CharEncoding> 34 struct use_terminal<karma::domain 35 , tag::char_code<CharClass, CharEncoding> > 36 : mpl::true_ {}; 37 38 }} 39 40 /////////////////////////////////////////////////////////////////////////////// 41 namespace boost { namespace spirit { namespace karma 42 { 43 // hoist the char classification namespaces into karma sub-namespaces of 44 // the same name 45 namespace ascii { using namespace boost::spirit::ascii; } 46 namespace iso8859_1 { using namespace boost::spirit::iso8859_1; } 47 namespace standard { using namespace boost::spirit::standard; } 48 namespace standard_wide { using namespace boost::spirit::standard_wide; } 49 #if defined(BOOST_SPIRIT_UNICODE) 50 namespace unicode { using namespace boost::spirit::unicode; } 51 #endif 52 53 // Import the standard namespace into the karma namespace. This allows 54 // for default handling of all character/string related operations if not 55 // prefixed with a character set namespace. 56 using namespace boost::spirit::standard; 57 58 // Import encoding 59 using spirit::encoding; 60 61 /////////////////////////////////////////////////////////////////////////// 62 // 63 // char_class 64 // generates a single character if it matches the given character 65 // class 66 // 67 /////////////////////////////////////////////////////////////////////////// 68 template <typename Tag, typename CharEncoding, typename CharClass> 69 struct char_class 70 : char_generator< 71 char_class<Tag, CharEncoding, CharClass> 72 , CharEncoding, CharClass> 73 { 74 typedef typename Tag::char_encoding char_encoding; 75 typedef typename char_encoding::char_type char_type; 76 typedef typename Tag::char_class classification; 77 78 template <typename Context, typename Unused> 79 struct attribute 80 { 81 typedef char_type type; 82 }; 83 84 // char_class needs an attached attribute 85 template <typename Attribute, typename CharParam, typename Context> testboost::spirit::karma::char_class86 bool test(Attribute const& attr, CharParam& ch, Context&) const 87 { 88 ch = attr; 89 90 using spirit::char_class::classify; 91 return classify<char_encoding>::is(classification(), attr); 92 } 93 94 // char_class shouldn't be used without any associated attribute 95 template <typename CharParam, typename Context> testboost::spirit::karma::char_class96 bool test(unused_type, CharParam&, Context&) const 97 { 98 // It is not possible (doesn't make sense) to use char_ generators 99 // without providing any attribute, as the generator doesn't 'know' 100 // what to output. The following assertion fires if this situation 101 // is detected in your code. 102 BOOST_SPIRIT_ASSERT_FAIL(CharParam 103 , char_class_not_usable_without_attribute, ()); 104 return false; 105 } 106 107 template <typename Context> whatboost::spirit::karma::char_class108 static info what(Context const& /*context*/) 109 { 110 typedef spirit::char_class::what<char_encoding> what_; 111 return info(what_::is(classification())); 112 } 113 }; 114 115 /////////////////////////////////////////////////////////////////////////// 116 // 117 // space 118 // generates a single character from the associated parameter 119 // 120 /////////////////////////////////////////////////////////////////////////// 121 template <typename CharEncoding> 122 struct any_space 123 : char_generator<any_space<CharEncoding>, CharEncoding, tag::space> 124 { 125 typedef typename CharEncoding::char_type char_type; 126 typedef CharEncoding char_encoding; 127 128 template <typename Context, typename Unused> 129 struct attribute 130 { 131 typedef char_type type; 132 }; 133 134 // any_space has an attached parameter 135 template <typename Attribute, typename CharParam, typename Context> testboost::spirit::karma::any_space136 bool test(Attribute const& attr, CharParam& ch, Context&) const 137 { 138 ch = CharParam(attr); 139 140 using spirit::char_class::classify; 141 return classify<char_encoding>::is(tag::space(), attr); 142 } 143 144 // any_space has no attribute attached, use single space character 145 template <typename CharParam, typename Context> testboost::spirit::karma::any_space146 bool test(unused_type, CharParam& ch, Context&) const 147 { 148 ch = ' '; 149 return true; 150 } 151 152 template <typename Context> whatboost::spirit::karma::any_space153 static info what(Context const& /*context*/) 154 { 155 return info("space"); 156 } 157 }; 158 159 /////////////////////////////////////////////////////////////////////////// 160 // Generator generators: make_xxx function (objects) 161 /////////////////////////////////////////////////////////////////////////// 162 163 namespace detail 164 { 165 template <typename Tag, bool lower = false, bool upper = false> 166 struct make_char_class : mpl::identity<Tag> {}; 167 168 template <> 169 struct make_char_class<tag::alpha, true, false> 170 : mpl::identity<tag::lower> {}; 171 172 template <> 173 struct make_char_class<tag::alpha, false, true> 174 : mpl::identity<tag::upper> {}; 175 176 template <> 177 struct make_char_class<tag::alnum, true, false> 178 : mpl::identity<tag::lowernum> {}; 179 180 template <> 181 struct make_char_class<tag::alnum, false, true> 182 : mpl::identity<tag::uppernum> {}; 183 } 184 185 // enables alnum, alpha, graph, etc. 186 template <typename CharClass, typename CharEncoding, typename Modifiers> 187 struct make_primitive<tag::char_code<CharClass, CharEncoding>, Modifiers> 188 { 189 static bool const lower = 190 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; 191 static bool const upper = 192 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; 193 194 typedef tag::char_code< 195 typename detail::make_char_class<CharClass, lower, upper>::type 196 , CharEncoding> 197 tag_type; 198 199 typedef char_class< 200 tag_type 201 , typename spirit::detail::get_encoding_with_case< 202 Modifiers, CharEncoding, lower || upper>::type 203 , typename detail::get_casetag<Modifiers, lower || upper>::type 204 > result_type; 205 operator ()boost::spirit::karma::make_primitive206 result_type operator()(unused_type, unused_type) const 207 { 208 return result_type(); 209 } 210 }; 211 212 // space is special 213 template <typename CharEncoding, typename Modifiers> 214 struct make_primitive<tag::char_code<tag::space, CharEncoding>, Modifiers> 215 { 216 typedef any_space<CharEncoding> result_type; 217 operator ()boost::spirit::karma::make_primitive218 result_type operator()(unused_type, unused_type) const 219 { 220 return result_type(); 221 } 222 }; 223 224 }}} // namespace boost::spirit::karma 225 226 #endif // !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM) 227