Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Boost.Wave: A Standard compliant C++ preprocessor library
|
Chris@16
|
3
|
Chris@16
|
4 Definition of the unput queue iterator
|
Chris@16
|
5
|
Chris@16
|
6 http://www.boost.org/
|
Chris@16
|
7
|
Chris@16
|
8 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
|
Chris@16
|
9 Software License, Version 1.0. (See accompanying file
|
Chris@16
|
10 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
11 =============================================================================*/
|
Chris@16
|
12 #if !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)
|
Chris@16
|
13 #define UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED
|
Chris@16
|
14
|
Chris@16
|
15 #include <list>
|
Chris@16
|
16
|
Chris@16
|
17 #include <boost/assert.hpp>
|
Chris@16
|
18 #include <boost/iterator_adaptors.hpp>
|
Chris@16
|
19
|
Chris@16
|
20 #include <boost/wave/wave_config.hpp>
|
Chris@16
|
21 #include <boost/wave/token_ids.hpp> // token_id
|
Chris@16
|
22
|
Chris@16
|
23 // this must occur after all of the includes and before any code appears
|
Chris@16
|
24 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
25 #include BOOST_ABI_PREFIX
|
Chris@16
|
26 #endif
|
Chris@16
|
27
|
Chris@16
|
28 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
29 namespace boost {
|
Chris@16
|
30 namespace wave {
|
Chris@16
|
31 namespace util {
|
Chris@16
|
32
|
Chris@16
|
33 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
34 //
|
Chris@16
|
35 // unput_queue_iterator
|
Chris@16
|
36 //
|
Chris@16
|
37 // The unput_queue_iterator templates encapsulates an unput_queue together
|
Chris@16
|
38 // with the direct input to be read after the unput queue is emptied
|
Chris@16
|
39 //
|
Chris@16
|
40 // This version is for the new iterator_adaptors (was released with
|
Chris@16
|
41 // Boost V1.31.0)
|
Chris@16
|
42 //
|
Chris@16
|
43 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
44 template <typename IteratorT, typename TokenT, typename ContainerT>
|
Chris@16
|
45 class unput_queue_iterator
|
Chris@16
|
46 : public boost::iterator_adaptor<
|
Chris@16
|
47 unput_queue_iterator<IteratorT, TokenT, ContainerT>,
|
Chris@16
|
48 IteratorT, TokenT const, std::forward_iterator_tag>
|
Chris@16
|
49 {
|
Chris@16
|
50 typedef boost::iterator_adaptor<
|
Chris@16
|
51 unput_queue_iterator<IteratorT, TokenT, ContainerT>,
|
Chris@16
|
52 IteratorT, TokenT const, std::forward_iterator_tag>
|
Chris@16
|
53 base_type;
|
Chris@16
|
54
|
Chris@16
|
55 public:
|
Chris@16
|
56 typedef ContainerT container_type;
|
Chris@16
|
57 typedef IteratorT iterator_type;
|
Chris@16
|
58
|
Chris@16
|
59 unput_queue_iterator(IteratorT const &it, ContainerT &queue)
|
Chris@16
|
60 : base_type(it), unput_queue(queue)
|
Chris@16
|
61 {}
|
Chris@16
|
62
|
Chris@16
|
63 ContainerT &get_unput_queue()
|
Chris@16
|
64 { return unput_queue; }
|
Chris@16
|
65 ContainerT const &get_unput_queue() const
|
Chris@16
|
66 { return unput_queue; }
|
Chris@16
|
67 IteratorT &get_base_iterator()
|
Chris@16
|
68 { return base_type::base_reference(); }
|
Chris@16
|
69 IteratorT const &get_base_iterator() const
|
Chris@16
|
70 { return base_type::base_reference(); }
|
Chris@16
|
71
|
Chris@16
|
72 unput_queue_iterator &operator= (unput_queue_iterator const &rhs)
|
Chris@16
|
73 {
|
Chris@16
|
74 if (this != &rhs) {
|
Chris@16
|
75 unput_queue = rhs.unput_queue;
|
Chris@16
|
76 base_type::operator=(rhs);
|
Chris@16
|
77 }
|
Chris@16
|
78 return *this;
|
Chris@16
|
79 }
|
Chris@16
|
80
|
Chris@16
|
81 typename base_type::reference dereference() const
|
Chris@16
|
82 {
|
Chris@16
|
83 if (!unput_queue.empty())
|
Chris@16
|
84 return unput_queue.front();
|
Chris@16
|
85 return *base_type::base_reference();
|
Chris@16
|
86 }
|
Chris@16
|
87
|
Chris@16
|
88 void increment()
|
Chris@16
|
89 {
|
Chris@16
|
90 if (!unput_queue.empty()) {
|
Chris@16
|
91 // there exist pending tokens in the unput queue
|
Chris@16
|
92 unput_queue.pop_front();
|
Chris@16
|
93 }
|
Chris@16
|
94 else {
|
Chris@16
|
95 // the unput_queue is empty, so advance the base iterator
|
Chris@16
|
96 ++base_type::base_reference();
|
Chris@16
|
97 }
|
Chris@16
|
98 }
|
Chris@16
|
99
|
Chris@16
|
100 template <
|
Chris@16
|
101 typename OtherDerivedT, typename OtherIteratorT,
|
Chris@16
|
102 typename V, typename C, typename R, typename D
|
Chris@16
|
103 >
|
Chris@16
|
104 bool equal(
|
Chris@16
|
105 boost::iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
|
Chris@16
|
106 const &x) const
|
Chris@16
|
107 {
|
Chris@16
|
108 // two iterators are equal, if both begin() iterators of the queue
|
Chris@16
|
109 // objects are equal and the base iterators are equal as well
|
Chris@16
|
110 OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x);
|
Chris@16
|
111 return
|
Chris@16
|
112 ((unput_queue.empty() && rhs.unput_queue.empty()) ||
|
Chris@16
|
113 (&unput_queue == &rhs.unput_queue &&
|
Chris@16
|
114 unput_queue.begin() == rhs.unput_queue.begin()
|
Chris@16
|
115 )
|
Chris@16
|
116 ) &&
|
Chris@16
|
117 (get_base_iterator() == rhs.get_base_iterator());
|
Chris@16
|
118 }
|
Chris@16
|
119
|
Chris@16
|
120 private:
|
Chris@16
|
121 ContainerT &unput_queue;
|
Chris@16
|
122 };
|
Chris@16
|
123
|
Chris@16
|
124 namespace impl {
|
Chris@16
|
125
|
Chris@16
|
126 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
127 template <typename IteratorT, typename TokenT, typename ContainerT>
|
Chris@16
|
128 struct gen_unput_queue_iterator
|
Chris@16
|
129 {
|
Chris@16
|
130 typedef ContainerT container_type;
|
Chris@16
|
131 typedef IteratorT iterator_type;
|
Chris@16
|
132 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
|
Chris@16
|
133 return_type;
|
Chris@16
|
134
|
Chris@16
|
135 static container_type last;
|
Chris@16
|
136
|
Chris@16
|
137 static return_type
|
Chris@16
|
138 generate(iterator_type const &it)
|
Chris@16
|
139 {
|
Chris@16
|
140 return return_type(it, last);
|
Chris@16
|
141 }
|
Chris@16
|
142
|
Chris@16
|
143 static return_type
|
Chris@16
|
144 generate(ContainerT &queue, iterator_type const &it)
|
Chris@16
|
145 {
|
Chris@16
|
146 return return_type(it, queue);
|
Chris@16
|
147 }
|
Chris@16
|
148 };
|
Chris@16
|
149
|
Chris@16
|
150 template <typename IteratorT, typename TokenT, typename ContainerT>
|
Chris@16
|
151 typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::
|
Chris@16
|
152 container_type
|
Chris@16
|
153 gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::last =
|
Chris@16
|
154 typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::
|
Chris@16
|
155 container_type();
|
Chris@16
|
156
|
Chris@16
|
157 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
158 template <typename IteratorT, typename TokenT, typename ContainerT>
|
Chris@16
|
159 struct gen_unput_queue_iterator<
|
Chris@16
|
160 unput_queue_iterator<IteratorT, TokenT, ContainerT>,
|
Chris@16
|
161 TokenT, ContainerT>
|
Chris@16
|
162 {
|
Chris@16
|
163 typedef ContainerT container_type;
|
Chris@16
|
164 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
|
Chris@16
|
165 iterator_type;
|
Chris@16
|
166 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT>
|
Chris@16
|
167 return_type;
|
Chris@16
|
168
|
Chris@16
|
169 static container_type last;
|
Chris@16
|
170
|
Chris@16
|
171 static return_type
|
Chris@16
|
172 generate(iterator_type &it)
|
Chris@16
|
173 {
|
Chris@16
|
174 return return_type(it.base(), last);
|
Chris@16
|
175 }
|
Chris@16
|
176
|
Chris@16
|
177 static return_type
|
Chris@16
|
178 generate(ContainerT &queue, iterator_type &it)
|
Chris@16
|
179 {
|
Chris@16
|
180 return return_type(it.base(), queue);
|
Chris@16
|
181 }
|
Chris@16
|
182 };
|
Chris@16
|
183
|
Chris@16
|
184 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
185 template <typename IteratorT>
|
Chris@16
|
186 struct assign_iterator
|
Chris@16
|
187 {
|
Chris@16
|
188 static void
|
Chris@16
|
189 do_ (IteratorT &dest, IteratorT const &src)
|
Chris@16
|
190 {
|
Chris@16
|
191 dest = src;
|
Chris@16
|
192 }
|
Chris@16
|
193 };
|
Chris@16
|
194
|
Chris@16
|
195 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
196 //
|
Chris@16
|
197 // Look for the first non-whitespace token and return this token id.
|
Chris@16
|
198 // Note though, that the embedded unput_queues are not touched in any way!
|
Chris@16
|
199 //
|
Chris@16
|
200 template <typename IteratorT>
|
Chris@16
|
201 struct next_token
|
Chris@16
|
202 {
|
Chris@16
|
203 static boost::wave::token_id
|
Chris@16
|
204 peek(IteratorT it, IteratorT end, bool skip_whitespace = true)
|
Chris@16
|
205 {
|
Chris@16
|
206 using namespace boost::wave;
|
Chris@16
|
207 if (skip_whitespace) {
|
Chris@16
|
208 for (++it; it != end; ++it) {
|
Chris@16
|
209 if (!IS_CATEGORY(*it, WhiteSpaceTokenType) &&
|
Chris@16
|
210 T_NEWLINE != token_id(*it))
|
Chris@16
|
211 {
|
Chris@16
|
212 break; // stop at the first non-whitespace token
|
Chris@16
|
213 }
|
Chris@16
|
214 }
|
Chris@16
|
215 }
|
Chris@16
|
216 else {
|
Chris@16
|
217 ++it; // we have at least to look ahead
|
Chris@16
|
218 }
|
Chris@16
|
219 if (it != end)
|
Chris@16
|
220 return token_id(*it);
|
Chris@16
|
221 return T_EOI;
|
Chris@16
|
222 }
|
Chris@16
|
223 };
|
Chris@16
|
224
|
Chris@16
|
225 template <typename IteratorT, typename TokenT, typename ContainerT>
|
Chris@16
|
226 struct next_token<
|
Chris@16
|
227 unput_queue_iterator<IteratorT, TokenT, ContainerT> > {
|
Chris@16
|
228
|
Chris@16
|
229 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> iterator_type;
|
Chris@16
|
230
|
Chris@16
|
231 static boost::wave::token_id
|
Chris@16
|
232 peek(iterator_type it, iterator_type end, bool skip_whitespace = true)
|
Chris@16
|
233 {
|
Chris@16
|
234 using namespace boost::wave;
|
Chris@16
|
235
|
Chris@16
|
236 typename iterator_type::container_type &queue = it.get_unput_queue();
|
Chris@16
|
237
|
Chris@16
|
238 // first try to find it in the unput_queue
|
Chris@16
|
239 if (0 != queue.size()) {
|
Chris@16
|
240 typename iterator_type::container_type::iterator cit = queue.begin();
|
Chris@16
|
241 typename iterator_type::container_type::iterator cend = queue.end();
|
Chris@16
|
242
|
Chris@16
|
243 if (skip_whitespace) {
|
Chris@16
|
244 for (++cit; cit != cend; ++cit) {
|
Chris@16
|
245 if (!IS_CATEGORY(*cit, WhiteSpaceTokenType) &&
|
Chris@16
|
246 T_NEWLINE != token_id(*cit))
|
Chris@16
|
247 {
|
Chris@16
|
248 break; // stop at the first non-whitespace token
|
Chris@16
|
249 }
|
Chris@16
|
250 }
|
Chris@16
|
251 }
|
Chris@16
|
252 else {
|
Chris@16
|
253 ++cit; // we have at least to look ahead
|
Chris@16
|
254 }
|
Chris@16
|
255 if (cit != cend)
|
Chris@16
|
256 return token_id(*cit);
|
Chris@16
|
257 }
|
Chris@16
|
258
|
Chris@16
|
259 // second try to move on into the base iterator stream
|
Chris@16
|
260 typename iterator_type::iterator_type base_it = it.get_base_iterator();
|
Chris@16
|
261 typename iterator_type::iterator_type base_end = end.get_base_iterator();
|
Chris@16
|
262
|
Chris@16
|
263 if (0 == queue.size())
|
Chris@16
|
264 ++base_it; // advance, if the unput queue is empty
|
Chris@16
|
265
|
Chris@16
|
266 if (skip_whitespace) {
|
Chris@16
|
267 for (/**/; base_it != base_end; ++base_it) {
|
Chris@16
|
268 if (!IS_CATEGORY(*base_it, WhiteSpaceTokenType) &&
|
Chris@16
|
269 T_NEWLINE != token_id(*base_it))
|
Chris@16
|
270 {
|
Chris@16
|
271 break; // stop at the first non-whitespace token
|
Chris@16
|
272 }
|
Chris@16
|
273 }
|
Chris@16
|
274 }
|
Chris@16
|
275 if (base_it == base_end)
|
Chris@16
|
276 return T_EOI;
|
Chris@16
|
277
|
Chris@16
|
278 return token_id(*base_it);
|
Chris@16
|
279 }
|
Chris@16
|
280 };
|
Chris@16
|
281
|
Chris@16
|
282 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
283 } // namespace impl
|
Chris@16
|
284
|
Chris@16
|
285 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
286 } // namespace util
|
Chris@16
|
287 } // namespace wave
|
Chris@16
|
288 } // namespace boost
|
Chris@16
|
289
|
Chris@16
|
290 // the suffix header occurs after all of the code
|
Chris@16
|
291 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
292 #include BOOST_ABI_SUFFIX
|
Chris@16
|
293 #endif
|
Chris@16
|
294
|
Chris@16
|
295 #endif // !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED)
|