import java.io.*;

// Tokenizer
public class CS211In implements CS211InInterface {

	// Instance variable declarations 
	
	String Name;
	InputStream in;
	boolean reading_file = false;
	StreamTokenizer tokens;
	boolean errorp = false; //To avoid multiple error messages

	//Open a file for input
	public CS211In (String FileName) {
		try { 
			Name = FileName;
			in = new FileInputStream(FileName);
			reading_file = true;
			Reader r = new BufferedReader(new InputStreamReader(in));
			tokens = new StreamTokenizer(r);
			tokens.wordChars(':',':');
		} catch (Exception e) { //Do not report any exceptions
			System.out.println("ERROR: Unable to open file " + FileName + " for input\n");
			errorp = true;
		}
	}
        
	//Open a Reader for input
	public CS211In (Reader r) {
		Name = "string";
		tokens = new StreamTokenizer(r);
		tokens.wordChars(':',':');
	}

	//Get an integer from file
	public int getInt () {
		try {
			if (tokens.nextToken() == tokens.TT_NUMBER)
			    return (int)tokens.nval;
			else
			    throw new Exception();
		} catch (Exception e) {
			if (! errorp)
			    System.out.println("ERROR: Attempt to read a non-integer value as an integer\n");
			errorp = true;
			return 0;
		}
	 }

	//Get a word from file
	public String getWord () {
		try {
			if (tokens.nextToken() == tokens.TT_WORD)
			    return tokens.sval;
			else 
                throw new Exception();
		} catch (Exception e) {
			if (! errorp)
			    System.out.println("ERROR: Attempt to read a non-word value as a word\n");
			errorp = true;
			return "";
		}
	}

	//Get an operator (!(wordChar,numberChar,EOF)) from file
	public char getOp () {
		try {
		   if ((tokens.nextToken() != tokens.TT_NUMBER)
		       && (tokens.ttype != tokens.TT_WORD)
		       && (tokens.ttype != tokens.TT_EOF))
		       return (char)tokens.ttype;
		   else
               throw new Exception();
		} catch (Exception e) {
			if (! errorp) 
			    System.out.println("ERROR: Attempt to read non-operator value as an operator\n");
			errorp = true;
			return (char)0;
		}
	}

	//Peek at the next token and return its "kind"
	public int peekAtKind () { //look at kind of next token w/o eating it
		try {
			int kind = tokens.nextToken();
			switch (kind) {
				case tokens.TT_EOF:    tokens.pushBack(); return EOF;
				case tokens.TT_NUMBER: tokens.pushBack(); return INTEGER;
				case tokens.TT_WORD:   tokens.pushBack(); return WORD;
				default:               tokens.pushBack(); return OPERATOR; //character found
			}
		} catch (Exception e) {
		    if (! errorp) 
		        System.out.println("ERROR: Unable to peek into file " + Name);
		    errorp = true;
		    return 0;
		}
	}

	//Make sure next token in input is operator c
	public void match(char c) {
		char n;
		if (peekAtKind() == OPERATOR) {
            n = getOp();
		    if (n == c)
                return;
		    else {
                System.out.println(
		        "Expecting " + c + " but found " + n + " in Line " + lineNo());
		        return;
		    }
		} else
            System.out.println("Did not find " + c + " in Line " + lineNo());
	}

	//Make sure next token in input is word s
	public void match(String s) {
		String n;
		if (peekAtKind() == WORD) {
            n = getWord();
			if (n.equals(s))
                return;
			else {
                System.out.println("Expecting " + s + " but found " +
                                   n + " in Line " + lineNo());
			    return;
			}
	    } else
            System.out.println("Did not find " + s + " in Line " + lineNo());
	}

	public boolean check(char c) {
		//Look for c but don't panic if you don't find it
		if (peekAtKind() == OPERATOR) {
            char n = getOp();
		    if (n == c) 
                return true;
		    else {
                pushBack();
                return false;
            }
		} else 
            return false;
	}

	public boolean check(String s) {
		//Look for s but don't panic if you don't find it
		if (peekAtKind() == WORD) {
            String n = getWord();
		    if (n.equals(s)) 
                return true;
		    else {
                pushBack();
                return false;
            }
		} else 
            return false;
	}

	//Pushes one token back into input stream
	public void pushBack() { tokens.pushBack(); }

    // Return the line number
    public int lineNo()    { return tokens.lineno(); }

	//Close file
	public void close () {
		if (reading_file)
			try { in.close(); }
			catch (Exception e) {
			    if (! errorp)
			        System.out.println("Error: Unable to close file " + Name);
			    errorp = true;
			}
	}
}