package rebelsky.compiler.misc; import java.io.Reader; /** * A stream of characters created from a reader. * * @author Samuel A. Rebelsky * @version 0.2 of October 2002 */ public class StandardCharStream implements CharStream { // +-----------+---------------------------------------------------------- // | Constants | // +-----------+ /** The value used for end of file. Reader says that this is -1. */ private static int EOF = -1; /** The value used for "not defined" */ private static int UNDEF = -2; // +--------+------------------------------------------------------------- // | Fields | // +--------+ /** * The reader used for most of the real work. */ protected Reader reader; /** * The next character to read. Set to EOF when the end of file * is reached. Set to UNDEF when it's time to read another character. */ protected int buffer; // +--------------+------------------------------------------------------- // | Constructors | // +--------------+ /** * Build a new character stream from a reader. */ public StandardCharStream(Reader reader) { this.reader = reader; this.buffer = UNDEF; } // StandardCharStream(Reader) // +-----------------+---------------------------------------------------- // | Local Utilities | // +-----------------+ /** * Fill the buffer if it's not full. */ private void fillBuffer() { try { if (this.buffer == UNDEF) this.buffer = reader.read(); } catch (Exception e) { this.buffer = EOF; } } // fillBuffer // +-----------+---------------------------------------------------------- // | 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() { // Fill the buffer if necessary. this.fillBuffer(); // See whether or not the buffer includes an EOF character. return (this.buffer != EOF); } // hasMore(void) /** * 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 Exception { // Make sure the buffer is full. this.fillBuffer(); // Make sure that it's not empty. if (this.buffer == EOF) { throw new Exception("end of file"); } // Return it return (char) this.buffer; } // peek(void) // +-----------+---------------------------------------------------------- // | 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 Exception * if no characters remain. */ public char next() throws Exception { // Get the next character (let peek do the hard work). char ch = this.peek(); // Note that the buffer is now empty. this.buffer = UNDEF; // That's it. return ch; } // next() } // interface StandardCharStream