1 ///////////////////////////////////////////////////////////////////////////////
2 // transmogrify.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_TRANSMOGRIFY_HPP_EAN_10_04_2005
9 #define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSMOGRIFY_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 <cstring> // for std::strlen
17 #include <boost/mpl/if.hpp>
18 #include <boost/mpl/or.hpp>
19 #include <boost/mpl/bool.hpp>
20 #include <boost/mpl/assert.hpp>
21 #include <boost/type_traits/is_same.hpp>
22 #include <boost/xpressive/detail/detail_fwd.hpp>
23 #include <boost/xpressive/detail/core/matchers.hpp>
24 #include <boost/xpressive/detail/static/placeholders.hpp>
25 #include <boost/xpressive/detail/utility/dont_care.hpp>
26 #include <boost/xpressive/detail/utility/traits_utils.hpp>
27 
28 namespace boost { namespace xpressive { namespace detail
29 {
30     template<typename T, typename Char>
31     struct is_char_literal
32       : mpl::or_<is_same<T, Char>, is_same<T, char> >
33     {};
34 
35     ///////////////////////////////////////////////////////////////////////////////
36     // transmogrify
37     //
38     template<typename BidiIter, typename ICase, typename Traits, typename Matcher, typename EnableIf = void>
39     struct default_transmogrify
40     {
41         typedef typename Traits::char_type char_type;
42         typedef typename Traits::string_type string_type;
43 
44         typedef typename mpl::if_c
45         <
46             is_char_literal<Matcher, char_type>::value
47           , literal_matcher<Traits, ICase, mpl::false_>
48           , string_matcher<Traits, ICase>
49         >::type type;
50 
51         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::default_transmogrify52         static type call(Matcher2 const &m, Visitor &visitor)
53         {
54             return default_transmogrify::call_(m, visitor, is_char_literal<Matcher2, char_type>());
55         }
56 
57         template<typename Matcher2, typename Visitor>
call_boost::xpressive::detail::default_transmogrify58         static type call_(Matcher2 const &m, Visitor &visitor, mpl::true_)
59         {
60             char_type ch = char_cast<char_type>(m, visitor.traits());
61             return type(ch, visitor.traits());
62         }
63 
64         template<typename Matcher2, typename Visitor>
call_boost::xpressive::detail::default_transmogrify65         static type call_(Matcher2 const &m, Visitor &visitor, mpl::false_)
66         {
67             string_type str = string_cast<string_type>(m, visitor.traits());
68             return type(str, visitor.traits());
69         }
70     };
71 
72     template<typename BidiIter, typename ICase, typename Traits, typename Matcher>
73     struct default_transmogrify<BidiIter, ICase, Traits, Matcher, typename Matcher::is_boost_xpressive_xpression_>
74     {
75         typedef Matcher type;
76 
77         template<typename Matcher2>
callboost::xpressive::detail::default_transmogrify78         static Matcher2 const &call(Matcher2 const &m, dont_care)
79         {
80             return m;
81         }
82     };
83 
84     template<typename BidiIter, typename ICase, typename Traits, typename Matcher>
85     struct transmogrify
86       : default_transmogrify<BidiIter, ICase, Traits, Matcher>
87     {};
88 
89     template<typename BidiIter, typename ICase, typename Traits>
90     struct transmogrify<BidiIter, ICase, Traits, assert_bol_placeholder >
91     {
92         typedef assert_bol_matcher<Traits> type;
93 
94         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::transmogrify95         static type call(Matcher2, Visitor &visitor)
96         {
97             return type(visitor.traits());
98         }
99     };
100 
101     template<typename BidiIter, typename ICase, typename Traits>
102     struct transmogrify<BidiIter, ICase, Traits, assert_eol_placeholder >
103     {
104         typedef assert_eol_matcher<Traits> type;
105 
106         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::transmogrify107         static type call(Matcher2, Visitor &visitor)
108         {
109             return type(visitor.traits());
110         }
111     };
112 
113     template<typename BidiIter, typename ICase, typename Traits>
114     struct transmogrify<BidiIter, ICase, Traits, logical_newline_placeholder >
115     {
116         typedef logical_newline_matcher<Traits> type;
117 
118         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::transmogrify119         static type call(Matcher2, Visitor &visitor)
120         {
121             return type(visitor.traits());
122         }
123     };
124 
125     template<typename BidiIter, typename ICase, typename Traits, typename Char>
126     struct transmogrify<BidiIter, ICase, Traits, range_placeholder<Char> >
127     {
128         // By design, we don't widen character ranges.
129         typedef typename iterator_value<BidiIter>::type char_type;
130         BOOST_MPL_ASSERT((is_same<Char, char_type>));
131         typedef range_matcher<Traits, ICase> type;
132 
133         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::transmogrify134         static type call(Matcher2 const &m, Visitor &visitor)
135         {
136             return type(m.ch_min_, m.ch_max_, m.not_, visitor.traits());
137         }
138     };
139 
140     template<typename BidiIter, typename ICase, typename Traits>
141     struct transmogrify<BidiIter, ICase, Traits, mark_placeholder >
142     {
143         typedef mark_matcher<Traits, ICase> type;
144 
145         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::transmogrify146         static type call(Matcher2 const &m, Visitor &visitor)
147         {
148             return type(m.mark_number_, visitor.traits());
149         }
150     };
151 
152     template<typename BidiIter, typename ICase, typename Traits>
153     struct transmogrify<BidiIter, ICase, Traits, posix_charset_placeholder >
154     {
155         typedef posix_charset_matcher<Traits> type;
156 
157         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::transmogrify158         static type call(Matcher2 const &m, Visitor &visitor)
159         {
160             char const *name_end = m.name_ + std::strlen(m.name_);
161             return type(visitor.traits().lookup_classname(m.name_, name_end, ICase::value), m.not_);
162         }
163     };
164 
165     template<typename BidiIter, typename Traits, typename Size>
166     struct transmogrify<BidiIter, mpl::true_, Traits, set_matcher<Traits, Size> >
167     {
168         typedef set_matcher<Traits, Size> type;
169 
170         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::transmogrify171         static type call(Matcher2 m, Visitor &visitor)
172         {
173             m.nocase(visitor.traits());
174             return m;
175         }
176     };
177 
178     template<typename BidiIter, typename ICase, typename Traits, typename Cond>
179     struct transmogrify<BidiIter, ICase, Traits, assert_word_placeholder<Cond> >
180     {
181         typedef assert_word_matcher<Cond, Traits> type;
182 
183         template<typename Visitor>
callboost::xpressive::detail::transmogrify184         static type call(dont_care, Visitor &visitor)
185         {
186             return type(visitor.traits());
187         }
188     };
189 
190     template<typename BidiIter, typename ICase, typename Traits>
191     struct transmogrify<BidiIter, ICase, Traits, reference_wrapper<basic_regex<BidiIter> > >
192     {
193         typedef regex_byref_matcher<BidiIter> type;
194 
195         template<typename Matcher2>
callboost::xpressive::detail::transmogrify196         static type call(Matcher2 const &m, dont_care)
197         {
198             return type(detail::core_access<BidiIter>::get_regex_impl(m.get()));
199         }
200     };
201 
202     template<typename BidiIter, typename ICase, typename Traits>
203     struct transmogrify<BidiIter, ICase, Traits, reference_wrapper<basic_regex<BidiIter> const> >
204     {
205         typedef regex_byref_matcher<BidiIter> type;
206 
207         template<typename Matcher2>
callboost::xpressive::detail::transmogrify208         static type call(Matcher2 const &m, dont_care)
209         {
210             return type(detail::core_access<BidiIter>::get_regex_impl(m.get()));
211         }
212     };
213 
214     template<typename BidiIter, typename ICase, typename Traits>
215     struct transmogrify<BidiIter, ICase, Traits, tracking_ptr<regex_impl<BidiIter> > >
216     {
217         typedef regex_matcher<BidiIter> type;
218 
219         template<typename Matcher2>
callboost::xpressive::detail::transmogrify220         static type call(Matcher2 const &m, dont_care)
221         {
222             return type(m.get());
223         }
224     };
225 
226     template<typename BidiIter, typename ICase, typename Traits>
227     struct transmogrify<BidiIter, ICase, Traits, self_placeholder >
228     {
229         typedef regex_byref_matcher<BidiIter> type;
230 
231         template<typename Matcher2, typename Visitor>
callboost::xpressive::detail::transmogrify232         static type call(Matcher2, Visitor &visitor)
233         {
234             return type(visitor.self());
235         }
236     };
237 
238 }}}
239 
240 #endif
241