/*
* ParserCreationException.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 parser creation exception. This exception is used for signalling
* an error in the token or production patterns, making it impossible
* to create a working parser or tokenizer.
*
* @author Per Cederberg, <per at percederberg dot net>
* @version 1.0
*/
public class ParserCreationException : 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 invalid parser error type is used when the parser
* as such is invalid. This error is typically caused by
* using a parser without any patterns.
*/
INVALID_PARSER,
/*
* The invalid token error type is used when a token
* pattern is erroneous. This error is typically caused
* by an invalid pattern type or an erroneous regular
* expression.
*/
INVALID_TOKEN,
/*
* The invalid production error type is used when a
* production pattern is erroneous. This error is
* typically caused by referencing undeclared productions,
* or violating some other production pattern constraint.
*/
INVALID_PRODUCTION,
/*
* The infinite loop error type is used when an infinite
* loop has been detected in the grammar. One of the
* productions in the loop will be reported.
*/
INFINITE_LOOP,
/*
* The inherent ambiguity error type is used when the set
* of production patterns (i.e. the grammar) contains
* ambiguities that cannot be resolved.
*/
INHERENT_AMBIGUITY
}
/**
* The error type.
*/
private ErrorType type;
/**
* The token or production pattern name. This variable is only
* set for some error types.
*/
private string name;
/**
* The additional error information string. This variable is only
* set for some error types.
*/
private string info;
/**
* The error details list. This variable is only set for some
* error types.
*/
private ArrayList details;
/**
* Creates a new parser creation exception.
*
* @param type the parse error type
* @param info the additional error information
*/
public ParserCreationException(ErrorType type,
String info)
: this(type, null, info) {
}
/**
* Creates a new parser creation exception.
*
* @param type the parse error type
* @param name the token or production pattern name
* @param info the additional error information
*/
public ParserCreationException(ErrorType type,
String name,
String info)
: this(type, name, info, null) {
}
/**
* Creates a new parser creation exception.
*
* @param type the parse error type
* @param name the token or production pattern name
* @param info the additional error information
* @param details the error details list
*/
public ParserCreationException(ErrorType type,
String name,
String info,
ArrayList details) {
this.type = type;
this.name = name;
this.info = info;
this.details = details;
}
/**
* 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 token or production name.
*
* @return the token or production name
*/
public string GetName() {
return name;
}
/**
* Returns the additional error information.
*
* @return the additional error information
*/
public string GetInfo() {
return info;
}
/**
* Returns the detailed error information as a string
*
* @return the detailed error information
*/
public string GetDetails() {
StringBuilder buffer = new StringBuilder();
if (details == null) {
return null;
}
for (int i = 0; i < details.Count; i++) {
if (i > 0) {
buffer.Append(", ");
if (i + 1 == details.Count) {
buffer.Append("and ");
}
}
buffer.Append(details[i]);
}
return buffer.ToString();
}
/**
* Returns the error message. This message will contain all the
* information available.
*
* @return the error message
*/
public string GetMessage() {
StringBuilder buffer = new StringBuilder();
switch (type) {
case ErrorType.INVALID_PARSER:
buffer.Append("parser is invalid, as ");
buffer.Append(info);
break;
case ErrorType.INVALID_TOKEN:
buffer.Append("token '");
buffer.Append(name);
buffer.Append("' is invalid, as ");
buffer.Append(info);
break;
case ErrorType.INVALID_PRODUCTION:
buffer.Append("production '");
buffer.Append(name);
buffer.Append("' is invalid, as ");
buffer.Append(info);
break;
case ErrorType.INFINITE_LOOP:
buffer.Append("infinite loop found in production pattern '");
buffer.Append(name);
buffer.Append("'");
break;
case ErrorType.INHERENT_AMBIGUITY:
buffer.Append("inherent ambiguity in production '");
buffer.Append(name);
buffer.Append("'");
if (info != null) {
buffer.Append(" ");
buffer.Append(info);
}
if (details != null) {
buffer.Append(" starting with ");
if (details.Count > 1) {
buffer.Append("tokens ");
} else {
buffer.Append("token ");
}
buffer.Append(GetDetails());
}
break;
default:
buffer.Append("internal error");
break;
}
return buffer.ToString();
}
}
}