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; } }