/*
 * LpParserException.java
 *
 * Copyright (C) 2006 - 2007 Martin Slota
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

/*
 * History:
 * v0.2 (2007-01-01): taken from proposition EVOLP implementation
 * v0.2.1 (2007-01-28):
 * - changed to an unchecked exception (see
 *   http://www.mindview.net/Etc/Discussions/CheckedExceptions)
 * - documentation updated
 * v0.2.2 (2007-03-05):
 * - documentation updated
 * 1.0.0 (2007-05-04):
 * - promoted to version 1.0.0 :o)
 */

package lp.parse;

/**
 * An exception thrown by {@link LpParser} when it can't parse the input.
 * Contains information about what token the parser expected, what it found and
 * where. This information is accessible through getter methods
 * ({@link #getExpected()}, {@link #getFound()}, {@link #getLineNumber()} and
 * {@link #getPosition()}) and is also included in the message returned by
 * {@link #getMessage()}.
 *
 * @author Martin Slota
 * @version 1.0.0
 * @see LpParser
 * @see LpTokenType
 */
public class LpParserException extends RuntimeException {
	/**
	 * Expected token.
	 */
	private final LpTokenType expected;
	
	/**
	 * Token found instead.
	 */
	private final String found;
	
	/**
	 * Line position of the problematic token's beginning.
	 */
	private final int position;
	
	/**
	 * Line number within the input where the problematic token was found.
	 */
	private final int lineNumber;
	
	/**
	 * Exception constructor taking the necessary information about the
	 * problematic token from a given {@link LpLexer}.
	 *
	 * @param expected expected token
	 * @param lexer lexer that just returned the token found
	 */
	public LpParserException(LpTokenType expected, LpLexer lexer) {
		this(expected, lexer.getLexem(), lexer.getLineNumber(),
				lexer.getPosition());
	}
	
	/**
	 * Exception constructor. Doesn't check if the expected token and the token
	 * found differ.
	 *
	 * @param expected expected token
	 * @param found token found instead of the expected token
	 * @param lineNumber number of the line where the problematic token was
	 * found
	 * @param position position of the problematic token within the line
	 */
	public LpParserException(LpTokenType expected, String found, int lineNumber,
			int position) {
		super();
		this.expected = expected;
		this.found = found;
		this.lineNumber = lineNumber;
		this.position = position;
	}
	
	/**
	 * Getter method for the expected token.
	 *
	 * @return expected token
	 */
	public LpTokenType getExpected() {
		return expected;
	}
	
	/**
	 * Getter method for the problematic token, i.e. the token found instead of
	 * the expected token.
	 *
	 * @return problematic token
	 */
	public String getFound() {
		return found;
	}
	
	/**
	 * Getter method for line position of the problematic token's beginning.
	 *
	 * @return line position of the problematic token's beginning
	 */
	public int getPosition() {
		return position;
	}
	
	/**
	 * Getter method for number of line on which the problematic token was
	 * found.
	 *
	 * @return number of line on which the problematic token was found
	 */
	public int getLineNumber() {
		return lineNumber;
	}
	
	/**
	 * Returns a message containing information about the parser problem.
	 *
	 * @return message containing the position in the input where the problem
	 * was encountered, the expected token and the token found instead
	 */
	@Override
	public String getMessage() {
		if ("".equals(found)) {
			return "line " + lineNumber + ", position " + position
					+ ": Unexpected end of input, " + expected.getDescription()
					+ " expected";
		}
		return "line " + lineNumber + ", position " + position
				+ ": Syntax error on token \"" + found + "\", "
				+ expected.getDescription() + " expected.";
	}
}