/*
* ParseException.cs
*
* This work 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 work 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* As a special exception, the copyright holders of this library give
* you permission to link this library with independent modules to
* produce an executable, regardless of the license terms of these
* independent modules, and to copy and distribute the resulting
* executable under terms of your choice, provided that you also meet,
* for each linked independent module, the terms and conditions of the
* license of that module. An independent module is a module which is
* not derived from or based on this library. If you modify this
* library, you may extend this exception to your version of the
* library, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Copyright (c) 2003 Per Cederberg. All rights reserved.
*/
using System;
using System.Collections;
using System.Text;
namespace PerCederberg.Grammatica.Parser {
/**
* A parse exception.
*
* @author Per Cederberg, <per at percederberg dot net>
* @version 1.1
*/
public class ParseException : Exception {
/**
* The error type enumeration.
*/
public enum ErrorType {
/*
* The internal error type is only used to signal an error
* that is a result of a bug in the parser or tokenizer
* code.
*/
INTERNAL,
/*
* The I/O error type is used for stream I/O errors.
*/
IO,
/*
* The unexpected end of file error type is used when end
* of file is encountered instead of a valid token.
*/
UNEXPECTED_EOF,
/*
* The unexpected character error type is used when a
* character is read that isn't handled by one of the
* token patterns.
*/
UNEXPECTED_CHAR,
/*
* The unexpected token error type is used when another
* token than the expected one is encountered.
*/
UNEXPECTED_TOKEN,
/*
* The invalid token error type is used when a token
* pattern with an error message is matched. The
* additional information provided should contain the
* error message.
*/
INVALID_TOKEN,
/*
* The analysis error type is used when an error is
* encountered in the analysis. The additional information
* provided should contain the error message.
*/
ANALYSIS
}
/**
* The error type.
*/
private ErrorType type;
/**
* The additional information string.
*/
private string info;
/**
* The additional details information. This variable is only
* used for unexpected token errors.
*/
private ArrayList details;
/**
* The line number.
*/
private int line;
/**
* The column number.
*/
private int column;
/**
* Creates a new parse exception.
*
* @param type the parse error type
* @param info the additional information
* @param line the line number, or -1 for unknown
* @param column the column number, or -1 for unknown
*/
public ParseException(ErrorType type,
string info,
int line,
int column)
: this(type, info, null, line, column) {
}
/**
* Creates a new parse exception. This constructor is only
* used to supply the detailed information array, which is
* only used for expected token errors. The list then contains
* descriptions of the expected tokens.
*
* @param type the parse error type
* @param info the additional information
* @param details the additional detailed information
* @param line the line number, or -1 for unknown
* @param column the column number, or -1 for unknown
*/
public ParseException(ErrorType type,
string info,
ArrayList details,
int line,
int column) {
this.type = type;
this.info = info;
this.details = details;
this.line = line;
this.column = column;
}
/**
* The message property. This property contains the detailed
* exception error message.
*/
public override string Message {
get{
return GetMessage();
}
}
/**
* Returns the error type.
*
* @return the error type
*/
public ErrorType GetErrorType() {
return type;
}
/**
* Returns the additional error information.
*
* @return the additional error information
*/
public string GetInfo() {
return info;
}
/**
* Returns the additional detailed error information.
*
* @return the additional detailed error information
*/
public ArrayList GetDetails() {
return new ArrayList(details);
}
/**
* Returns the line number where the error occured.
*
* @return the line number of the error, or
* -1 if unknown
*/
public int GetLine() {
return line;
}
/**
* Returns the column number where the error occured.
*
* @return the column number of the error, or
* -1 if unknown
*/
public int GetColumn() {
return column;
}
/**
* Returns a default error message.
*
* @return a default error message
*/
public string GetMessage() {
StringBuilder buffer = new StringBuilder();
// Add error description
buffer.Append(GetErrorMessage());
// Add line and column
if (line > 0 && column > 0) {
buffer.Append(", on line: ");
buffer.Append(line);
buffer.Append(" column: ");
buffer.Append(column);
}
return buffer.ToString();
}
/**
* Returns the error message. This message will contain all the
* information available, except for the line and column number
* information.
*
* @return the error message
*/
public string GetErrorMessage() {
StringBuilder buffer = new StringBuilder();
// Add type and info
switch (type) {
case ErrorType.IO:
buffer.Append("I/O error: ");
buffer.Append(info);
break;
case ErrorType.UNEXPECTED_EOF:
buffer.Append("unexpected end of file");
break;
case ErrorType.UNEXPECTED_CHAR:
buffer.Append("unexpected character '");
buffer.Append(info);
buffer.Append("'");
break;
case ErrorType.UNEXPECTED_TOKEN:
buffer.Append("unexpected token ");
buffer.Append(info);
if (details != null) {
buffer.Append(", expected ");
if (details.Count > 1) {
buffer.Append("one of ");
}
buffer.Append(GetMessageDetails());
}
break;
case ErrorType.INVALID_TOKEN:
buffer.Append(info);
break;
case ErrorType.ANALYSIS:
buffer.Append(info);
break;
default:
buffer.Append("internal error");
if (info != null) {
buffer.Append(": ");
buffer.Append(info);
}
break;
}
return buffer.ToString();
}
/**
* Returns a string containing all the detailed information in
* a list. The elements are separated with a comma.
*
* @return the detailed information string
*/
private string GetMessageDetails() {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < details.Count; i++) {
if (i > 0) {
buffer.Append(", ");
if (i + 1 == details.Count) {
buffer.Append("or ");
}
}
buffer.Append(details[i]);
}
return buffer.ToString();
}
}
}