]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // peeker.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_CORE_PEEKER_HPP_EAN_10_04_2005 | |
9 | #define BOOST_XPRESSIVE_DETAIL_CORE_PEEKER_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 <string> | |
17 | #include <typeinfo> | |
18 | #include <boost/assert.hpp> | |
19 | #include <boost/mpl/bool.hpp> | |
20 | #include <boost/mpl/assert.hpp> | |
21 | #include <boost/mpl/size_t.hpp> | |
22 | #include <boost/mpl/equal_to.hpp> | |
23 | #include <boost/utility/enable_if.hpp> | |
24 | #include <boost/xpressive/detail/detail_fwd.hpp> | |
25 | #include <boost/xpressive/detail/core/matchers.hpp> | |
26 | #include <boost/xpressive/detail/utility/hash_peek_bitset.hpp> | |
27 | #include <boost/xpressive/detail/utility/never_true.hpp> | |
28 | #include <boost/xpressive/detail/utility/algorithm.hpp> | |
29 | ||
30 | namespace boost { namespace xpressive { namespace detail | |
31 | { | |
32 | ||
33 | /////////////////////////////////////////////////////////////////////////////// | |
34 | // peeker_string | |
35 | // | |
36 | template<typename Char> | |
37 | struct peeker_string | |
38 | { | |
39 | Char const *begin_; | |
40 | Char const *end_; | |
41 | bool icase_; | |
42 | }; | |
43 | ||
44 | /////////////////////////////////////////////////////////////////////////////// | |
45 | // char_sink | |
46 | // | |
47 | template<typename Traits, bool ICase> | |
48 | struct char_sink | |
49 | { | |
50 | typedef typename Traits::char_type char_type; | |
51 | ||
52 | char_sink(hash_peek_bitset<char_type> &bset, Traits const &tr) | |
53 | : bset_(bset) | |
54 | , traits_(tr) | |
55 | {} | |
56 | ||
57 | void operator()(char_type ch) const | |
58 | { | |
59 | this->bset_.set_char(ch, ICase, this->traits_); | |
60 | } | |
61 | ||
62 | hash_peek_bitset<char_type> &bset_; | |
63 | Traits const &traits_; | |
64 | private: | |
65 | char_sink &operator =(char_sink const &); | |
66 | }; | |
67 | ||
68 | /////////////////////////////////////////////////////////////////////////////// | |
69 | // xpression_peeker | |
70 | // | |
71 | template<typename Char> | |
72 | struct xpression_peeker | |
73 | { | |
74 | template<typename Traits> | |
75 | xpression_peeker(hash_peek_bitset<Char> &bset, Traits const &tr, bool has_backrefs = false) | |
76 | : bset_(bset) | |
77 | , str_() | |
78 | , line_start_(false) | |
79 | , traits_(0) | |
80 | , traits_type_(0) | |
81 | , leading_simple_repeat_(0) | |
82 | , has_backrefs_(has_backrefs) | |
83 | { | |
84 | this->set_traits(tr); | |
85 | } | |
86 | ||
87 | /////////////////////////////////////////////////////////////////////////////// | |
88 | // accessors | |
89 | peeker_string<Char> const &get_string() const | |
90 | { | |
91 | return this->str_; | |
92 | } | |
93 | ||
94 | bool line_start() const | |
95 | { | |
96 | return this->line_start_; | |
97 | } | |
98 | ||
99 | bool leading_simple_repeat() const | |
100 | { | |
101 | return 0 < this->leading_simple_repeat_; | |
102 | } | |
103 | ||
104 | hash_peek_bitset<Char> const &bitset() const | |
105 | { | |
106 | return this->bset_; | |
107 | } | |
108 | ||
109 | /////////////////////////////////////////////////////////////////////////////// | |
110 | // modifiers | |
111 | void fail() | |
112 | { | |
113 | this->bset_.set_all(); | |
114 | } | |
115 | ||
116 | template<typename Matcher> | |
117 | mpl::false_ accept(Matcher const &) | |
118 | { | |
119 | this->fail(); | |
120 | return mpl::false_(); | |
121 | } | |
122 | ||
123 | mpl::true_ accept(mark_begin_matcher const &) | |
124 | { | |
125 | if(this->has_backrefs_) | |
126 | { | |
127 | --this->leading_simple_repeat_; | |
128 | } | |
129 | return mpl::true_(); | |
130 | } | |
131 | ||
132 | mpl::true_ accept(repeat_begin_matcher const &) | |
133 | { | |
134 | --this->leading_simple_repeat_; | |
135 | return mpl::true_(); | |
136 | } | |
137 | ||
138 | template<typename Traits> | |
139 | mpl::true_ accept(assert_bol_matcher<Traits> const &) | |
140 | { | |
141 | this->line_start_ = true; | |
142 | return mpl::true_(); | |
143 | } | |
144 | ||
145 | template<typename Traits, typename ICase> | |
146 | mpl::false_ accept(literal_matcher<Traits, ICase, mpl::false_> const &xpr) | |
147 | { | |
148 | this->bset_.set_char(xpr.ch_, ICase(), this->get_traits_<Traits>()); | |
149 | return mpl::false_(); | |
150 | } | |
151 | ||
152 | template<typename Traits, typename ICase> | |
153 | mpl::false_ accept(string_matcher<Traits, ICase> const &xpr) | |
154 | { | |
155 | this->bset_.set_char(xpr.str_[0], ICase(), this->get_traits_<Traits>()); | |
156 | this->str_.begin_ = detail::data_begin(xpr.str_); | |
157 | this->str_.end_ = detail::data_end(xpr.str_); | |
158 | this->str_.icase_ = ICase::value; | |
159 | return mpl::false_(); | |
160 | } | |
161 | ||
162 | template<typename Alternates, typename Traits> | |
163 | mpl::false_ accept(alternate_matcher<Alternates, Traits> const &xpr) | |
164 | { | |
165 | BOOST_ASSERT(0 != xpr.bset_.count()); | |
166 | this->bset_.set_bitset(xpr.bset_); | |
167 | return mpl::false_(); | |
168 | } | |
169 | ||
170 | template<typename Matcher, typename Traits, typename ICase> | |
171 | mpl::false_ accept(attr_matcher<Matcher, Traits, ICase> const &xpr) | |
172 | { | |
173 | xpr.sym_.peek(char_sink<Traits, ICase::value>(this->bset_, this->get_traits_<Traits>())); | |
174 | return mpl::false_(); | |
175 | } | |
176 | ||
177 | template<typename Xpr, typename Greedy> | |
178 | mpl::false_ accept(optional_matcher<Xpr, Greedy> const &) | |
179 | { | |
180 | this->fail(); // a union of xpr and next | |
181 | return mpl::false_(); | |
182 | } | |
183 | ||
184 | template<typename Xpr, typename Greedy> | |
185 | mpl::false_ accept(optional_mark_matcher<Xpr, Greedy> const &) | |
186 | { | |
187 | this->fail(); // a union of xpr and next | |
188 | return mpl::false_(); | |
189 | } | |
190 | ||
191 | //template<typename Xpr, typename Greedy> | |
192 | //mpl::true_ accept(optional_matcher<Xpr, Greedy> const &xpr) | |
193 | //{ | |
194 | // xpr.xpr_.peek(*this); // a union of xpr and next | |
195 | // return mpl::true_(); | |
196 | //} | |
197 | ||
198 | //template<typename Xpr, typename Greedy> | |
199 | //mpl::true_ accept(optional_mark_matcher<Xpr, Greedy> const &xpr) | |
200 | //{ | |
201 | // xpr.xpr_.peek(*this); // a union of xpr and next | |
202 | // return mpl::true_(); | |
203 | //} | |
204 | ||
205 | template<typename Traits> | |
206 | mpl::false_ accept(posix_charset_matcher<Traits> const &xpr) | |
207 | { | |
208 | this->bset_.set_class(xpr.mask_, xpr.not_, this->get_traits_<Traits>()); | |
209 | return mpl::false_(); | |
210 | } | |
211 | ||
212 | template<typename ICase, typename Traits> | |
213 | typename enable_if<is_narrow_char<typename Traits::char_type>, mpl::false_>::type | |
214 | accept(charset_matcher<Traits, ICase, basic_chset<Char> > const &xpr) | |
215 | { | |
216 | BOOST_ASSERT(0 != xpr.charset_.base().count()); | |
217 | this->bset_.set_charset(xpr.charset_, ICase()); | |
218 | return mpl::false_(); | |
219 | } | |
220 | ||
221 | template<typename Traits, typename ICase> | |
222 | mpl::false_ accept(range_matcher<Traits, ICase> const &xpr) | |
223 | { | |
224 | this->bset_.set_range(xpr.ch_min_, xpr.ch_max_, xpr.not_, ICase(), this->get_traits_<Traits>()); | |
225 | return mpl::false_(); | |
226 | } | |
227 | ||
228 | template<typename Xpr, typename Greedy> | |
229 | mpl::false_ accept(simple_repeat_matcher<Xpr, Greedy> const &xpr) | |
230 | { | |
231 | if(Greedy() && 1U == xpr.width_) | |
232 | { | |
233 | ++this->leading_simple_repeat_; | |
234 | xpr.leading_ = this->leading_simple_repeat(); | |
235 | } | |
236 | 0 != xpr.min_ ? xpr.xpr_.peek(*this) : this->fail(); // could be a union of xpr and next | |
237 | return mpl::false_(); | |
238 | } | |
239 | ||
240 | template<typename Xpr> | |
241 | mpl::false_ accept(keeper_matcher<Xpr> const &xpr) | |
242 | { | |
243 | xpr.xpr_.peek(*this); | |
244 | return mpl::false_(); | |
245 | } | |
246 | ||
247 | template<typename Traits> | |
248 | void set_traits(Traits const &tr) | |
249 | { | |
250 | if(0 == this->traits_) | |
251 | { | |
252 | this->traits_ = &tr; | |
253 | this->traits_type_ = &typeid(Traits); | |
254 | } | |
255 | else if(*this->traits_type_ != typeid(Traits) || this->get_traits_<Traits>() != tr) | |
256 | { | |
257 | this->fail(); // traits mis-match! set all and bail | |
258 | } | |
259 | } | |
260 | ||
261 | private: | |
262 | xpression_peeker(xpression_peeker const &); | |
263 | xpression_peeker &operator =(xpression_peeker const &); | |
264 | ||
265 | template<typename Traits> | |
266 | Traits const &get_traits_() const | |
267 | { | |
268 | BOOST_ASSERT(!!(*this->traits_type_ == typeid(Traits))); | |
269 | return *static_cast<Traits const *>(this->traits_); | |
270 | } | |
271 | ||
272 | hash_peek_bitset<Char> &bset_; | |
273 | peeker_string<Char> str_; | |
274 | bool str_icase_; | |
275 | bool line_start_; | |
276 | void const *traits_; | |
277 | std::type_info const *traits_type_; | |
278 | int leading_simple_repeat_; | |
279 | bool has_backrefs_; | |
280 | }; | |
281 | ||
282 | }}} // namespace boost::xpressive::detail | |
283 | ||
284 | #endif |