transcendental-lisp/src/scanner/LispCommentRemovingInputStream.java

81 lines
2.1 KiB
Java

package scanner;
import static util.Characters.*;
import java.io.InputStream;
import stream.SafeInputStream;
/**
* Removes Lisp comments from an input stream.
*/
public class LispCommentRemovingInputStream implements LispInputStream {
private SafeInputStream underlyingInputStream;
private boolean isInQuotedString;
private boolean rereadLastCharacter;
private int previousCharacter;
private int currentCharacter;
public LispCommentRemovingInputStream(InputStream underlyingInputStream) {
this.underlyingInputStream = new SafeInputStream(underlyingInputStream);
this.isInQuotedString = false;
this.rereadLastCharacter = false;
this.previousCharacter = 0;
this.currentCharacter = 0;
}
@Override
public int read() {
if (!rereadLastCharacter)
return readFromUnderlyingInputStream();
rereadLastCharacter = false;
return currentCharacter;
}
private int readFromUnderlyingInputStream() {
readNextCharacter();
if (haveEnteredComment())
consumeAllBytesInComment();
return currentCharacter;
}
private void readNextCharacter() {
previousCharacter = currentCharacter;
currentCharacter = underlyingInputStream.read();
if (haveEncounteredStringBoundary())
isInQuotedString = !isInQuotedString;
}
private boolean haveEncounteredStringBoundary() {
return (previousCharacter != BACKSLASH) && (currentCharacter == DOUBLE_QUOTE);
}
private boolean haveEnteredComment() {
return (currentCharacter == SEMICOLON) && (!isInQuotedString);
}
private void consumeAllBytesInComment() {
while (stillInComment())
currentCharacter = underlyingInputStream.read();
}
private boolean stillInComment() {
return (currentCharacter != NEWLINE) && (currentCharacter != EOF);
}
@Override
public void unreadLastCharacter() {
if (rereadLastCharacter)
throw new MaximumUnreadsExceededException();
this.rereadLastCharacter = true;
}
}