1/*=============================================================================
2 Copyright (c) 2002 Juan Carlos Arevalo-Baeza
3 Copyright (c) 2002-2006 Hartmut Kaiser
4 Copyright (c) 2003 Giovanni Bajo
5 http://spirit.sourceforge.net/
6
7 Distributed under the Boost Software License, Version 1.0. (See accompanying
8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9=============================================================================*/
10#ifndef BOOST_SPIRIT_POSITION_ITERATOR_HPP
11#define BOOST_SPIRIT_POSITION_ITERATOR_HPP
12
13#include <string>
14#include <boost/config.hpp>
15
16#include <boost/spirit/home/classic/namespace.hpp>
17#include <boost/spirit/home/classic/iterator/position_iterator_fwd.hpp>
18
19namespace boost { namespace spirit {
20
21BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
22
23///////////////////////////////////////////////////////////////////////////////
24//
25// file_position_without_column
26//
27// A structure to hold positional information. This includes the file,
28// and the line number
29//
30///////////////////////////////////////////////////////////////////////////////
31template <typename String>
32struct file_position_without_column_base {
33 String file;
34 int line;
35
36 file_position_without_column_base(String const& file_ = String(),
37 int line_ = 1):
38 file (file_),
39 line (line_)
40 {}
41
42 bool operator==(const file_position_without_column_base& fp) const
43 { return line == fp.line && file == fp.file; }
44};
45
46///////////////////////////////////////////////////////////////////////////////
47//
48// file_position
49//
50// This structure holds complete file position, including file name,
51// line and column number
52//
53///////////////////////////////////////////////////////////////////////////////
54template <typename String>
55struct file_position_base : public file_position_without_column_base<String> {
56 int column;
57
58 file_position_base(String const& file_ = String(),
59 int line_ = 1, int column_ = 1):
60 file_position_without_column_base<String> (file_, line_),
61 column (column_)
62 {}
63
64 bool operator==(const file_position_base& fp) const
65 { return column == fp.column && this->line == fp.line && this->file == fp.file; }
66};
67
68///////////////////////////////////////////////////////////////////////////////
69//
70// position_policy<>
71//
72// This template is the policy to handle the file position. It is specialized
73// on the position type. Providing a custom file_position also requires
74// providing a specialization of this class.
75//
76// Policy interface:
77//
78// Default constructor of the custom position class must be accessible.
79// set_tab_chars(unsigned int chars) - Set the tabstop width
80// next_char(PositionT& pos) - Notify that a new character has been
81// processed
82// tabulation(PositionT& pos) - Notify that a tab character has been
83// processed
84// next_line(PositionT& pos) - Notify that a new line delimiter has
85// been reached.
86//
87///////////////////////////////////////////////////////////////////////////////
88template <typename PositionT> class position_policy;
89
90///////////////////////////////////////////////////////////////////////////////
91BOOST_SPIRIT_CLASSIC_NAMESPACE_END
92
93}} /* namespace BOOST_SPIRIT_CLASSIC_NS */
94
95
96// This must be included here for full compatibility with old MSVC
97#include <boost/spirit/home/classic/iterator/impl/position_iterator.ipp>
98
99///////////////////////////////////////////////////////////////////////////////
100namespace boost { namespace spirit {
101
102BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
103
104///////////////////////////////////////////////////////////////////////////////
105//
106// position_iterator
107//
108// It wraps an iterator, and keeps track of the current position in the input,
109// as it gets incremented.
110//
111// The wrapped iterator must be at least a Forward iterator. The position
112// iterator itself will always be a non-mutable Forward iterator.
113//
114// In order to have begin/end iterators constructed, the end iterator must be
115// empty constructed. Similar to what happens with stream iterators. The begin
116// iterator must be constructed from both, the begin and end iterators of the
117// wrapped iterator type. This is necessary to implement the lookahead of
118// characters necessary to parse CRLF sequences.
119//
120// In order to extract the current positional data from the iterator, you may
121// use the get_position member function.
122//
123// You can also use the set_position member function to reset the current
124// position to something new.
125//
126// The structure that holds the current position can be customized through a
127// template parameter, and the class position_policy must be specialized
128// on the new type to define how to handle it. Currently, it's possible
129// to choose between the file_position and file_position_without_column
130// (which saves some overhead if managing current column is not required).
131//
132///////////////////////////////////////////////////////////////////////////////
133
134#if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
135 BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
136#error "Please use at least Boost V1.31.0 while compiling the position_iterator class!"
137#else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
138
139///////////////////////////////////////////////////////////////////////////////
140//
141// Uses the newer iterator_adaptor version (should be released with
142// Boost V1.31.0)
143//
144///////////////////////////////////////////////////////////////////////////////
145template <
146 typename ForwardIteratorT,
147 typename PositionT,
148 typename SelfT
149>
150class position_iterator
151: public iterator_::impl::position_iterator_base_generator<
152 SelfT,
153 ForwardIteratorT,
154 PositionT
155 >::type,
156 public position_policy<PositionT>
157{
158private:
159
160 typedef position_policy<PositionT> position_policy_t;
161 typedef typename iterator_::impl::position_iterator_base_generator<
162 SelfT,
163 ForwardIteratorT,
164 PositionT
165 >::type base_t;
166 typedef typename iterator_::impl::position_iterator_base_generator<
167 SelfT,
168 ForwardIteratorT,
169 PositionT
170 >::main_iter_t main_iter_t;
171
172public:
173
174 typedef PositionT position_t;
175
176 position_iterator()
177 : _isend(true)
178 {}
179
180 position_iterator(
181 const ForwardIteratorT& begin,
182 const ForwardIteratorT& end)
183 : base_t(begin), _end(end), _pos(PositionT()), _isend(begin == end)
184 {}
185
186 template <typename FileNameT>
187 position_iterator(
188 const ForwardIteratorT& begin,
189 const ForwardIteratorT& end,
190 FileNameT fileName)
191 : base_t(begin), _end(end), _pos(PositionT(fileName)),
192 _isend(begin == end)
193 {}
194
195 template <typename FileNameT, typename LineT>
196 position_iterator(
197 const ForwardIteratorT& begin,
198 const ForwardIteratorT& end,
199 FileNameT fileName, LineT line)
200 : base_t(begin), _end(end), _pos(PositionT(fileName, line)),
201 _isend(begin == end)
202 {}
203
204 template <typename FileNameT, typename LineT, typename ColumnT>
205 position_iterator(
206 const ForwardIteratorT& begin,
207 const ForwardIteratorT& end,
208 FileNameT fileName, LineT line, ColumnT column)
209 : base_t(begin), _end(end), _pos(PositionT(fileName, line, column)),
210 _isend(begin == end)
211 {}
212
213 position_iterator(
214 const ForwardIteratorT& begin,
215 const ForwardIteratorT& end,
216 const PositionT& pos)
217 : base_t(begin), _end(end), _pos(pos), _isend(begin == end)
218 {}
219
220 position_iterator(const position_iterator& iter)
221 : base_t(iter.base()), position_policy_t(iter),
222 _end(iter._end), _pos(iter._pos), _isend(iter._isend)
223 {}
224
225 position_iterator& operator=(const position_iterator& iter)
226 {
227 base_t::operator=(iter);
228 position_policy_t::operator=(iter);
229 _end = iter._end;
230 _pos = iter._pos;
231 _isend = iter._isend;
232 return *this;
233 }
234
235 void set_position(PositionT const& newpos) { _pos = newpos; }
236 PositionT& get_position() { return _pos; }
237 PositionT const& get_position() const { return _pos; }
238
239 void set_tabchars(unsigned int chars)
240 {
241 // This function (which comes from the position_policy) has a
242 // different name on purpose, to avoid messing with using
243 // declarations or qualified calls to access the base template
244 // function, which might break some compilers.
245 this->position_policy_t::set_tab_chars(chars);
246 }
247
248private:
249 friend class boost::iterator_core_access;
250
251 void increment()
252 {
253 typename base_t::reference val = *(this->base());
254 if (val == '\n') {
255 ++this->base_reference();
256 this->next_line(_pos);
257 static_cast<main_iter_t &>(*this).newline();
258 }
259 else if ( val == '\r') {
260 ++this->base_reference();
261 if (this->base_reference() == _end || *(this->base()) != '\n')
262 {
263 this->next_line(_pos);
264 static_cast<main_iter_t &>(*this).newline();
265 }
266 }
267 else if (val == '\t') {
268 this->tabulation(_pos);
269 ++this->base_reference();
270 }
271 else {
272 this->next_char(_pos);
273 ++this->base_reference();
274 }
275
276 // The iterator is at the end only if it's the same
277 // of the
278 _isend = (this->base_reference() == _end);
279 }
280
281 template <
282 typename OtherDerivedT, typename OtherIteratorT,
283 typename V, typename C, typename R, typename D
284 >
285 bool equal(iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
286 const &x) const
287 {
288 OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x);
289 bool x_is_end = rhs._isend;
290
291 return (_isend == x_is_end) && (_isend || this->base() == rhs.base());
292 }
293
294protected:
295
296 void newline()
297 {}
298
299 ForwardIteratorT _end;
300 PositionT _pos;
301 bool _isend;
302};
303
304#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
305
306///////////////////////////////////////////////////////////////////////////////
307//
308// position_iterator2
309//
310// Equivalent to position_iterator, but it is able to extract the current
311// line into a string. This is very handy for error reports.
312//
313// Notice that the footprint of this class is higher than position_iterator,
314// (how much depends on how bulky the underlying iterator is), so it should
315// be used only if necessary.
316//
317///////////////////////////////////////////////////////////////////////////////
318
319template
320<
321 typename ForwardIteratorT,
322 typename PositionT
323>
324class position_iterator2
325 : public position_iterator
326 <
327 ForwardIteratorT,
328 PositionT,
329 position_iterator2<ForwardIteratorT, PositionT>
330 >
331{
332 typedef position_iterator
333 <
334 ForwardIteratorT,
335 PositionT,
336 position_iterator2<ForwardIteratorT, PositionT> // JDG 4-15-03
337 > base_t;
338
339public:
340 typedef typename base_t::value_type value_type;
341 typedef PositionT position_t;
342
343 position_iterator2()
344 {}
345
346 position_iterator2(
347 const ForwardIteratorT& begin,
348 const ForwardIteratorT& end):
349 base_t(begin, end),
350 _startline(begin)
351 {}
352
353 template <typename FileNameT>
354 position_iterator2(
355 const ForwardIteratorT& begin,
356 const ForwardIteratorT& end,
357 FileNameT file):
358 base_t(begin, end, file),
359 _startline(begin)
360 {}
361
362 template <typename FileNameT, typename LineT>
363 position_iterator2(
364 const ForwardIteratorT& begin,
365 const ForwardIteratorT& end,
366 FileNameT file, LineT line):
367 base_t(begin, end, file, line),
368 _startline(begin)
369 {}
370
371 template <typename FileNameT, typename LineT, typename ColumnT>
372 position_iterator2(
373 const ForwardIteratorT& begin,
374 const ForwardIteratorT& end,
375 FileNameT file, LineT line, ColumnT column):
376 base_t(begin, end, file, line, column),
377 _startline(begin)
378 {}
379
380 position_iterator2(
381 const ForwardIteratorT& begin,
382 const ForwardIteratorT& end,
383 const PositionT& pos):
384 base_t(begin, end, pos),
385 _startline(begin)
386 {}
387
388 position_iterator2(const position_iterator2& iter)
389 : base_t(iter), _startline(iter._startline)
390 {}
391
392 position_iterator2& operator=(const position_iterator2& iter)
393 {
394 base_t::operator=(iter);
395 _startline = iter._startline;
396 return *this;
397 }
398
399 ForwardIteratorT get_currentline_begin() const
400 { return _startline; }
401
402 ForwardIteratorT get_currentline_end() const
403 { return get_endline(); }
404
405 std::basic_string<value_type> get_currentline() const
406 {
407 return std::basic_string<value_type>
408 (get_currentline_begin(), get_currentline_end());
409 }
410
411protected:
412 ForwardIteratorT _startline;
413
414 friend class position_iterator<ForwardIteratorT, PositionT,
415 position_iterator2<ForwardIteratorT, PositionT> >;
416
417 ForwardIteratorT get_endline() const
418 {
419 ForwardIteratorT endline = _startline;
420 while (endline != this->_end && *endline != '\r' && *endline != '\n')
421 {
422 ++endline;
423 }
424 return endline;
425 }
426
427 void newline()
428 { _startline = this->base(); }
429};
430
431BOOST_SPIRIT_CLASSIC_NAMESPACE_END
432
433}} // namespace BOOST_SPIRIT_CLASSIC_NS
434
435#endif
436

source code of boost/libs/spirit/include/boost/spirit/home/classic/iterator/position_iterator.hpp