]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |