Check-in [ca08e3a704]

Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview

SHA1 Hash:ca08e3a704640f5ad6dac399b36c97df70952dc7
Date: 2008-06-21 10:57:43
User: stephan
Comment:added missing include

Tags And Properties
Changes
[hide diffs]

Changes to parsepp.hpp

@@ -4,10 +4,11 @@
 #include <map>
 #include <string>
 #include <cassert>
 #include <iostream>
 #include <sstream>
+#include <stdexcept>
 #include <vector>
 #include <list>
 #include <set>
 
 #include "parsepp_typelist.hpp"
@@ -189,26 +190,28 @@
        - parse_iterators are read-only iterators. They cannot be used
        to change their input.
     */
     class parse_iterator : public std::iterator<std::input_iterator_tag,const std::string::value_type>
     {
+    private:
+	static const int start_column = 1;
     public:
 	typedef std::string::const_iterator iterator;
 	/**
 	   Constructs an empty iterator, useful only as the target
 	   of an assignment.
 	*/
-	parse_iterator() : m_beg(), m_pos(), m_end(m_pos)
+	parse_iterator() : m_beg(), m_pos(), m_end(m_pos), m_line(1), m_col(start_column)
 	{}
 	/**
 	   Constructs an iterator for the range [it,end). The string
 	   pointed-to by (it,end) must not change (or otherwise
 	   invalid the iterators) for the life of this object, or
 	   undefined behaviour results.
 	*/
 	parse_iterator( iterator it, iterator end )
-	    : m_beg(it), m_pos(it), m_end(end)
+	    : m_beg(it), m_pos(it), m_end(end), m_line(1), m_col(start_column)
 	{}
 	/**
 	   Equivalent to the parse_iterator(in.begin(),in.end()).
 
 	   Note that the input string must outlive this
@@ -215,11 +218,12 @@
 	   iterator. Also, the string MUST NOT change for the life of
 	   this iterator (and any copies of this iterator). Changing
 	   the string invalidates all iterators.
 	*/
 	explicit parse_iterator( std::string const & in )
-	    : m_beg(in.begin()),m_pos(m_beg), m_end(in.end())
+	    : m_beg(in.begin()),m_pos(m_beg), m_end(in.end()),
+	      m_line(1), m_col(start_column)
 	{}
 
 	/**
 	   Returns true if this object has been advanced
 	   to its end iterator or if the current
@@ -273,13 +277,28 @@
 	   input (i.e., ++iterator becomes a no-op once iterator.eof()
 	   is true).
 	*/
  	parse_iterator & operator++()
  	{
-	    if( this->m_pos != this->m_end )
-	    {
-		++this->m_pos;
+	    if( m_pos != m_end )
+	    {
+		if( ++m_pos != m_end )
+		{
+		    if('\n' == *m_pos)
+		    {
+			m_line += 1;
+			m_col = 0;
+		    }
+		    else
+		    {
+			++m_col;
+		    }
+		}
+ 		else
+ 		{
+ 		    ++m_col; // for symmetry with op--
+ 		}
 	    }
  	    return *this;
  	}
 
 	/**
@@ -289,12 +308,12 @@
 	   See the Prefix form for notes about advancing past the end
 	   of the input.
 	*/
  	parse_iterator operator++(int)
  	{
-	    return ( this->m_pos != this->m_end )
-		? parse_iterator(this->m_pos++, this->m_end)
+	    return (this->m_pos != this->m_end )
+		? (++(parse_iterator(*this)))
 		: *this;
  	}
 
 	/**
 	   Prefix decrement. Decrements the iternal iterator.  It will
@@ -303,11 +322,33 @@
 	*/
  	parse_iterator & operator--()
  	{
 	    if( this->m_pos != this->m_beg )
 	    {
-		--this->m_pos;
+		if( m_beg != --m_pos )
+		{
+		    if('\n' == *m_pos)
+		    {
+			m_line -= 1;
+			m_col = 0;
+			iterator it = m_pos;
+			--it;
+			for( ; it != m_beg; --it )
+			{
+			    ++m_col;
+			    if( '\n' == *it ) break;
+			}
+		    }
+		    else
+		    {
+			--m_col;
+		    }
+		}
+		else
+		{
+		    m_col = 0;
+		}
 	    }
  	    return *this;
  	}
 
 	/** Postfix decrement. It will not decrement to a point
@@ -314,11 +355,11 @@
 	    before begin().
 	*/
  	parse_iterator operator--(int)
  	{
 	    return ( this->m_pos != this->m_beg )
-		? parse_iterator(this->m_pos--, this->m_end)
+		? (--(parse_iterator(*this)))
 		: *this;
  	}
 
 	/**
 	   Returns a copy of the pointed-to char, or 0 if
@@ -355,14 +396,33 @@
 	bool operator<( parse_iterator const & rhs ) const
 	{
 	    return this->m_pos < rhs.m_pos;
 	}
 
+	/**
+	   Returns the 1-based line number of this iterator. Counting starts
+	   only at the begin iterator this object was initialized with, and is
+	   updated via the ++/-- operators. If an itertor is used on a partial
+	   range of input, the line/col numbers won't reflect those of the
+	   whole input.
+	*/
+	int line() const { return m_line; }
+	/**
+	   Returns the 1-base column number of the input. When (*this == '\n')
+	   then col() actually returns 0, as doing so simplifies the implementation
+	   a good deal and seems to coincide with text editors which use row 1/col 1
+	   as a starting point (as opposed to emacs, which uses row 1/col 0).
+	   See line() for important caveats.
+	*/
+	int col() const { return m_col; }
+
     private:
 	iterator m_beg;
 	iterator m_pos;
 	iterator m_end;
+	int m_line;
+	int m_col;
     };
 
     /***
 	parser_state stores the "significant" information about a
 	parsing run, where "significant" means significant to the
@@ -597,12 +657,18 @@
     class parse_error : public std::exception
     {
     private:
 	void calcWhere()
 	{
+	    // these two options actually provide different column numbers:
+#if 0
 	    int line = 1, col = 0;
 	    calc_line_col( m_pos, line, col );
+#else
+	    int line = m_pos.line();
+	    int col = m_pos.col();
+#endif
 	    std::ostringstream os;
 	    os << "[line "<<line<<" col "<<col<<']';
 	    m_where = (os.str());
 	}