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