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