width_of.hpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // width_of.hpp
  3. //
  4. // Copyright 2008 Eric Niebler. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_XPRESSIVE_DETAIL_STATIC_WIDTH_OF_HPP_EAN_10_04_2005
  8. #define BOOST_XPRESSIVE_DETAIL_STATIC_WIDTH_OF_HPP_EAN_10_04_2005
  9. // MS compatible compilers support #pragma once
  10. #if defined(_MSC_VER)
  11. # pragma once
  12. #endif
  13. #include <boost/ref.hpp>
  14. #include <boost/mpl/if.hpp>
  15. #include <boost/mpl/or.hpp>
  16. #include <boost/mpl/plus.hpp>
  17. #include <boost/mpl/times.hpp>
  18. #include <boost/mpl/assert.hpp>
  19. #include <boost/mpl/size_t.hpp>
  20. #include <boost/mpl/equal_to.hpp>
  21. #include <boost/type_traits/is_same.hpp>
  22. #include <boost/xpressive/detail/detail_fwd.hpp>
  23. #include <boost/xpressive/detail/static/type_traits.hpp>
  24. #include <boost/proto/traits.hpp>
  25. namespace boost { namespace xpressive { namespace detail
  26. {
  27. template<typename Expr, typename Char, typename Tag = typename Expr::proto_tag>
  28. struct width_of;
  29. ///////////////////////////////////////////////////////////////////////////////
  30. // add_widths
  31. //
  32. template<std::size_t N, std::size_t M>
  33. struct add_widths
  34. : mpl::size_t<N + M>
  35. {};
  36. template<std::size_t M>
  37. struct add_widths<unknown_width::value, M>
  38. : unknown_width
  39. {};
  40. template<std::size_t N>
  41. struct add_widths<N, unknown_width::value>
  42. : unknown_width
  43. {};
  44. template<>
  45. struct add_widths<unknown_width::value, unknown_width::value>
  46. : unknown_width
  47. {};
  48. ///////////////////////////////////////////////////////////////////////////////
  49. // or_widths
  50. //
  51. template<std::size_t N, std::size_t M>
  52. struct or_widths
  53. : unknown_width
  54. {};
  55. template<std::size_t N>
  56. struct or_widths<N, N>
  57. : mpl::size_t<N>
  58. {};
  59. ///////////////////////////////////////////////////////////////////////////////
  60. // width_of_terminal
  61. //
  62. template<typename Expr, typename Char, bool IsXpr = is_xpr<Expr>::value>
  63. struct width_of_terminal
  64. : mpl::size_t<Expr::width> // xpressive literals
  65. {};
  66. template<typename Expr, typename Char>
  67. struct width_of_terminal<Expr, Char, false>
  68. : unknown_width // unknown literals (eg, basic_string, basic_regex, etc.)
  69. {};
  70. template<typename Char>
  71. struct width_of_terminal<Char, Char, false>
  72. : mpl::size_t<1> // char literals
  73. {};
  74. template<typename Char>
  75. struct width_of_terminal<char, Char, false>
  76. : mpl::size_t<1> // char literals
  77. {};
  78. template<>
  79. struct width_of_terminal<char, char, false>
  80. : mpl::size_t<1> // char literals
  81. {};
  82. template<typename Elem, std::size_t N, typename Char>
  83. struct width_of_terminal<Elem (&) [N], Char, false>
  84. : mpl::size_t<N-is_char<Elem>::value> // string literals
  85. {};
  86. template<typename Elem, std::size_t N, typename Char>
  87. struct width_of_terminal<Elem const (&) [N], Char, false>
  88. : mpl::size_t<N-is_char<Elem>::value> // string literals
  89. {};
  90. ///////////////////////////////////////////////////////////////////////////////
  91. // width_of
  92. //
  93. template<typename Expr, typename Char, typename Tag>
  94. struct width_of
  95. {};
  96. template<typename Expr, typename Char>
  97. struct width_of<Expr, Char, proto::tag::terminal>
  98. : width_of_terminal<typename proto::result_of::value<Expr>::type, Char>
  99. {};
  100. template<typename Expr, typename Char>
  101. struct width_of<Expr, Char, proto::tag::shift_right>
  102. : add_widths<
  103. width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>::value
  104. , width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value
  105. >
  106. {};
  107. template<typename Expr, typename Char>
  108. struct width_of<Expr, Char, proto::tag::bitwise_or>
  109. : or_widths<
  110. width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>::value
  111. , width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value
  112. >
  113. {};
  114. template<typename Expr, typename Char, typename Left>
  115. struct width_of_assign
  116. {};
  117. template<typename Expr, typename Char>
  118. struct width_of_assign<Expr, Char, mark_placeholder>
  119. : width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
  120. {};
  121. template<typename Expr, typename Char>
  122. struct width_of_assign<Expr, Char, set_initializer>
  123. : mpl::size_t<1>
  124. {};
  125. template<typename Expr, typename Char, typename Nbr>
  126. struct width_of_assign<Expr, Char, attribute_placeholder<Nbr> >
  127. : unknown_width
  128. {};
  129. // either (s1 = ...) or (a1 = ...) or (set = ...)
  130. template<typename Expr, typename Char>
  131. struct width_of<Expr, Char, proto::tag::assign>
  132. : width_of_assign<
  133. Expr
  134. , Char
  135. , typename proto::result_of::value<
  136. typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr
  137. >::type
  138. >
  139. {};
  140. template<typename Expr, typename Char>
  141. struct width_of<Expr, Char, modifier_tag>
  142. : width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>
  143. {};
  144. template<typename Expr, typename Char>
  145. struct width_of<Expr, Char, lookahead_tag>
  146. : mpl::size_t<0>
  147. {};
  148. template<typename Expr, typename Char>
  149. struct width_of<Expr, Char, lookbehind_tag>
  150. : mpl::size_t<0>
  151. {};
  152. // keep() is used to turn off backtracking, so they should only be used
  153. // for things that are variable-width (eg. quantified)
  154. template<typename Expr, typename Char>
  155. struct width_of<Expr, Char, keeper_tag>
  156. : unknown_width
  157. {
  158. // TODO: keep() now has a second meaning: execute actions immediately.
  159. // In that sense, it is perfectly reasonable to put a fixed-width
  160. // sub-expression in a keep. Can fixed-width keep() sub-expressions
  161. // use the simple_repeat_matcher?
  162. };
  163. template<typename Expr, typename Char>
  164. struct width_of<Expr, Char, proto::tag::unary_plus>
  165. : unknown_width
  166. {};
  167. template<typename Expr, typename Char>
  168. struct width_of<Expr, Char, proto::tag::dereference>
  169. : unknown_width
  170. {};
  171. template<typename Expr, typename Char>
  172. struct width_of<Expr, Char, proto::tag::logical_not>
  173. : unknown_width
  174. {};
  175. template<typename Expr, typename Char, uint_t Min, uint_t Max>
  176. struct width_of<Expr, Char, generic_quant_tag<Min, Max> >
  177. : unknown_width
  178. {};
  179. template<typename Expr, typename Char, uint_t Count>
  180. struct width_of<Expr, Char, generic_quant_tag<Count, Count> >
  181. : mpl::if_c<
  182. mpl::equal_to<unknown_width, width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char> >::value
  183. , unknown_width
  184. , mpl::times<
  185. width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
  186. , mpl::size_t<Count>
  187. >
  188. >::type
  189. {};
  190. template<typename Expr, typename Char>
  191. struct width_of<Expr, Char, proto::tag::negate>
  192. : width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
  193. {};
  194. // when complementing a set or an assertion, the width is that of the set (1) or the assertion (0)
  195. template<typename Expr, typename Char>
  196. struct width_of<Expr, Char, proto::tag::complement>
  197. : width_of<typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr, Char>
  198. {};
  199. // The comma is used in list-initialized sets, and the width of sets are 1
  200. template<typename Expr, typename Char>
  201. struct width_of<Expr, Char, proto::tag::comma>
  202. : mpl::size_t<1>
  203. {};
  204. // The subscript operator[] is used for sets, as in set['a' | range('b','h')],
  205. // or for actions as in (any >> expr)[ action ]
  206. template<typename Expr, typename Char, typename Left>
  207. struct width_of_subscript
  208. : width_of<Left, Char>
  209. {};
  210. template<typename Expr, typename Char>
  211. struct width_of_subscript<Expr, Char, set_initializer_type>
  212. : mpl::size_t<1>
  213. {
  214. // If Left is "set" then make sure that Right has a width_of 1
  215. BOOST_MPL_ASSERT_RELATION(
  216. 1
  217. , ==
  218. , (width_of<typename remove_reference<typename Expr::proto_child1>::type::proto_base_expr, Char>::value));
  219. };
  220. template<typename Expr, typename Char>
  221. struct width_of<Expr, Char, proto::tag::subscript>
  222. : width_of_subscript<Expr, Char, typename remove_reference<typename Expr::proto_child0>::type::proto_base_expr>
  223. {};
  224. }}} // namespace boost::xpressive::detail
  225. #undef UNREF
  226. #endif