161 lines
5.1 KiB
Java
161 lines
5.1 KiB
Java
/*
|
|
* Name: Mike Cifelli
|
|
* Course: CIS 443 - Programming Languages
|
|
* Assignment: Lisp Interpreter Phase 1 - Lexical Analysis
|
|
*/
|
|
|
|
package scanner;
|
|
|
|
import java.io.InputStream;
|
|
import java.io.FilterInputStream;
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* A <code>LispFilterStream</code> is an input stream that returns the bytes
|
|
* from an underlying input stream with all Lisp comments removed and replaced
|
|
* with newlines.
|
|
*/
|
|
public class LispFilterStream extends FilterInputStream {
|
|
|
|
private boolean inQuote;
|
|
|
|
/**
|
|
* Creates a <code>LispFilterStream</code> with the specified underlying
|
|
* <code>InputStream</code>.
|
|
*
|
|
* @param in
|
|
* the underlying input stream (must not be <code>null</code>)
|
|
*/
|
|
public LispFilterStream(InputStream in) {
|
|
super(in);
|
|
|
|
inQuote = false;
|
|
}
|
|
|
|
/**
|
|
* Reads the next byte of data from this input stream. The value byte is
|
|
* returned as an <code>int</code> in the range <code>0</code> to
|
|
* <code>255</code>. If no byte is available because the end of the stream
|
|
* has been reached, the value <code>-1</code> is returned.
|
|
*
|
|
* @return
|
|
* the next byte of data, or <code>-1</code> if the end of the stream has
|
|
* been reached.
|
|
* @throws IOException
|
|
* Indicates that an I/O error has occurred.
|
|
*/
|
|
@Override
|
|
public int read() throws IOException {
|
|
int next = super.read();
|
|
|
|
if ((next == ';') && (! inQuote)) {
|
|
// we have entered a comment, consume all the bytes from the
|
|
// underlying input stream until we reach a newline character or
|
|
// the end of the stream
|
|
while ((next != '\n') && (next != -1)) {
|
|
next = super.read();
|
|
}
|
|
} else if (next == '\n') {
|
|
inQuote = false;
|
|
} else if (next == '\"') { // we have entered or left a quoted string
|
|
inQuote = (! inQuote);
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
/**
|
|
* Reads up to the specified number of data bytes from this input stream
|
|
* into an array of bytes starting at the specified offset. If no bytes are
|
|
* available because the end of this stream has been reached then
|
|
* <code>-1</code> is returned. Also, If the specified number of bytes is
|
|
* more than the number of remaining data bytes in this input stream, then
|
|
* only the number of remaining data bytes are copied into the byte array.
|
|
*
|
|
* @param b
|
|
* the buffer into which the data bytes are read (must not be
|
|
* <code>null</code>)
|
|
* @param off
|
|
* the start offset in <code>b</code> at which the data is written (must
|
|
* be <code>>= 0</code> and <code>< b.length</code>)
|
|
* @param len
|
|
* the maximum number of bytes to read into <code>b</code> (<code>len +
|
|
* off</code> must be <code>< b.length</code>)
|
|
* @return
|
|
* the total number of bytes read into the buffer, or <code>-1</code> if
|
|
* there is no more data because the end of the stream has been reached
|
|
* @throws IOException
|
|
* Indicates that the first byte could not be read into <code>b</code>
|
|
* for some reason other than reaching the end of the stream.
|
|
* @throws IndexOutOfBoundsException
|
|
* Indicates that this method attempted to access an index in
|
|
* <code>b</code> that was either negative or greater than or equal to
|
|
* <code>b.length</code> as a result of the given parameters.
|
|
* @throws NullPointerException
|
|
* Indicates that <code>b</code> is <code>null</code>.
|
|
*/
|
|
@Override
|
|
public int read(byte[] b, int off, int len) throws IOException {
|
|
int bytesRead = 0;
|
|
|
|
// make sure we are supposed to read at least one byte into 'b'
|
|
if (len > 0) {
|
|
int next = read();
|
|
|
|
if (next == -1) {
|
|
// there are no more bytes to read from this input stream
|
|
|
|
return -1;
|
|
}
|
|
|
|
int i = off;
|
|
|
|
while (next != -1) {
|
|
++bytesRead;
|
|
|
|
b[i++] = (byte) next;
|
|
|
|
if (i >= (off + len)) { // we have read 'len' bytes into 'b'
|
|
break;
|
|
}
|
|
|
|
try {
|
|
next = read();
|
|
} catch (IOException e) {
|
|
// treat this exception like an end of stream
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bytesRead;
|
|
}
|
|
|
|
/**
|
|
* Skip over and discard the specified number of bytes from this input
|
|
* stream. This method may, for a variety of reasons, end up skipping some
|
|
* smaller number of bytes, possibly <code>0</code>. The actual number of
|
|
* bytes skipped is returned.
|
|
*
|
|
* @param n
|
|
* the number of bytes to be skipped
|
|
* @return
|
|
* the actual number of bytes skipped
|
|
* @throws IOException
|
|
* Indicates that an I/O error has occurred.
|
|
*/
|
|
@Override
|
|
public long skip (long n) throws IOException {
|
|
long bytesSkipped = 0;
|
|
|
|
while ((n > 0) && (read() != -1)) {
|
|
++bytesSkipped;
|
|
--n;
|
|
}
|
|
|
|
return bytesSkipped;
|
|
}
|
|
|
|
}
|