/**
 * A stream of characters.  Intended to serve as the input
 * to a tokenizer.  Might be implemented in a variety of ways
 * (e.g., taking input from a file or string).  This "advanced"
 * version also gives access to the line and position of the
 * current character.
 *
 * Advanced character streams are built from basic character 
 * streams.
 *
 * @author Samuel A. Rebelsky
 * @version 0.1 of 18 July 2002
 */
public class AdvCharStream 
  implements CharStream
{
  // +--------+-------------------------------------------------------------
  // | Fields |
  // +--------+

  /**
   * The stream that is used as the basis of this stream.
   */
  private CharStream base;

  /**
   * The number of the current line.
   */
  private int curline;

  /**
   * The position on the current line.
   */
  private int curpos;


  // +--------------+-------------------------------------------------------
  // | Constructors |
  // +--------------+

  /**
   * Create an advanced character stream using a basic character
   * stream as the basis.  The advanced stream adds the ability 
   * to get the current line and position.
   */
  public AdvCharStream(CharStream baseStream) {
    this.base = baseStream;
    this.curline = 1;
    this.curpos = 1;
  } // AdvCharStream(CharStream)


  // +-----------+----------------------------------------------------------
  // | Observers |
  // +-----------+

  /**
   * Determine if any more characters remain in the stream.
   *
   * Pre: (none).
   * Post: Returns true if characters remain and false o/w.
   */
  public boolean hasMore() {
    return this.base.hasMore();
  } // hasMore()

  /**
   * Look at the next character in the stream, but do not advance
   * the stream.
   *
   * Pre: The stream has a next character.
   * Post: Returns that character.  Does not affect the stream.
   *
   * @exception Exception 
   *   if no characters remain.
   */
  public char peek() throws EndOfStream,Exception {
    return this.base.peek();
  } // peek()

  /**
   * Determine the current line number.
   */
  public int line() {
    return this.curline;
  } // line()

  /**
   * Determine the position within the current line.
   */
  public int pos() {
    return this.curpos;
  } // pos()


  // +-----------+----------------------------------------------------------
  // | Modifiers |
  // +-----------+

  /**
   * Get the next character from the stream and advance the stream.
   *
   * Pre: The stream has a next character.
   * Post: The stream has advanced beyond that character.
   *
   * @exception EndOfStream
   *   if no characters remain.
   * @exception Exception
   *   if some I/O error occurs.
   */
  public char next() 
    throws EndOfStream, Exception
  {
    char ch = base.next();
    if (ch == '\n') {
      this.curline++;
      this.curpos = 1;
    }
    else {
      this.curpos++;
    }
    return ch;
  } // next()

} // class AdvCharStream

