1 ///////////////////////////////////////////////////////////////////////////////
2 // as_quantifier.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_TRANSFORMS_AS_QUANTIFIER_HPP_EAN_04_01_2007
9 #define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_QUANTIFIER_HPP_EAN_04_01_2007
10 
11 // MS compatible compilers support #pragma once
12 #if defined(_MSC_VER)
13 # pragma once
14 #endif
15 
16 #include <boost/mpl/assert.hpp>
17 #include <boost/type_traits/is_same.hpp>
18 #include <boost/xpressive/detail/detail_fwd.hpp>
19 #include <boost/xpressive/detail/static/static.hpp>
20 #include <boost/proto/core.hpp>
21 
22 namespace boost { namespace xpressive { namespace detail
23 {
24     ///////////////////////////////////////////////////////////////////////////////
25     // generic_quant_tag
26     template<uint_t Min, uint_t Max>
27     struct generic_quant_tag
28     {
29         typedef mpl::integral_c<uint_t, Min> min_type;
30         typedef mpl::integral_c<uint_t, Max> max_type;
31     };
32 }}}
33 
34 namespace boost { namespace xpressive { namespace grammar_detail
35 {
36     using detail::uint_t;
37 
38     ///////////////////////////////////////////////////////////////////////////////
39     // min_type / max_type
40     template<typename Tag>
41     struct min_type : Tag::min_type {};
42 
43     template<>
44     struct min_type<proto::tag::unary_plus> : mpl::integral_c<uint_t, 1> {};
45 
46     template<>
47     struct min_type<proto::tag::dereference> : mpl::integral_c<uint_t, 0> {};
48 
49     template<>
50     struct min_type<proto::tag::logical_not> : mpl::integral_c<uint_t, 0> {};
51 
52     template<typename Tag>
53     struct max_type : Tag::max_type {};
54 
55     template<>
56     struct max_type<proto::tag::unary_plus> : mpl::integral_c<uint_t, UINT_MAX-1> {};
57 
58     template<>
59     struct max_type<proto::tag::dereference> : mpl::integral_c<uint_t, UINT_MAX-1> {};
60 
61     template<>
62     struct max_type<proto::tag::logical_not> : mpl::integral_c<uint_t, 1> {};
63 
64     ///////////////////////////////////////////////////////////////////////////////
65     // as_simple_quantifier
66     template<typename Grammar, typename Greedy, typename Callable = proto::callable>
67     struct as_simple_quantifier : proto::transform<as_simple_quantifier<Grammar, Greedy, Callable> >
68     {
69         template<typename Expr, typename State, typename Data>
70         struct impl : proto::transform_impl<Expr, State, Data>
71         {
72             typedef
73                 typename proto::result_of::child<Expr>::type
74             arg_type;
75 
76             typedef
77                 typename Grammar::template impl<arg_type, detail::true_xpression, Data>::result_type
78             xpr_type;
79 
80             typedef
81                 detail::simple_repeat_matcher<xpr_type, Greedy>
82             matcher_type;
83 
84             typedef
85                 typename proto::terminal<matcher_type>::type
86             result_type;
87 
operator ()boost::xpressive::grammar_detail::as_simple_quantifier::impl88             result_type operator ()(
89                 typename impl::expr_param expr
90               , typename impl::state_param
91               , typename impl::data_param data
92             ) const
93             {
94                 xpr_type xpr = typename Grammar::template impl<arg_type, detail::true_xpression, Data>()(
95                     proto::child(expr)
96                   , detail::true_xpression()
97                   , data
98                 );
99 
100                 typedef typename impl::expr expr_type;
101                 matcher_type matcher(
102                     xpr
103                   , (uint_t)min_type<typename expr_type::proto_tag>::value
104                   , (uint_t)max_type<typename expr_type::proto_tag>::value
105                   , xpr.get_width().value()
106                 );
107 
108                 return result_type::make(matcher);
109             }
110         };
111     };
112 
113     ///////////////////////////////////////////////////////////////////////////////
114     // add_hidden_mark
115     struct add_hidden_mark : proto::transform<add_hidden_mark>
116     {
117         template<typename Expr, typename State, typename Data>
118         struct impl : proto::transform_impl<Expr, State, Data>
119         {
120             typedef typename impl::expr expr_type;
121             typedef
122                 typename shift_right<
123                     terminal<detail::mark_begin_matcher>::type
124                   , typename shift_right<
125                         Expr
126                       , terminal<detail::mark_end_matcher>::type
127                     >::type
128                 >::type
129             result_type;
130 
operator ()boost::xpressive::grammar_detail::add_hidden_mark::impl131             result_type operator ()(
132                 typename impl::expr_param expr
133               , typename impl::state_param
134               , typename impl::data_param data
135             ) const
136             {
137                 // we're inserting a hidden mark ... so grab the next hidden mark number.
138                 int mark_nbr = data.get_hidden_mark();
139                 detail::mark_begin_matcher begin(mark_nbr);
140                 detail::mark_end_matcher end(mark_nbr);
141 
142                 result_type that = {{begin}, {expr, {end}}};
143                 return that;
144             }
145         };
146     };
147 
148     ///////////////////////////////////////////////////////////////////////////////
149     // InsertMark
150     struct InsertMark
151       : or_<
152             when<proto::assign<detail::basic_mark_tag, _>, _>
153           , otherwise<add_hidden_mark>
154         >
155     {};
156 
157     ///////////////////////////////////////////////////////////////////////////////
158     // as_default_quantifier_impl
159     template<typename Greedy, uint_t Min, uint_t Max>
160     struct as_default_quantifier_impl : proto::transform<as_default_quantifier_impl<Greedy, Min, Max> >
161     {
162         template<typename Expr, typename State, typename Data>
163         struct impl : proto::transform_impl<Expr, State, Data>
164         {
165             typedef
166                 typename proto::result_of::child<Expr>::type
167             xpr_type;
168 
169             typedef
170                 typename InsertMark::impl<xpr_type, State, Data>::result_type
171             marked_sub_type;
172 
173             typedef
174                 typename shift_right<
175                     terminal<detail::repeat_begin_matcher>::type
176                   , typename shift_right<
177                         marked_sub_type
178                       , typename terminal<detail::repeat_end_matcher<Greedy> >::type
179                     >::type
180                 >::type
181             result_type;
182 
operator ()boost::xpressive::grammar_detail::as_default_quantifier_impl::impl183             result_type operator ()(
184                 typename impl::expr_param expr
185               , typename impl::state_param state
186               , typename impl::data_param data
187             ) const
188             {
189                 // Ensure this sub-expression is book-ended with mark matchers
190                 marked_sub_type marked_sub =
191                     InsertMark::impl<xpr_type, State, Data>()(proto::child(expr), state, data);
192 
193                 // Get the mark_number from the begin_mark_matcher
194                 int mark_number = proto::value(proto::left(marked_sub)).mark_number_;
195                 BOOST_ASSERT(0 != mark_number);
196 
197                 typedef typename impl::expr expr_type;
198                 uint_t min_ = (uint_t)min_type<typename expr_type::proto_tag>();
199                 uint_t max_ = (uint_t)max_type<typename expr_type::proto_tag>();
200 
201                 detail::repeat_begin_matcher begin(mark_number);
202                 detail::repeat_end_matcher<Greedy> end(mark_number, min_, max_);
203 
204                 result_type that = {{begin}, {marked_sub, {end}}};
205                 return that;
206             }
207         };
208     };
209 
210     ///////////////////////////////////////////////////////////////////////////////
211     // optional_tag
212     template<typename Greedy>
213     struct optional_tag
214     {};
215 
216     ///////////////////////////////////////////////////////////////////////////////
217     // as_default_optional
218     template<typename Grammar, typename Greedy, typename Callable = proto::callable>
219     struct as_default_optional : proto::transform<as_default_optional<Grammar, Greedy, Callable> >
220     {
221         template<typename Expr, typename State, typename Data>
222         struct impl : proto::transform_impl<Expr, State, Data>
223         {
224             typedef
225                 detail::alternate_end_xpression
226             end_xpr;
227 
228             typedef
229                 detail::optional_matcher<
230                     typename Grammar::template impl<Expr, end_xpr, Data>::result_type
231                   , Greedy
232                 >
233             result_type;
234 
operator ()boost::xpressive::grammar_detail::as_default_optional::impl235             result_type operator ()(
236                 typename impl::expr_param expr
237               , typename impl::state_param
238               , typename impl::data_param data
239             ) const
240             {
241                 return result_type(
242                     typename Grammar::template impl<Expr, end_xpr, Data>()(expr, end_xpr(), data)
243                 );
244             }
245         };
246     };
247 
248     ///////////////////////////////////////////////////////////////////////////////
249     // as_mark_optional
250     template<typename Grammar, typename Greedy, typename Callable = proto::callable>
251     struct as_mark_optional : proto::transform<as_mark_optional<Grammar, Greedy, Callable> >
252     {
253         template<typename Expr, typename State, typename Data>
254         struct impl : proto::transform_impl<Expr, State, Data>
255         {
256             typedef
257                 detail::alternate_end_xpression
258             end_xpr;
259 
260             typedef
261                 detail::optional_mark_matcher<
262                     typename Grammar::template impl<Expr, end_xpr, Data>::result_type
263                   , Greedy
264                 >
265             result_type;
266 
operator ()boost::xpressive::grammar_detail::as_mark_optional::impl267             result_type operator ()(
268                 typename impl::expr_param expr
269               , typename impl::state_param
270               , typename impl::data_param data
271             ) const
272             {
273                 int mark_number = proto::value(proto::left(expr)).mark_number_;
274 
275                 return result_type(
276                     typename Grammar::template impl<Expr, end_xpr, Data>()(expr, end_xpr(), data)
277                   , mark_number
278                 );
279             }
280         };
281     };
282 
283     ///////////////////////////////////////////////////////////////////////////////
284     // IsMarkerOrRepeater
285     struct IsMarkerOrRepeater
286       : or_<
287             shift_right<terminal<detail::repeat_begin_matcher>, _>
288           , assign<terminal<detail::mark_placeholder>, _>
289         >
290     {};
291 
292     ///////////////////////////////////////////////////////////////////////////////
293     // as_optional
294     template<typename Grammar, typename Greedy>
295     struct as_optional
296       : or_<
297             when<IsMarkerOrRepeater, as_mark_optional<Grammar, Greedy> >
298           , otherwise<as_default_optional<Grammar, Greedy> >
299         >
300     {};
301 
302     ///////////////////////////////////////////////////////////////////////////////
303     // make_optional_
304     template<typename Greedy, typename Callable = proto::callable>
305     struct make_optional_ : proto::transform<make_optional_<Greedy, Callable> >
306     {
307         template<typename Expr, typename State, typename Data>
308         struct impl : proto::transform_impl<Expr, State, Data>
309         {
310             typedef typename impl::expr expr_type;
311             typedef
312                 typename unary_expr<
313                     optional_tag<Greedy>
314                   , Expr
315                 >::type
316             result_type;
317 
operator ()boost::xpressive::grammar_detail::make_optional_::impl318             result_type operator ()(
319                 typename impl::expr_param expr
320               , typename impl::state_param
321               , typename impl::data_param
322             ) const
323             {
324                 result_type that = {expr};
325                 return that;
326             }
327         };
328     };
329 
330     ///////////////////////////////////////////////////////////////////////////////
331     // as_default_quantifier_impl
332     template<typename Greedy, uint_t Max>
333     struct as_default_quantifier_impl<Greedy, 0, Max>
334       : call<make_optional_<Greedy>(as_default_quantifier_impl<Greedy, 1, Max>)>
335     {};
336 
337     ///////////////////////////////////////////////////////////////////////////////
338     // as_default_quantifier_impl
339     template<typename Greedy>
340     struct as_default_quantifier_impl<Greedy, 0, 1>
341       : call<make_optional_<Greedy>(_child)>
342     {};
343 
344     ///////////////////////////////////////////////////////////////////////////////
345     // as_default_quantifier
346     template<typename Greedy, typename Callable = proto::callable>
347     struct as_default_quantifier : proto::transform<as_default_quantifier<Greedy, Callable> >
348     {
349         template<typename Expr, typename State, typename Data>
350         struct impl : proto::transform_impl<Expr, State, Data>
351         {
352             typedef typename impl::expr expr_type;
353             typedef
354                 as_default_quantifier_impl<
355                     Greedy
356                   , min_type<typename expr_type::proto_tag>::value
357                   , max_type<typename expr_type::proto_tag>::value
358                 >
359             other;
360 
361             typedef
362                 typename other::template impl<Expr, State, Data>::result_type
363             result_type;
364 
operator ()boost::xpressive::grammar_detail::as_default_quantifier::impl365             result_type operator ()(
366                 typename impl::expr_param expr
367               , typename impl::state_param state
368               , typename impl::data_param data
369             ) const
370             {
371                 return typename other::template impl<Expr, State, Data>()(expr, state, data);
372             }
373         };
374     };
375 
376 }}}
377 
378 #endif
379