char_class.hpp 8.0 KB

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