]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // as_set.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_SET_HPP_EAN_04_05_2007 | |
9 | #define BOOST_XPRESSIVE_DETAIL_STATIC_TRANSFORMS_AS_SET_HPP_EAN_04_05_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/proto/core.hpp> | |
18 | #include <boost/xpressive/detail/detail_fwd.hpp> | |
19 | #include <boost/xpressive/detail/static/static.hpp> | |
20 | #include <boost/xpressive/detail/utility/chset/chset.hpp> | |
21 | #include <boost/xpressive/detail/utility/traits_utils.hpp> | |
22 | ||
23 | namespace boost { namespace xpressive { namespace grammar_detail | |
24 | { | |
25 | ||
26 | /////////////////////////////////////////////////////////////////////////// | |
27 | // CharLiteral | |
28 | template<typename Char> | |
29 | struct CharLiteral | |
30 | : or_< | |
31 | terminal<char> | |
32 | , terminal<Char> | |
33 | > | |
34 | {}; | |
35 | ||
36 | template<> | |
37 | struct CharLiteral<char> | |
38 | : terminal<char> | |
39 | {}; | |
40 | ||
41 | /////////////////////////////////////////////////////////////////////////// | |
42 | // ListSet | |
43 | // matches expressions like (set= 'a','b','c') | |
44 | // calculates the size of the set | |
45 | template<typename Char> | |
46 | struct ListSet | |
47 | : or_< | |
48 | when< | |
49 | comma<ListSet<Char>, CharLiteral<Char> > | |
50 | , make<mpl::next<call<ListSet<Char>(_left)> > > // TODO make a custom transform for this... | |
51 | > | |
52 | , when< | |
53 | assign<detail::set_initializer_type, CharLiteral<Char> > | |
54 | , make<mpl::int_<1> > | |
55 | > | |
56 | > | |
57 | {}; | |
58 | ||
59 | template<typename Char, typename Traits> | |
60 | void fill_list_set(Char *&, detail::set_initializer_type, Traits const &) | |
61 | {} | |
62 | ||
63 | template<typename Char, typename Expr, typename Traits> | |
64 | void fill_list_set(Char *&buffer, Expr const &expr, Traits const &traits) | |
65 | { | |
66 | fill_list_set(buffer, proto::left(expr), traits); | |
67 | *buffer++ = traits.translate(detail::char_cast<Char>(proto::value(proto::right(expr)), traits)); | |
68 | } | |
69 | ||
70 | /////////////////////////////////////////////////////////////////////////////// | |
71 | // as_list_set_matcher | |
72 | template<typename Char, typename Callable = proto::callable> | |
73 | struct as_list_set_matcher : proto::transform<as_list_set_matcher<Char, Callable> > | |
74 | { | |
75 | template<typename Expr, typename State, typename Data> | |
76 | struct impl : proto::transform_impl<Expr, State, Data> | |
77 | { | |
78 | typedef typename impl::data data_type; | |
79 | typedef | |
80 | detail::set_matcher< | |
81 | typename data_type::traits_type | |
82 | , typename ListSet<Char>::template impl<Expr, State, Data>::result_type | |
83 | > | |
84 | result_type; | |
85 | ||
86 | result_type operator ()( | |
87 | typename impl::expr_param expr | |
88 | , typename impl::state_param | |
89 | , typename impl::data_param data | |
90 | ) const | |
91 | { | |
92 | result_type set; | |
93 | typedef typename impl::data data_type; | |
94 | typename data_type::char_type *buffer = set.set_; | |
95 | fill_list_set(buffer, expr, data.traits()); | |
96 | return set; | |
97 | } | |
98 | }; | |
99 | }; | |
100 | ||
101 | /////////////////////////////////////////////////////////////////////////////// | |
102 | // merge_charset | |
103 | // | |
104 | template<typename Grammar, typename CharSet, typename Data> | |
105 | struct merge_charset | |
106 | { | |
107 | typedef typename Data::traits_type traits_type; | |
108 | typedef typename CharSet::char_type char_type; | |
109 | typedef typename CharSet::icase_type icase_type; | |
110 | ||
111 | merge_charset(CharSet &charset, Data &data) | |
112 | : charset_(charset) | |
113 | , visitor_(data) | |
114 | {} | |
115 | ||
116 | template<typename Expr> | |
117 | void operator ()(Expr const &expr) const | |
118 | { | |
119 | this->call_(expr, typename Expr::proto_tag()); | |
120 | } | |
121 | ||
122 | private: | |
123 | merge_charset &operator =(merge_charset const &); | |
124 | ||
125 | template<typename Expr, typename Tag> | |
126 | void call_(Expr const &expr, Tag) const | |
127 | { | |
128 | this->set_( | |
129 | typename Grammar::template impl<Expr const &, detail::end_xpression, Data &>()( | |
130 | expr | |
131 | , detail::end_xpression() | |
132 | , this->visitor_ | |
133 | ) | |
134 | ); | |
135 | } | |
136 | ||
137 | template<typename Expr> | |
138 | void call_(Expr const &expr, tag::bitwise_or) const | |
139 | { | |
140 | (*this)(proto::left(expr)); | |
141 | (*this)(proto::right(expr)); | |
142 | } | |
143 | ||
144 | template<typename Not> | |
145 | void set_(detail::literal_matcher<traits_type, icase_type, Not> const &ch) const | |
146 | { | |
147 | // BUGBUG fixme! | |
148 | BOOST_MPL_ASSERT_NOT((Not)); | |
149 | set_char(this->charset_.charset_, ch.ch_, this->visitor_.traits(), icase_type()); | |
150 | } | |
151 | ||
152 | void set_(detail::range_matcher<traits_type, icase_type> const &rg) const | |
153 | { | |
154 | // BUGBUG fixme! | |
155 | BOOST_ASSERT(!rg.not_); | |
156 | set_range(this->charset_.charset_, rg.ch_min_, rg.ch_max_, this->visitor_.traits(), icase_type()); | |
157 | } | |
158 | ||
159 | template<typename Size> | |
160 | void set_(detail::set_matcher<traits_type, Size> const &set_) const | |
161 | { | |
162 | // BUGBUG fixme! | |
163 | BOOST_ASSERT(!set_.not_); | |
164 | for(int i = 0; i < Size::value; ++i) | |
165 | { | |
166 | set_char(this->charset_.charset_, set_.set_[i], this->visitor_.traits(), icase_type()); | |
167 | } | |
168 | } | |
169 | ||
170 | void set_(detail::posix_charset_matcher<traits_type> const &posix) const | |
171 | { | |
172 | set_class(this->charset_.charset_, posix.mask_, posix.not_, this->visitor_.traits()); | |
173 | } | |
174 | ||
175 | CharSet &charset_; | |
176 | Data &visitor_; | |
177 | }; | |
178 | ||
179 | /////////////////////////////////////////////////////////////////////////////// | |
180 | // | |
181 | template<typename Grammar, typename Callable = proto::callable> | |
182 | struct as_set_matcher : proto::transform<as_set_matcher<Grammar, Callable> > | |
183 | { | |
184 | template<typename Expr, typename State, typename Data> | |
185 | struct impl : proto::transform_impl<Expr, State, Data> | |
186 | { | |
187 | typedef typename impl::data data_type; | |
188 | typedef typename data_type::char_type char_type; | |
189 | ||
190 | // if sizeof(char_type)==1, merge everything into a basic_chset | |
191 | // BUGBUG this is not optimal. | |
192 | typedef | |
193 | typename mpl::if_c< | |
194 | detail::is_narrow_char<char_type>::value | |
195 | , detail::basic_chset<char_type> | |
196 | , detail::compound_charset<typename data_type::traits_type> | |
197 | >::type | |
198 | charset_type; | |
199 | ||
200 | typedef | |
201 | detail::charset_matcher< | |
202 | typename data_type::traits_type | |
203 | , typename data_type::icase_type | |
204 | , charset_type | |
205 | > | |
206 | result_type; | |
207 | ||
208 | result_type operator ()( | |
209 | typename impl::expr_param expr | |
210 | , typename impl::state_param | |
211 | , typename impl::data_param data | |
212 | ) const | |
213 | { | |
214 | result_type matcher; | |
215 | merge_charset<Grammar, result_type, typename impl::data> merge(matcher, data); | |
216 | merge(expr); // Walks the tree and fills in the charset | |
217 | return matcher; | |
218 | } | |
219 | }; | |
220 | }; | |
221 | ||
222 | }}} | |
223 | ||
224 | #endif |