import java.io.*;

class Lexer {
    DataInputStream inStream;
    Token currentToken;
    boolean replacedTokenExists;
    Token replacedToken;
    
    Lexer(DataInputStream in) {
	replacedTokenExists = false;
	replacedToken = null;
	inStream = in;
    }
    
    // Read next symbol/keyword, return as Token.
    // Remember what it was in case we want to inspect it again.
    // If a token has been pushed back onto the input, return that instead

    Token nextToken() throws IOException {
	if (replacedTokenExists) {
	    replacedTokenExists = false;
	    currentToken = replacedToken;
	    return replacedToken;
	} else {
	    String word = getWord();
	    currentToken = new Token(word);
	    return currentToken;
	}
    }
    Token getLastToken() {
	if (currentToken == null) {
	    System.out.println("currentToken is null");
	}
	return currentToken;
    }
    void replaceToken(Token t) {
	if (replacedTokenExists) {
	    System.out.println("replaceToken() called twice, token lost");
	}
	replacedTokenExists = true;
	replacedToken = t;
    }
    void match(int expectedTokenId) throws IOException {
	Token t = nextToken();
	if (t.tokenId != expectedTokenId) {
	    System.out.println("Syntax error: "+Token.name(expectedTokenId)+
			       " expected, but "+t.string+" found");
	}
    }
    /**
     * Get the next space(etc)-separated word/number from the stream
     */
    String getWord() 
	throws IOException
    {
	String theWord = new String();
	char ch = (char) inStream.readByte();
	// skip blanks and comment lines
	while (IsSkippable(ch)) { 
	    ch = (char) inStream.readByte(); 
	}
	while(!IsSkippable(ch)) {
	    theWord = theWord+ch;
	    ch = (char) inStream.readByte();
	}
	return theWord;
    }
    private static boolean IsSkippable(char ch) {
	return (ch == ' ') || (ch == '#') || (ch == '\n') 
	    || (ch == '\r') || (ch == '\t');
    }
}
