| /*============================================================================= |
| Copyright (c) 2002 Juan Carlos Arevalo-Baeza |
| Copyright (c) 2002-2006 Hartmut Kaiser |
| Copyright (c) 2003 Giovanni Bajo |
| http://spirit.sourceforge.net/ |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| =============================================================================*/ |
| #ifndef BOOST_SPIRIT_POSITION_ITERATOR_HPP |
| #define BOOST_SPIRIT_POSITION_ITERATOR_HPP |
| |
| #include <string> |
| #include <boost/config.hpp> |
| #include <boost/concept_check.hpp> |
| |
| #include <boost/spirit/home/classic/namespace.hpp> |
| #include <boost/spirit/home/classic/iterator/position_iterator_fwd.hpp> |
| |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // file_position_without_column |
| // |
| // A structure to hold positional information. This includes the file, |
| // and the line number |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| template <typename String> |
| struct file_position_without_column_base { |
| String file; |
| int line; |
| |
| file_position_without_column_base(String const& file_ = String(), |
| int line_ = 1): |
| file (file_), |
| line (line_) |
| {} |
| |
| bool operator==(const file_position_without_column_base& fp) const |
| { return line == fp.line && file == fp.file; } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // file_position |
| // |
| // This structure holds complete file position, including file name, |
| // line and column number |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| template <typename String> |
| struct file_position_base : public file_position_without_column_base<String> { |
| int column; |
| |
| file_position_base(String const& file_ = String(), |
| int line_ = 1, int column_ = 1): |
| file_position_without_column_base<String> (file_, line_), |
| column (column_) |
| {} |
| |
| bool operator==(const file_position_base& fp) const |
| { return column == fp.column && this->line == fp.line && this->file == fp.file; } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // position_policy<> |
| // |
| // This template is the policy to handle the file position. It is specialized |
| // on the position type. Providing a custom file_position also requires |
| // providing a specialization of this class. |
| // |
| // Policy interface: |
| // |
| // Default constructor of the custom position class must be accessible. |
| // set_tab_chars(unsigned int chars) - Set the tabstop width |
| // next_char(PositionT& pos) - Notify that a new character has been |
| // processed |
| // tabulation(PositionT& pos) - Notify that a tab character has been |
| // processed |
| // next_line(PositionT& pos) - Notify that a new line delimiter has |
| // been reached. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| template <typename PositionT> class position_policy; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} /* namespace BOOST_SPIRIT_CLASSIC_NS */ |
| |
| |
| // This must be included here for full compatibility with old MSVC |
| #include "boost/spirit/home/classic/iterator/impl/position_iterator.ipp" |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // position_iterator |
| // |
| // It wraps an iterator, and keeps track of the current position in the input, |
| // as it gets incremented. |
| // |
| // The wrapped iterator must be at least a Forward iterator. The position |
| // iterator itself will always be a non-mutable Forward iterator. |
| // |
| // In order to have begin/end iterators constructed, the end iterator must be |
| // empty constructed. Similar to what happens with stream iterators. The begin |
| // iterator must be constructed from both, the begin and end iterators of the |
| // wrapped iterator type. This is necessary to implement the lookahead of |
| // characters necessary to parse CRLF sequences. |
| // |
| // In order to extract the current positional data from the iterator, you may |
| // use the get_position member function. |
| // |
| // You can also use the set_position member function to reset the current |
| // position to something new. |
| // |
| // The structure that holds the current position can be customized through a |
| // template parameter, and the class position_policy must be specialized |
| // on the new type to define how to handle it. Currently, it's possible |
| // to choose between the file_position and file_position_without_column |
| // (which saves some overhead if managing current column is not required). |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| #if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \ |
| BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200 |
| #error "Please use at least Boost V1.31.0 while compiling the position_iterator class!" |
| #else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200 |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // Uses the newer iterator_adaptor version (should be released with |
| // Boost V1.31.0) |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| template < |
| typename ForwardIteratorT, |
| typename PositionT, |
| typename SelfT |
| > |
| class position_iterator |
| : public iterator_::impl::position_iterator_base_generator< |
| SelfT, |
| ForwardIteratorT, |
| PositionT |
| >::type, |
| public position_policy<PositionT> |
| { |
| private: |
| |
| typedef position_policy<PositionT> position_policy_t; |
| typedef typename iterator_::impl::position_iterator_base_generator< |
| SelfT, |
| ForwardIteratorT, |
| PositionT |
| >::type base_t; |
| typedef typename iterator_::impl::position_iterator_base_generator< |
| SelfT, |
| ForwardIteratorT, |
| PositionT |
| >::main_iter_t main_iter_t; |
| |
| public: |
| |
| typedef PositionT position_t; |
| |
| position_iterator() |
| : _isend(true) |
| {} |
| |
| position_iterator( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end) |
| : base_t(begin), _end(end), _pos(PositionT()), _isend(begin == end) |
| {} |
| |
| template <typename FileNameT> |
| position_iterator( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end, |
| FileNameT fileName) |
| : base_t(begin), _end(end), _pos(PositionT(fileName)), |
| _isend(begin == end) |
| {} |
| |
| template <typename FileNameT, typename LineT> |
| position_iterator( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end, |
| FileNameT fileName, LineT line) |
| : base_t(begin), _end(end), _pos(PositionT(fileName, line)), |
| _isend(begin == end) |
| {} |
| |
| template <typename FileNameT, typename LineT, typename ColumnT> |
| position_iterator( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end, |
| FileNameT fileName, LineT line, ColumnT column) |
| : base_t(begin), _end(end), _pos(PositionT(fileName, line, column)), |
| _isend(begin == end) |
| {} |
| |
| position_iterator( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end, |
| const PositionT& pos) |
| : base_t(begin), _end(end), _pos(pos), _isend(begin == end) |
| {} |
| |
| position_iterator(const position_iterator& iter) |
| : base_t(iter.base()), position_policy_t(iter), |
| _end(iter._end), _pos(iter._pos), _isend(iter._isend) |
| {} |
| |
| position_iterator& operator=(const position_iterator& iter) |
| { |
| base_t::operator=(iter); |
| position_policy_t::operator=(iter); |
| _end = iter._end; |
| _pos = iter._pos; |
| _isend = iter._isend; |
| return *this; |
| } |
| |
| void set_position(PositionT const& newpos) { _pos = newpos; } |
| PositionT& get_position() { return _pos; } |
| PositionT const& get_position() const { return _pos; } |
| |
| void set_tabchars(unsigned int chars) |
| { |
| // This function (which comes from the position_policy) has a |
| // different name on purpose, to avoid messing with using |
| // declarations or qualified calls to access the base template |
| // function, which might break some compilers. |
| this->position_policy_t::set_tab_chars(chars); |
| } |
| |
| private: |
| friend class boost::iterator_core_access; |
| |
| void increment() |
| { |
| typename base_t::reference val = *(this->base()); |
| if (val == '\n') { |
| ++this->base_reference(); |
| this->next_line(_pos); |
| static_cast<main_iter_t &>(*this).newline(); |
| } |
| else if ( val == '\r') { |
| ++this->base_reference(); |
| if (this->base_reference() == _end || *(this->base()) != '\n') |
| { |
| this->next_line(_pos); |
| static_cast<main_iter_t &>(*this).newline(); |
| } |
| } |
| else if (val == '\t') { |
| this->tabulation(_pos); |
| ++this->base_reference(); |
| } |
| else { |
| this->next_char(_pos); |
| ++this->base_reference(); |
| } |
| |
| // The iterator is at the end only if it's the same |
| // of the |
| _isend = (this->base_reference() == _end); |
| } |
| |
| template < |
| typename OtherDerivedT, typename OtherIteratorT, |
| typename V, typename C, typename R, typename D |
| > |
| bool equal(iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D> |
| const &x) const |
| { |
| OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x); |
| bool x_is_end = rhs._isend; |
| |
| return (_isend == x_is_end) && (_isend || this->base() == rhs.base()); |
| } |
| |
| protected: |
| |
| void newline(void) |
| {} |
| |
| ForwardIteratorT _end; |
| PositionT _pos; |
| bool _isend; |
| }; |
| |
| #endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200 |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // position_iterator2 |
| // |
| // Equivalent to position_iterator, but it is able to extract the current |
| // line into a string. This is very handy for error reports. |
| // |
| // Notice that the footprint of this class is higher than position_iterator, |
| // (how much depends on how bulky the underlying iterator is), so it should |
| // be used only if necessary. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| template |
| < |
| typename ForwardIteratorT, |
| typename PositionT |
| > |
| class position_iterator2 |
| : public position_iterator |
| < |
| ForwardIteratorT, |
| PositionT, |
| position_iterator2<ForwardIteratorT, PositionT> |
| > |
| { |
| typedef position_iterator |
| < |
| ForwardIteratorT, |
| PositionT, |
| position_iterator2<ForwardIteratorT, PositionT> // JDG 4-15-03 |
| > base_t; |
| |
| public: |
| typedef typename base_t::value_type value_type; |
| typedef PositionT position_t; |
| |
| position_iterator2() |
| {} |
| |
| position_iterator2( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end): |
| base_t(begin, end), |
| _startline(begin) |
| {} |
| |
| template <typename FileNameT> |
| position_iterator2( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end, |
| FileNameT file): |
| base_t(begin, end, file), |
| _startline(begin) |
| {} |
| |
| template <typename FileNameT, typename LineT> |
| position_iterator2( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end, |
| FileNameT file, LineT line): |
| base_t(begin, end, file, line), |
| _startline(begin) |
| {} |
| |
| template <typename FileNameT, typename LineT, typename ColumnT> |
| position_iterator2( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end, |
| FileNameT file, LineT line, ColumnT column): |
| base_t(begin, end, file, line, column), |
| _startline(begin) |
| {} |
| |
| position_iterator2( |
| const ForwardIteratorT& begin, |
| const ForwardIteratorT& end, |
| const PositionT& pos): |
| base_t(begin, end, pos), |
| _startline(begin) |
| {} |
| |
| position_iterator2(const position_iterator2& iter) |
| : base_t(iter), _startline(iter._startline) |
| {} |
| |
| position_iterator2& operator=(const position_iterator2& iter) |
| { |
| base_t::operator=(iter); |
| _startline = iter._startline; |
| return *this; |
| } |
| |
| ForwardIteratorT get_currentline_begin(void) const |
| { return _startline; } |
| |
| ForwardIteratorT get_currentline_end(void) const |
| { return get_endline(); } |
| |
| std::basic_string<value_type> get_currentline(void) const |
| { |
| return std::basic_string<value_type> |
| (get_currentline_begin(), get_currentline_end()); |
| } |
| |
| protected: |
| ForwardIteratorT _startline; |
| |
| friend class position_iterator<ForwardIteratorT, PositionT, |
| position_iterator2<ForwardIteratorT, PositionT> >; |
| |
| ForwardIteratorT get_endline() const |
| { |
| ForwardIteratorT endline = _startline; |
| while (endline != this->_end && *endline != '\r' && *endline != '\n') |
| { |
| ++endline; |
| } |
| return endline; |
| } |
| |
| void newline(void) |
| { _startline = this->base(); } |
| }; |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} // namespace BOOST_SPIRIT_CLASSIC_NS |
| |
| #endif |