Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 // static.hpp
|
Chris@16
|
3 //
|
Chris@16
|
4 // Copyright 2008 Eric Niebler. Distributed under the Boost
|
Chris@16
|
5 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef BOOST_XPRESSIVE_DETAIL_STATIC_STATIC_HPP_EAN_10_04_2005
|
Chris@16
|
9 #define BOOST_XPRESSIVE_DETAIL_STATIC_STATIC_HPP_EAN_10_04_2005
|
Chris@16
|
10
|
Chris@16
|
11 // MS compatible compilers support #pragma once
|
Chris@101
|
12 #if defined(_MSC_VER)
|
Chris@16
|
13 # pragma once
|
Chris@16
|
14 #endif
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/mpl/assert.hpp>
|
Chris@16
|
17 #include <boost/xpressive/detail/detail_fwd.hpp>
|
Chris@16
|
18 #include <boost/xpressive/detail/core/state.hpp>
|
Chris@16
|
19 #include <boost/xpressive/detail/core/linker.hpp>
|
Chris@16
|
20 #include <boost/xpressive/detail/core/peeker.hpp>
|
Chris@16
|
21 #include <boost/xpressive/detail/static/placeholders.hpp>
|
Chris@16
|
22 #include <boost/xpressive/detail/utility/width.hpp>
|
Chris@16
|
23
|
Chris@16
|
24 // Random thoughts:
|
Chris@16
|
25 // - must support indirect repeat counts {$n,$m}
|
Chris@16
|
26 // - add ws to eat whitespace (make *ws illegal)
|
Chris@16
|
27 // - a{n,m} -> repeat<n,m>(a)
|
Chris@16
|
28 // - a{$n,$m} -> repeat(n,m)(a)
|
Chris@16
|
29 // - add nil to match nothing
|
Chris@16
|
30 // - instead of s1, s2, etc., how about s[1], s[2], etc.? Needlessly verbose?
|
Chris@16
|
31
|
Chris@16
|
32 namespace boost { namespace xpressive { namespace detail
|
Chris@16
|
33 {
|
Chris@16
|
34
|
Chris@16
|
35 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
36 // stacked_xpression
|
Chris@16
|
37 //
|
Chris@16
|
38 template<typename Top, typename Next>
|
Chris@16
|
39 struct stacked_xpression
|
Chris@16
|
40 : Next
|
Chris@16
|
41 {
|
Chris@16
|
42 // match
|
Chris@16
|
43 // delegates to Next
|
Chris@16
|
44 template<typename BidiIter>
|
Chris@16
|
45 bool match(match_state<BidiIter> &state) const
|
Chris@16
|
46 {
|
Chris@16
|
47 return static_cast<Next const *>(this)->
|
Chris@16
|
48 BOOST_NESTED_TEMPLATE push_match<Top>(state);
|
Chris@16
|
49 }
|
Chris@16
|
50
|
Chris@16
|
51 // top_match
|
Chris@16
|
52 // jump back to the xpression on top of the xpression stack,
|
Chris@16
|
53 // and keep the xpression on the stack.
|
Chris@16
|
54 template<typename BidiIter>
|
Chris@16
|
55 static bool top_match(match_state<BidiIter> &state, void const *top)
|
Chris@16
|
56 {
|
Chris@16
|
57 return static_cast<Top const *>(top)->
|
Chris@16
|
58 BOOST_NESTED_TEMPLATE push_match<Top>(state);
|
Chris@16
|
59 }
|
Chris@16
|
60
|
Chris@16
|
61 // pop_match
|
Chris@16
|
62 // jump back to the xpression on top of the xpression stack,
|
Chris@16
|
63 // pop the xpression off the stack.
|
Chris@16
|
64 template<typename BidiIter>
|
Chris@16
|
65 static bool pop_match(match_state<BidiIter> &state, void const *top)
|
Chris@16
|
66 {
|
Chris@16
|
67 return static_cast<Top const *>(top)->match(state);
|
Chris@16
|
68 }
|
Chris@16
|
69
|
Chris@16
|
70 // skip_match
|
Chris@16
|
71 // pop the xpression off the top of the stack and ignore it; call
|
Chris@16
|
72 // match on next.
|
Chris@16
|
73 template<typename BidiIter>
|
Chris@16
|
74 bool skip_match(match_state<BidiIter> &state) const
|
Chris@16
|
75 {
|
Chris@16
|
76 // could be static_xpression::skip_impl or stacked_xpression::skip_impl
|
Chris@16
|
77 // depending on if there is 1 or more than 1 xpression on the
|
Chris@16
|
78 // xpression stack
|
Chris@16
|
79 return Top::skip_impl(*static_cast<Next const *>(this), state);
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 //protected:
|
Chris@16
|
83
|
Chris@16
|
84 // skip_impl
|
Chris@16
|
85 // implementation of skip_match.
|
Chris@16
|
86 template<typename That, typename BidiIter>
|
Chris@16
|
87 static bool skip_impl(That const &that, match_state<BidiIter> &state)
|
Chris@16
|
88 {
|
Chris@16
|
89 return that.BOOST_NESTED_TEMPLATE push_match<Top>(state);
|
Chris@16
|
90 }
|
Chris@16
|
91 };
|
Chris@16
|
92
|
Chris@16
|
93 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
94 // stacked_xpression_cast
|
Chris@16
|
95 //
|
Chris@16
|
96 template<typename Top, typename Next>
|
Chris@16
|
97 inline stacked_xpression<Top, Next> const &stacked_xpression_cast(Next const &next)
|
Chris@16
|
98 {
|
Chris@16
|
99 // NOTE: this is a little white lie. The "next" object doesn't really have
|
Chris@16
|
100 // the type to which we're casting it. It is harmless, though. We are only using
|
Chris@16
|
101 // the cast to decorate the next object with type information. It is done
|
Chris@16
|
102 // this way to save stack space.
|
Chris@16
|
103 BOOST_MPL_ASSERT_RELATION(sizeof(stacked_xpression<Top, Next>), ==, sizeof(Next));
|
Chris@16
|
104 return *static_cast<stacked_xpression<Top, Next> const *>(&next);
|
Chris@16
|
105 }
|
Chris@16
|
106
|
Chris@16
|
107 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
108 // static_xpression
|
Chris@16
|
109 //
|
Chris@16
|
110 template<typename Matcher, typename Next>
|
Chris@16
|
111 struct static_xpression
|
Chris@16
|
112 : Matcher
|
Chris@16
|
113 {
|
Chris@16
|
114 Next next_;
|
Chris@16
|
115
|
Chris@16
|
116 BOOST_STATIC_CONSTANT(bool, pure = Matcher::pure && Next::pure);
|
Chris@16
|
117 BOOST_STATIC_CONSTANT(
|
Chris@16
|
118 std::size_t
|
Chris@16
|
119 , width =
|
Chris@16
|
120 Matcher::width != unknown_width::value && Next::width != unknown_width::value
|
Chris@16
|
121 ? Matcher::width + Next::width
|
Chris@16
|
122 : unknown_width::value
|
Chris@16
|
123 );
|
Chris@16
|
124
|
Chris@16
|
125 static_xpression(Matcher const &matcher = Matcher(), Next const &next = Next())
|
Chris@16
|
126 : Matcher(matcher)
|
Chris@16
|
127 , next_(next)
|
Chris@16
|
128 {
|
Chris@16
|
129 }
|
Chris@16
|
130
|
Chris@16
|
131 // match
|
Chris@16
|
132 // delegates to the Matcher
|
Chris@16
|
133 template<typename BidiIter>
|
Chris@16
|
134 bool match(match_state<BidiIter> &state) const
|
Chris@16
|
135 {
|
Chris@16
|
136 return this->Matcher::match(state, this->next_);
|
Chris@16
|
137 }
|
Chris@16
|
138
|
Chris@16
|
139 // push_match
|
Chris@16
|
140 // call match on this, but also push "Top" onto the xpression
|
Chris@16
|
141 // stack so we know what we are jumping back to later.
|
Chris@16
|
142 template<typename Top, typename BidiIter>
|
Chris@16
|
143 bool push_match(match_state<BidiIter> &state) const
|
Chris@16
|
144 {
|
Chris@16
|
145 return this->Matcher::match(state, stacked_xpression_cast<Top>(this->next_));
|
Chris@16
|
146 }
|
Chris@16
|
147
|
Chris@16
|
148 // skip_impl
|
Chris@16
|
149 // implementation of skip_match, called from stacked_xpression::skip_match
|
Chris@16
|
150 template<typename That, typename BidiIter>
|
Chris@16
|
151 static bool skip_impl(That const &that, match_state<BidiIter> &state)
|
Chris@16
|
152 {
|
Chris@16
|
153 return that.match(state);
|
Chris@16
|
154 }
|
Chris@16
|
155
|
Chris@16
|
156 // for linking a compiled regular xpression
|
Chris@16
|
157 template<typename Char>
|
Chris@16
|
158 void link(xpression_linker<Char> &linker) const
|
Chris@16
|
159 {
|
Chris@16
|
160 linker.accept(*static_cast<Matcher const *>(this), &this->next_);
|
Chris@16
|
161 this->next_.link(linker);
|
Chris@16
|
162 }
|
Chris@16
|
163
|
Chris@16
|
164 // for building a lead-follow
|
Chris@16
|
165 template<typename Char>
|
Chris@16
|
166 void peek(xpression_peeker<Char> &peeker) const
|
Chris@16
|
167 {
|
Chris@16
|
168 this->peek_next_(peeker.accept(*static_cast<Matcher const *>(this)), peeker);
|
Chris@16
|
169 }
|
Chris@16
|
170
|
Chris@16
|
171 // for getting xpression width
|
Chris@16
|
172 detail::width get_width() const
|
Chris@16
|
173 {
|
Chris@16
|
174 return this->get_width_(mpl::size_t<width>());
|
Chris@16
|
175 }
|
Chris@16
|
176
|
Chris@16
|
177 private:
|
Chris@16
|
178
|
Chris@16
|
179 static_xpression &operator =(static_xpression const &);
|
Chris@16
|
180
|
Chris@16
|
181 template<typename Char>
|
Chris@16
|
182 void peek_next_(mpl::true_, xpression_peeker<Char> &peeker) const
|
Chris@16
|
183 {
|
Chris@16
|
184 this->next_.peek(peeker);
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 template<typename Char>
|
Chris@16
|
188 void peek_next_(mpl::false_, xpression_peeker<Char> &) const
|
Chris@16
|
189 {
|
Chris@16
|
190 // no-op
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 template<std::size_t Width>
|
Chris@16
|
194 detail::width get_width_(mpl::size_t<Width>) const
|
Chris@16
|
195 {
|
Chris@16
|
196 return Width;
|
Chris@16
|
197 }
|
Chris@16
|
198
|
Chris@16
|
199 detail::width get_width_(unknown_width) const
|
Chris@16
|
200 {
|
Chris@16
|
201 // Should only be called in contexts where the width is
|
Chris@16
|
202 // known to be fixed.
|
Chris@16
|
203 return this->Matcher::get_width() + this->next_.get_width();
|
Chris@16
|
204 }
|
Chris@16
|
205 };
|
Chris@16
|
206
|
Chris@16
|
207 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
208 // make_static
|
Chris@16
|
209 //
|
Chris@16
|
210 template<typename Matcher>
|
Chris@16
|
211 inline static_xpression<Matcher> const
|
Chris@16
|
212 make_static(Matcher const &matcher)
|
Chris@16
|
213 {
|
Chris@16
|
214 return static_xpression<Matcher>(matcher);
|
Chris@16
|
215 }
|
Chris@16
|
216
|
Chris@16
|
217 template<typename Matcher, typename Next>
|
Chris@16
|
218 inline static_xpression<Matcher, Next> const
|
Chris@16
|
219 make_static(Matcher const &matcher, Next const &next)
|
Chris@16
|
220 {
|
Chris@16
|
221 return static_xpression<Matcher, Next>(matcher, next);
|
Chris@16
|
222 }
|
Chris@16
|
223
|
Chris@16
|
224 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
225 // no_next
|
Chris@16
|
226 //
|
Chris@16
|
227 struct no_next
|
Chris@16
|
228 {
|
Chris@16
|
229 BOOST_STATIC_CONSTANT(std::size_t, width = 0);
|
Chris@16
|
230 BOOST_STATIC_CONSTANT(bool, pure = true);
|
Chris@16
|
231
|
Chris@16
|
232 template<typename Char>
|
Chris@16
|
233 void link(xpression_linker<Char> &) const
|
Chris@16
|
234 {
|
Chris@16
|
235 }
|
Chris@16
|
236
|
Chris@16
|
237 template<typename Char>
|
Chris@16
|
238 void peek(xpression_peeker<Char> &peeker) const
|
Chris@16
|
239 {
|
Chris@16
|
240 peeker.fail();
|
Chris@16
|
241 }
|
Chris@16
|
242
|
Chris@16
|
243 detail::width get_width() const
|
Chris@16
|
244 {
|
Chris@16
|
245 return 0;
|
Chris@16
|
246 }
|
Chris@16
|
247 };
|
Chris@16
|
248
|
Chris@16
|
249 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
250 // get_mark_number
|
Chris@16
|
251 //
|
Chris@16
|
252 inline int get_mark_number(basic_mark_tag const &mark)
|
Chris@16
|
253 {
|
Chris@16
|
254 return proto::value(mark).mark_number_;
|
Chris@16
|
255 }
|
Chris@16
|
256
|
Chris@16
|
257 }}} // namespace boost::xpressive::detail
|
Chris@16
|
258
|
Chris@16
|
259 #endif
|