Imported Upstream version 1.51.0
[platform/upstream/boost.git] / boost / xpressive / detail / static / width_of.hpp
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) && (_MSC_VER >= 1020)
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