aima.core.logic.common.Parser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aima-core Show documentation
Show all versions of aima-core Show documentation
AIMA-Java Core Algorithms from the book Artificial Intelligence a Modern Approach 3rd Ed.
package aima.core.logic.common;
import java.io.Reader;
import java.io.StringReader;
/**
* An abstract base class for constructing parsers for knowledge representation
* languages. It provides a mechanism for converting a sequence of tokens
* (derived from an appropriate lexer) into a syntactically correct abstract
* syntax tree of the representation language.
*
* @author Ravi Mohan
* @author Ciaran O'Reilly
*
* @param the root type of the abstract syntax tree being parsed.
*/
public abstract class Parser {
protected int lookAheadBufferSize = 1;
//
private Token[] lookAheadBuffer = null;
/**
*
* @return an instance of the Lexer to be used by a concrete implementation
* of this class.
*/
public abstract Lexer getLexer();
/**
* Parse the input concrete syntax into an abstract syntax tree.
*
* @param input
* a string representation of the concrete syntax to be parsed.
* @return the root node of an abstract syntax tree representation of the
* the concrete input syntax that was parsed.
*/
public S parse(String input) {
return parse(new StringReader(input));
}
/**
* Parse the input concrete syntax into an abstract syntax tree.
*
* @param inputReader
* a Reader of the concrete syntax to be parsed.
* @return the root node of an abstract syntax tree representation of the
* the concrete input syntax that was parsed.
*/
public S parse(Reader inputReader) {
S result = null;
try {
getLexer().setInput(inputReader);
initializeLookAheadBuffer();
result = parse();
} catch (LexerException le) {
throw new ParserException("Lexer Exception thrown during parsing at position "+le.getCurrentPositionInInputExceptionThrown(), le);
}
return result;
}
//
// PROTECTED
//
/**
* To be implemented by concrete implementations of this class.
*
* @return the root node of an abstract syntax tree representation of the
* the concrete input syntax that was parsed.
*/
protected abstract S parse();
/**
* @return the token at the specified position in the lookahead buffer.
*/
protected Token lookAhead(int i) {
return lookAheadBuffer[i - 1];
}
/**
* Consume 1 token from the input.
*/
protected void consume() {
loadNextTokenFromInput();
}
/**
* Consume the given match symbol if it matches the current input token. If
* it does not match throws a ParserException detailing the match error.
*
* @param toMatchSymbol
* the symbol to match before consuming it.
*/
protected void match(String toMatchSymbol) {
if (lookAhead(1).getText().equals(toMatchSymbol)) {
consume();
} else {
throw new ParserException(
"Parser: Syntax error detected at match. Expected "
+ toMatchSymbol + " but got "
+ lookAhead(1).getText(), lookAhead(1));
}
}
//
// PRIVATE
//
private void initializeLookAheadBuffer() {
lookAheadBuffer = new Token[lookAheadBufferSize];
for (int i = 0; i < lookAheadBufferSize; i++) {
// Now fill the buffer (if possible) from the input.
lookAheadBuffer[i] = getLexer().nextToken();
if (isEndOfInput(lookAheadBuffer[i])) {
// The input is smaller than the buffer size
break;
}
}
}
/*
* Loads the next token into the lookahead buffer if the end of the stream
* has not already been reached.
*/
private void loadNextTokenFromInput() {
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] = getLexer().nextToken();
}
}
/*
* Returns true if the end of the stream has been reached.
*/
private boolean isEndOfInput(Token t) {
return (t == null || t.getType() == LogicTokenTypes.EOI);
}
}