1 | /////////////////////////////////////////////////////////////////////////////// |
---|
2 | // static.hpp |
---|
3 | // |
---|
4 | // Copyright 2004 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_STATIC_HPP_EAN_10_04_2005 |
---|
9 | #define BOOST_XPRESSIVE_DETAIL_STATIC_STATIC_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/mpl/assert.hpp> |
---|
17 | #include <boost/xpressive/detail/detail_fwd.hpp> |
---|
18 | #include <boost/xpressive/detail/core/state.hpp> |
---|
19 | #include <boost/xpressive/detail/core/linker.hpp> |
---|
20 | #include <boost/xpressive/detail/core/peeker.hpp> |
---|
21 | |
---|
22 | // Random thoughts: |
---|
23 | // - must support indirect repeat counts {$n,$m} |
---|
24 | // - add ws to eat whitespace (make *ws illegal) |
---|
25 | // - a{n,m} -> repeat<n,m>(a) |
---|
26 | // - a{$n,$m} -> repeat(n,m)(a) |
---|
27 | // - add nil to match nothing |
---|
28 | // - instead of s1, s2, etc., how about s[1], s[2], etc.? Needlessly verbose? |
---|
29 | |
---|
30 | namespace boost { namespace xpressive { namespace detail |
---|
31 | { |
---|
32 | |
---|
33 | #ifdef BOOST_XPR_DEBUG_STACK |
---|
34 | /////////////////////////////////////////////////////////////////////////////// |
---|
35 | // top_type |
---|
36 | // |
---|
37 | template<typename Top> |
---|
38 | struct top_type |
---|
39 | { |
---|
40 | typedef Top type; |
---|
41 | }; |
---|
42 | |
---|
43 | /////////////////////////////////////////////////////////////////////////////// |
---|
44 | // top_type |
---|
45 | // |
---|
46 | template<typename Top, typename Next> |
---|
47 | struct top_type<stacked_xpression<Top, Next> > |
---|
48 | { |
---|
49 | typedef Next type; |
---|
50 | }; |
---|
51 | #endif |
---|
52 | |
---|
53 | /////////////////////////////////////////////////////////////////////////////// |
---|
54 | // stacked_xpression |
---|
55 | // |
---|
56 | template<typename Top, typename Next> |
---|
57 | struct stacked_xpression |
---|
58 | : Next |
---|
59 | { |
---|
60 | // match |
---|
61 | // delegates to Next |
---|
62 | template<typename BidiIter> |
---|
63 | bool match(state_type<BidiIter> &state) const |
---|
64 | { |
---|
65 | return static_cast<Next const *>(this)-> |
---|
66 | BOOST_NESTED_TEMPLATE push_match<Top>(state); |
---|
67 | } |
---|
68 | |
---|
69 | // top_match |
---|
70 | // jump back to the xpression on top of the xpression stack, |
---|
71 | // and keep the xpression on the stack. |
---|
72 | template<typename BidiIter> |
---|
73 | static bool top_match(state_type<BidiIter> &state, xpression_base const *top) |
---|
74 | { |
---|
75 | BOOST_XPR_DEBUG_STACK_ASSERT(typeid(*top) == typeid(typename top_type<Top>::type)); |
---|
76 | return static_cast<Top const *>(top)-> |
---|
77 | BOOST_NESTED_TEMPLATE push_match<Top>(state); |
---|
78 | } |
---|
79 | |
---|
80 | // pop_match |
---|
81 | // jump back to the xpression on top of the xpression stack, |
---|
82 | // pop the xpression off the stack. |
---|
83 | template<typename BidiIter> |
---|
84 | static bool pop_match(state_type<BidiIter> &state, xpression_base const *top) |
---|
85 | { |
---|
86 | BOOST_XPR_DEBUG_STACK_ASSERT(typeid(*top) == typeid(typename top_type<Top>::type)); |
---|
87 | return static_cast<Top const *>(top)->match(state); |
---|
88 | } |
---|
89 | |
---|
90 | // skip_match |
---|
91 | // pop the xpression off the top of the stack and ignore it; call |
---|
92 | // match on next. |
---|
93 | template<typename BidiIter> |
---|
94 | bool skip_match(state_type<BidiIter> &state) const |
---|
95 | { |
---|
96 | // could be static_xpression::skip_impl or stacked_xpression::skip_impl |
---|
97 | // depending on if there is 1 or more than 1 xpression on the |
---|
98 | // xpression stack |
---|
99 | return Top::skip_impl(*static_cast<Next const *>(this), state); |
---|
100 | } |
---|
101 | |
---|
102 | //protected: |
---|
103 | |
---|
104 | // skip_impl |
---|
105 | // implementation of skip_match. |
---|
106 | template<typename That, typename BidiIter> |
---|
107 | static bool skip_impl(That const &that, state_type<BidiIter> &state) |
---|
108 | { |
---|
109 | return that.BOOST_NESTED_TEMPLATE push_match<Top>(state); |
---|
110 | } |
---|
111 | }; |
---|
112 | |
---|
113 | /////////////////////////////////////////////////////////////////////////////// |
---|
114 | // stacked_xpression_cast |
---|
115 | // |
---|
116 | template<typename Top, typename Next> |
---|
117 | inline stacked_xpression<Top, Next> const &stacked_xpression_cast(Next const &next) |
---|
118 | { |
---|
119 | // NOTE: this is a little white lie. The "next" object doesn't really have |
---|
120 | // the type to which we're casting it. It is harmless, though. We are only using |
---|
121 | // the cast to decorate the next object with type information. It is done |
---|
122 | // this way to save stack space. |
---|
123 | BOOST_MPL_ASSERT_RELATION(sizeof(stacked_xpression<Top, Next>), ==, sizeof(Next)); |
---|
124 | return *static_cast<stacked_xpression<Top, Next> const *>(&next); |
---|
125 | } |
---|
126 | |
---|
127 | /////////////////////////////////////////////////////////////////////////////// |
---|
128 | // static_xpression |
---|
129 | // |
---|
130 | template<typename Matcher, typename Next> |
---|
131 | struct static_xpression |
---|
132 | : Matcher |
---|
133 | { |
---|
134 | Next next_; |
---|
135 | |
---|
136 | static_xpression(Matcher const &matcher = Matcher(), Next const &next = Next()) |
---|
137 | : Matcher(matcher) |
---|
138 | , next_(next) |
---|
139 | { |
---|
140 | } |
---|
141 | |
---|
142 | // match |
---|
143 | // delegates to the Matcher |
---|
144 | template<typename BidiIter> |
---|
145 | bool match(state_type<BidiIter> &state) const |
---|
146 | { |
---|
147 | return this->Matcher::match(state, this->next_); |
---|
148 | } |
---|
149 | |
---|
150 | // push_match |
---|
151 | // call match on this, but also push "Top" onto the xpression |
---|
152 | // stack so we know what we are jumping back to later. |
---|
153 | template<typename Top, typename BidiIter> |
---|
154 | bool push_match(state_type<BidiIter> &state) const |
---|
155 | { |
---|
156 | return this->Matcher::match(state, stacked_xpression_cast<Top>(this->next_)); |
---|
157 | } |
---|
158 | |
---|
159 | // skip_impl |
---|
160 | // implementation of skip_match, called from stacked_xpression::skip_match |
---|
161 | template<typename That, typename BidiIter> |
---|
162 | static bool skip_impl(That const &that, state_type<BidiIter> &state) |
---|
163 | { |
---|
164 | return that.match(state); |
---|
165 | } |
---|
166 | |
---|
167 | // for linking a compiled regular xpression |
---|
168 | template<typename Char> |
---|
169 | void link(xpression_linker<Char> &linker) const |
---|
170 | { |
---|
171 | linker.link(*static_cast<Matcher const *>(this), &this->next_); |
---|
172 | this->next_.link(linker); |
---|
173 | } |
---|
174 | |
---|
175 | // for building a lead-follow |
---|
176 | template<typename Char> |
---|
177 | void peek(xpression_peeker<Char> &peeker) const |
---|
178 | { |
---|
179 | this->peek_next_(peeker.peek(*static_cast<Matcher const *>(this)), peeker); |
---|
180 | } |
---|
181 | |
---|
182 | // for getting xpression width |
---|
183 | template<typename BidiIter> |
---|
184 | std::size_t get_width(state_type<BidiIter> *state) const |
---|
185 | { |
---|
186 | // BUGBUG this gets called from the simple_repeat_matcher::match(), so this is slow. |
---|
187 | // or will the compiler be able to optimize this all away? |
---|
188 | std::size_t this_width = this->Matcher::get_width(state); |
---|
189 | if(this_width == unknown_width()) |
---|
190 | return unknown_width(); |
---|
191 | std::size_t that_width = this->next_.get_width(state); |
---|
192 | if(that_width == unknown_width()) |
---|
193 | return unknown_width(); |
---|
194 | return this_width + that_width; |
---|
195 | } |
---|
196 | |
---|
197 | private: // hide this |
---|
198 | |
---|
199 | static_xpression &operator =(static_xpression const &); |
---|
200 | |
---|
201 | template<typename Char> |
---|
202 | void peek_next_(mpl::true_, xpression_peeker<Char> &peeker) const |
---|
203 | { |
---|
204 | this->next_.peek(peeker); |
---|
205 | } |
---|
206 | |
---|
207 | template<typename Char> |
---|
208 | static void peek_next_(mpl::false_, xpression_peeker<Char> &) |
---|
209 | { |
---|
210 | // no-op |
---|
211 | } |
---|
212 | |
---|
213 | using Matcher::width; |
---|
214 | using Matcher::pure; |
---|
215 | }; |
---|
216 | |
---|
217 | // syntactic sugar so this xpression can be treated the same as |
---|
218 | // (a smart pointer to) a dynamic xpression from templates |
---|
219 | template<typename Matcher, typename Next> |
---|
220 | inline static_xpression<Matcher, Next> const * |
---|
221 | get_pointer(static_xpression<Matcher, Next> const &xpr) |
---|
222 | { |
---|
223 | return &xpr; |
---|
224 | } |
---|
225 | |
---|
226 | /////////////////////////////////////////////////////////////////////////////// |
---|
227 | // make_static_xpression |
---|
228 | // |
---|
229 | template<typename Matcher> |
---|
230 | inline static_xpression<Matcher> const |
---|
231 | make_static_xpression(Matcher const &matcher) |
---|
232 | { |
---|
233 | return static_xpression<Matcher>(matcher); |
---|
234 | } |
---|
235 | |
---|
236 | template<typename Matcher, typename Next> |
---|
237 | inline static_xpression<Matcher, Next> const |
---|
238 | make_static_xpression(Matcher const &matcher, Next const &next) |
---|
239 | { |
---|
240 | return static_xpression<Matcher, Next>(matcher, next); |
---|
241 | } |
---|
242 | |
---|
243 | /////////////////////////////////////////////////////////////////////////////// |
---|
244 | // no_next |
---|
245 | // |
---|
246 | struct no_next |
---|
247 | : xpression_base |
---|
248 | { |
---|
249 | template<typename Char> |
---|
250 | void link(xpression_linker<Char> &) const |
---|
251 | { |
---|
252 | } |
---|
253 | |
---|
254 | template<typename Char> |
---|
255 | void peek(xpression_peeker<Char> &peeker) const |
---|
256 | { |
---|
257 | peeker.fail(); |
---|
258 | } |
---|
259 | |
---|
260 | template<typename BidiIter> |
---|
261 | static std::size_t get_width(state_type<BidiIter> *) |
---|
262 | { |
---|
263 | return 0; |
---|
264 | } |
---|
265 | }; |
---|
266 | |
---|
267 | /////////////////////////////////////////////////////////////////////////////// |
---|
268 | // alternates_list |
---|
269 | // |
---|
270 | template<typename Alternates> |
---|
271 | struct alternates_list |
---|
272 | : Alternates |
---|
273 | { |
---|
274 | alternates_list(Alternates const &alternates) |
---|
275 | : Alternates(alternates) |
---|
276 | { |
---|
277 | } |
---|
278 | private: |
---|
279 | alternates_list &operator =(alternates_list const &); |
---|
280 | }; |
---|
281 | |
---|
282 | /////////////////////////////////////////////////////////////////////////////// |
---|
283 | // get_mark_number |
---|
284 | // |
---|
285 | inline int get_mark_number(mark_tag const &mark) |
---|
286 | { |
---|
287 | return proto::arg(mark).mark_number_; |
---|
288 | } |
---|
289 | |
---|
290 | }}} // namespace boost::xpressive::detail |
---|
291 | |
---|
292 | #endif |
---|