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) { } } // 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 : 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 { public override string Message { get { return String.Format("Redeclared builtin '{0}'.", Node.Builtin.Value); } } public sunRedeclaredBuiltinException(sunBuiltinDeclaration node) : base(node) { } } class sunUndefinedFunctionException : sunNodeException { 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 { public override string Message { get { return String.Format("Redefined function '{0}'.", Node.Function.Value); } } public sunRedefinedFunctionException(sunFunctionDefinition node) : base(node) { } } class sunUndeclaredVariableException : sunNodeException { public override string Message { get { return String.Format("Undeclared variable '{0}'.", Node.Value); } } public sunUndeclaredVariableException(sunIdentifier node) : base(node) { } } class sunRedeclaredVariableException : sunNodeException { public override string Message { get { return String.Format("Redeclared variable '{0}'.", Node.Value); } } public sunRedeclaredVariableException(sunIdentifier node) : base(node) { } } class sunRedeclaredParameterException : sunNodeException { public override string Message { get { return String.Format("Redeclared parameter '{0}'.", Node.Value); } } public sunRedeclaredParameterException(sunIdentifier node) : base(node) { } } class sunVariadicFunctionException : sunNodeException { 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 { public override string Message { get { return String.Format("Bad escape sequence in string."); } } public sunEscapeSequenceException(sunStringLiteral node) : base(node) { } } class sunVariadicParameterListException : sunNodeException { public override string Message { get { return String.Format("Bad variadic parameter list."); } } public sunVariadicParameterListException(sunParameterList node) : base(node) { } } class sunArgumentCountException : sunNodeException { 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 { public override string Message { get { return String.Format("Invalid identifier '{0}'.", Node.Value); } } public sunIdentifierException(sunIdentifier node) : base(node) { } } class sunMissingImportException : sunNodeException { 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 { public override string Message { get { return "Break statements must be placed within a loop statement."; } } public sunBreakException(sunBreak node) : base(node) { } } class sunContinueException : sunNodeException { public override string Message { get { return "Continue statements must be placed within a loop statement."; } } public sunContinueException(sunContinue node) : base(node) { } } }