package prolog.syntax;

import java.io.*;
import prolog.model.*;

public class Scanner
{
	protected Reader source = null;
	protected StringBuffer currentWord = new StringBuffer();
	protected int currentChar = -1;

	protected int currentLine = 0;
	protected int currentSign = 0;

	protected ISymbolTable symbolTable = null;

	public Scanner( ISymbolTable table )
	{
		this.symbolTable = table;
	}

	public void reset()
	{
		source = null;
		currentWord.setLength( 0 );

		currentChar = -1;
		currentLine = 0;
		currentSign = 0;
		symbolTable.clear();
	}

	public void openDocument( File f )
		throws FileNotFoundException
	{
		source = new BufferedReader( new FileReader( f ) );
	}

	public void openDocument( String text )
	{
		source = new StringReader( text );
	}

	public void openDocument( Reader input )
	{
		source = input;
	}

	public void close()
		throws IOException
	{
		if( source != null )
		{
			source.close();
			source = null;
		}
	}

	public int getCurrentChar()
	{
		return this.currentChar;
	}

	public int getCurrentWord()
	{
		return this.symbolTable.encode( currentWord.toString() );
	}

	public int input()
	{
		if( source == null )
			throw new RuntimeException(
				"You should open a source before parsing ;-)" );
		try
		{
			currentChar = source.read();
			currentSign++;
			if( currentChar == '\n' )
			{
				currentLine++;
				currentSign = 0;
			}
			else if( this.isCurrentWhiteSpace() )
				skipWhiteSpace();
		}
		catch( Exception ae )
		{
			ae.printStackTrace();
		}
		return currentChar;
	}

	public int getCurrentLine()
	{
		return this.currentLine;
	}

	public int getCurrentSign()
	{
		return this.currentSign;
	}

	public void skipWhiteSpace()
	{
		do
		{
			input();
		}
		while( isCurrentWhiteSpace() );
	}

	public boolean test( char c )
	{
		if( this.currentChar == -1 )
			return false;
		else return c==((char)currentChar);
	}

	public boolean isCurrentChar()
	{
		return
			(('a' <= currentChar) && (currentChar <= 'z')) ||
			(('A' <= currentChar) && (currentChar <= 'Z')) ||
			(('0' <= currentChar) && (currentChar <= '9')) ||
			(currentChar == '_');
	}

	public boolean isCurrentWhiteSpace()
	{
		return
			((char)currentChar) == ' ' ||
			((char)currentChar) == '\n';
	}

	public void scanWord()
	{
		currentWord.setLength (0);
		do // collect a..zA..Z0..9_
		{
			currentWord.append( (char)currentChar );
			input();
		}
		while( isCurrentChar() );
	}
}
