All Downloads are FREE. Search and download functionalities are using the official Maven repository.

aima.core.logic.common.Lexer Maven / Gradle / Ivy

package aima.core.logic.common;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

/**
 * An abstract base class for constructing lexical analyzers for knowledge
 * representation languages. It provides a mechanism for converting a sequence
 * of characters to a sequence of tokens that are meaningful in the
 * representation language of interest.
 * 
 * @author Ravi Mohan
 * @author Ciaran O'Reilly
 * @author Mike Stampone
 */
public abstract class Lexer {
	protected int lookAheadBufferSize = 1;
	//
	private static final int END_OF_INPUT = -1;
	//
	private Reader input;
	private int[] lookAheadBuffer;
	private int currentPositionInInput;

	/**
	 * Sets the character stream of the lexical analyzer.
	 * 
	 * @param inputString
	 *            a sequence of characters to be converted into a sequence of
	 *            tokens.
	 */
	public void setInput(String inputString) {
		setInput(new StringReader(inputString));
	}

	/**
	 * Set the character stream reader of the lexical analyzer.
	 * 
	 * @param inputReader
	 *            a reader on a sequence of characters to be converted into a
	 *            sequence of tokens.
	 */
	public void setInput(Reader inputReader) {
		input = inputReader;
		lookAheadBuffer = new int[lookAheadBufferSize];
		currentPositionInInput = 0;
		initializeLookAheadBuffer();
	}

	/**
	 * To be implemented by concrete implementations
	 * 
	 * @return the next token from the input.
	 */
	public abstract Token nextToken();

	//
	// PROTECTED
	//
	protected int getCurrentPositionInInput() {
		return currentPositionInInput;
	}

	/*
	 * Returns the character at the specified position in the lookahead buffer.
	 */
	protected char lookAhead(int position) {
		return (char) lookAheadBuffer[position - 1];
	}

	/**
	 * Consume 1 character from the input.
	 */
	protected void consume() {
		currentPositionInInput++;
		loadNextCharacterFromInput();
	}

	//
	// PRIVATE
	//

	/**
	 * Returns true if the end of the stream has been reached.
	 */
	private boolean isEndOfInput(int i) {
		return (END_OF_INPUT == i);
	}

	/**
	 * Initialize the look ahead buffer from the input.
	 */
	private void initializeLookAheadBuffer() {
		for (int i = 0; i < lookAheadBufferSize; i++) {
			// Mark th entire buffer as being end of input.
			lookAheadBuffer[i] = END_OF_INPUT;
		}
		for (int i = 0; i < lookAheadBufferSize; i++) {
			// Now fill the buffer (if possible) from the input.
			lookAheadBuffer[i] = readInput();
			if (isEndOfInput(lookAheadBuffer[i])) {
				// The input is smaller than the buffer size
				break;
			}
		}
	}

	/**
	 * Loads the next character into the lookahead buffer if the end of the
	 * stream has not already been reached.
	 */
	private void loadNextCharacterFromInput() {
		boolean eoiEncountered = false;
		for (int i = 0; i < lookAheadBufferSize - 1; i++) {
			lookAheadBuffer[i] = lookAheadBuffer[i + 1];
			if (isEndOfInput(lookAheadBuffer[i])) {
				eoiEncountered = true;
				break;
			}
		}
		if (!eoiEncountered) {
			lookAheadBuffer[lookAheadBufferSize - 1] = readInput();
		}
	}

	private int readInput() {
		int read = -1;

		try {
			read = input.read();
		} catch (IOException ioe) {
			throw new LexerException("IOException thrown reading input.",
					currentPositionInInput, ioe);
		}

		return read;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy