ssc/exceptions.cs

265 lines
6.8 KiB
C#

using PerCederberg.Grammatica.Runtime;
using System;
namespace arookas
{
// base exception type
public class sunCompilerException : Exception
{
public sunCompilerException()
{
}
public sunCompilerException(string format, params object[] args)
: base(String.Format(format, args))
{
}
}
// exceptions that have a location in the source
public abstract class sunScriptException : sunCompilerException
{
public abstract sunSourceLocation Location { get; }
public sunScriptException()
{
}
public sunScriptException(string format, params object[] args)
: base(format, args)
{
}
}
public class sunImportException : sunCompilerException
{
public string Name { get; private set; }
public sunImportResult Result { get; private set; }
public override string Message { get { return String.Format("Name: {0}, Result: {1}", Name, Result); } }
public sunImportException(string name, sunImportResult result)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
if (!result.IsDefined())
{
throw new ArgumentOutOfRangeException("name");
}
Name = name;
Result = result;
}
}
// wrapper around Grammatica exceptions
class sunParserException : sunScriptException
{
string file;
public ParseException Info { get; private set; }
public override string Message { get { return Info.ErrorMessage; } }
public override sunSourceLocation Location { get { return new sunSourceLocation(file, Info.Line, Info.Column); } }
public sunParserException(string file, ParseException info)
{
if (file == null)
{
throw new ArgumentNullException("file");
}
if (info == null)
{
throw new ArgumentNullException("info");
}
this.file = file;
Info = info;
}
}
// node exceptions
abstract class sunNodeException<TNode> : sunScriptException where TNode : sunNode
{
public TNode Node { get; private set; }
public override sunSourceLocation Location { get { return Node.Location; } }
protected sunNodeException(TNode node)
{
if (node == null)
{
throw new ArgumentNullException("node");
}
Node = node;
}
}
class sunRedeclaredBuiltinException : sunNodeException<sunBuiltinDeclaration>
{
public override string Message { get { return String.Format("Redeclared builtin '{0}'.", Node.Builtin.Value); } }
public sunRedeclaredBuiltinException(sunBuiltinDeclaration node)
: base(node)
{
}
}
class sunUndefinedFunctionException : sunNodeException<sunFunctionCall>
{
public override string Message { get { return String.Format("Undefined function or builtin '{0}'.", Node.Function.Value); } }
public sunUndefinedFunctionException(sunFunctionCall node)
: base(node)
{
}
}
class sunRedefinedFunctionException : sunNodeException<sunFunctionDefinition>
{
public override string Message { get { return String.Format("Redefined function '{0}'.", Node.Function.Value); } }
public sunRedefinedFunctionException(sunFunctionDefinition node)
: base(node)
{
}
}
class sunUndeclaredVariableException : sunNodeException<sunIdentifier>
{
public override string Message { get { return String.Format("Undeclared variable '{0}'.", Node.Value); } }
public sunUndeclaredVariableException(sunIdentifier node)
: base(node)
{
}
}
class sunRedeclaredVariableException : sunNodeException<sunIdentifier>
{
public override string Message { get { return String.Format("Redeclared variable '{0}'.", Node.Value); } }
public sunRedeclaredVariableException(sunIdentifier node)
: base(node)
{
}
}
class sunRedeclaredParameterException : sunNodeException<sunIdentifier>
{
public override string Message { get { return String.Format("Redeclared parameter '{0}'.", Node.Value); } }
public sunRedeclaredParameterException(sunIdentifier node)
: base(node)
{
}
}
class sunVariadicFunctionException : sunNodeException<sunFunctionDefinition>
{
public override string Message { get { return String.Format("Function '{0}' is defined as a variadic function (only builtins may be variadic).", Node.Function.Value); } }
public sunVariadicFunctionException(sunFunctionDefinition node)
: base(node)
{
}
}
class sunEscapeSequenceException : sunNodeException<sunStringLiteral>
{
public override string Message { get { return String.Format("Bad escape sequence in string."); } }
public sunEscapeSequenceException(sunStringLiteral node)
: base(node)
{
}
}
class sunVariadicParameterListException : sunNodeException<sunParameterList>
{
public override string Message { get { return String.Format("Bad variadic parameter list."); } }
public sunVariadicParameterListException(sunParameterList node)
: base(node)
{
}
}
class sunArgumentCountException : sunNodeException<sunFunctionCall>
{
public sunCallableSymbolInfo CalledSymbol { get; private set; }
public int ArgumentMinimum { get { return CalledSymbol.Parameters.Minimum; } }
public int ArgumentCount { get { return Node.Arguments.Count; } }
public override string Message
{
get
{
string format;
if (CalledSymbol.Parameters.IsVariadic)
{
// assuming to be missing because there's only a minimum
format = "Missing {0} argument(s) (expected at least {1}; got {2}).";
}
else if (Node.Arguments.Count < CalledSymbol.Parameters.Minimum)
{
format = "Missing {0} argument(s) (expected {1}; got {2})."; // missing arguments
}
else
{
format = "Too many arguments (expected {1}; got {2})."; // extra arguments
}
return String.Format(format, ArgumentMinimum - ArgumentCount, ArgumentMinimum, ArgumentCount);
}
}
public sunArgumentCountException(sunFunctionCall node, sunCallableSymbolInfo calledSymbol)
: base(node)
{
if (calledSymbol == null)
{
throw new ArgumentNullException("calledSymbol");
}
CalledSymbol = calledSymbol;
}
}
class sunIdentifierException : sunNodeException<sunIdentifier>
{
public override string Message { get { return String.Format("Invalid identifier '{0}'.", Node.Value); } }
public sunIdentifierException(sunIdentifier node)
: base(node)
{
}
}
class sunMissingImportException : sunNodeException<sunImport>
{
public override string Message { get { return String.Format("Could not find import file '{0}'.", Node.ImportFile.Value); } }
public sunMissingImportException(sunImport node)
: base(node)
{
}
}
class sunBreakException : sunNodeException<sunBreak>
{
public override string Message { get { return "Break statements must be placed within a loop statement."; } }
public sunBreakException(sunBreak node)
: base(node)
{
}
}
class sunContinueException : sunNodeException<sunContinue>
{
public override string Message { get { return "Continue statements must be placed within a loop statement."; } }
public sunContinueException(sunContinue node)
: base(node)
{
}
}
}