--- /dev/null
+/*==============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2010 Bryce Lelbach
+
+ 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)
+==============================================================================*/
+
+#if !defined(BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR)
+#define BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/range/iterator_range.hpp>
+
+namespace boost { namespace spirit
+{
+ //[line_pos_iterator_class
+ /*`The `line_pos_iterator` is a lightweight line position iterator.
+ This iterator adapter only stores the current line number, nothing else.
+ Unlike __classic__'s `position_iterator`, it does not store the
+ column number and does not need an end iterator. The current column can
+ be computed, if needed. */
+ //`[heading Class Reference]
+ template <class Iterator>
+ class line_pos_iterator : public boost::iterator_adaptor<
+ line_pos_iterator<Iterator> // Derived
+ , Iterator // Base
+ , boost::use_default // Value
+ , boost::forward_traversal_tag // CategoryOrTraversal
+ > {
+ public:
+ line_pos_iterator();
+
+ explicit line_pos_iterator(Iterator);
+
+ std::size_t position() const;
+
+ private:
+ friend class boost::iterator_core_access;
+
+ void increment();
+
+ std::size_t line; // The line position.
+ typename std::iterator_traits<Iterator>::value_type prev;
+ };
+ //]
+
+ template <class Iterator>
+ line_pos_iterator<Iterator>::line_pos_iterator() :
+ line_pos_iterator::iterator_adaptor_(), line(1), prev(0) { }
+
+ template <class Iterator>
+ line_pos_iterator<Iterator>::line_pos_iterator(Iterator base) :
+ line_pos_iterator::iterator_adaptor_(base), line(1), prev(0) { }
+
+ template <class Iterator>
+ std::size_t line_pos_iterator<Iterator>::position() const
+ {
+ return line;
+ }
+
+ template<class Iterator>
+ void line_pos_iterator<Iterator>::increment()
+ {
+ typename std::iterator_traits<Iterator>::reference
+ ref = *(this->base());
+
+ switch (ref) {
+ case '\r':
+ if (prev != '\n')
+ ++line;
+ break;
+ case '\n':
+ if (prev != '\r')
+ ++line;
+ break;
+ default:
+ break;
+ }
+
+ prev = ref;
+ ++this->base_reference();
+ }
+
+ //[line_pos_iterator_utilities
+ //`[heading get_line]
+ template <class Iterator>
+ inline std::size_t get_line(Iterator);
+ /*`Get the line position. Returns -1 if Iterator is not a
+ `line_pos_iterator`. */
+
+ //`[heading get_line_start]
+ template <class Iterator>
+ inline Iterator get_line_start(Iterator lower_bound, Iterator current);
+ /*`Get an iterator to the beginning of the line. Applicable to any
+ iterator. */
+
+ //`[heading get_current_line]
+ template <class Iterator>
+ inline iterator_range<Iterator>
+ get_current_line(Iterator lower_bound, Iterator current,
+ Iterator upper_bound);
+ /*`Get an `iterator_range` containing the current line. Applicable to any
+ iterator. */
+
+ //`[heading get_column]
+ template <class Iterator>
+ inline std::size_t get_column(Iterator lower_bound, Iterator current,
+ std::size_t tabs = 4);
+ /*`Get the current column. Applicable to any iterator. */
+ //]
+
+ template <class Iterator>
+ inline std::size_t get_line(Iterator)
+ {
+ return -1;
+ }
+
+ template <class Iterator>
+ inline std::size_t get_line(line_pos_iterator<Iterator> i)
+ {
+ return i.position();
+ }
+
+ template <class Iterator>
+ inline Iterator get_line_start(Iterator lower_bound, Iterator current)
+ {
+ Iterator latest = lower_bound;
+
+ for (Iterator i = lower_bound; i != current; ++i) {
+ switch (*i) {
+ case '\r':
+ case '\n':
+ latest = i;
+ }
+ }
+
+ return latest;
+ }
+
+ template <class Iterator>
+ inline iterator_range<Iterator>
+ get_current_line(Iterator lower_bound,
+ Iterator current,
+ Iterator upper_bound)
+ {
+ Iterator first = get_line_start(lower_bound, current);
+ Iterator last = get_line_start(current, upper_bound);
+
+ if (last == current)
+ last = upper_bound;
+
+ return iterator_range<Iterator>(first, last);
+ }
+
+ template <class Iterator>
+ inline std::size_t get_column(Iterator lower_bound,
+ Iterator current,
+ std::size_t tabs)
+ {
+ std::size_t column = 1;
+ Iterator first = get_line_start(lower_bound, current);
+
+ for (Iterator i = first; i != current; ++i) {
+ switch (*i) {
+ case '\t':
+ column += tabs - (column - 1) % tabs;
+ break;
+ default:
+ ++column;
+ }
+ }
+
+ return column;
+ }
+
+}}
+
+#endif // BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
+