1 // SDLang-D
2 // Written in the D programming language.
3 
4 module sdlang.exception;
5 
6 import std.array;
7 import std.exception;
8 import std.range;
9 import std.stdio;
10 import std.string;
11 
12 import sdlang.ast;
13 import sdlang.util;
14 
15 /// Abstract parent class of all SDLang-D defined exceptions.
16 abstract class SDLangException : Exception
17 {
18 	this(string msg, string file = __FILE__, size_t line = __LINE__)
19 	{
20 		super(msg, file, line);
21 	}
22 }
23 
24 /// Thrown when a syntax error is encounterd while parsing.
25 class ParseException : SDLangException
26 {
27 	Location location;
28 	bool hasLocation;
29 
30 	this(string msg, string file = __FILE__, size_t line = __LINE__)
31 	{
32 		hasLocation = false;
33 		super(msg, file, line);
34 	}
35 
36 	this(Location location, string msg, string file = __FILE__, size_t line = __LINE__)
37 	{
38 		hasLocation = true;
39 		super("%s: %s".format(location.toString(), msg), file, line);
40 	}
41 }
42 
43 /// Compatibility alias
44 deprecated("The new name is ParseException")
45 alias SDLangParseException = ParseException;
46 
47 /++
48 Thrown when attempting to do something in the DOM that's unsupported, such as:
49 
50 $(UL
51 $(LI Adding the same instance of a tag or attribute to more than one parent.)
52 $(LI Writing SDLang where:
53 	$(UL
54 	$(LI The root tag has values, attributes or a namespace. )
55 	$(LI An anonymous tag has a namespace. )
56 	$(LI An anonymous tag has no values. )
57 	$(LI A floating point value is infinity or NaN. )
58 	)
59 ))
60 +/
61 class ValidationException : SDLangException
62 {
63 	this(string msg, string file = __FILE__, size_t line = __LINE__)
64 	{
65 		super(msg, file, line);
66 	}
67 }
68 
69 /// Compatibility alias
70 deprecated("The new name is ValidationException")
71 alias SDLangValidationException = ValidationException;
72 
73 /// Thrown when someting is wrong with the provided arguments to a function.
74 class ArgumentException : SDLangException
75 {
76 	this(string msg, string file = __FILE__, size_t line = __LINE__)
77 	{
78 		super(msg, file, line);
79 	}
80 }
81 
82 /// Thrown by the DOM on empty range and out-of-range conditions.
83 abstract class DOMException : SDLangException
84 {
85 	Tag base; /// The tag searched from
86 
87 	this(Tag base, string msg, string file = __FILE__, size_t line = __LINE__)
88 	{
89 		this.base = base;
90 		super(msg, file, line);
91 	}
92 
93 	/// Prefixes a message with file/line information from the tag (if tag exists).
94 	/// Optionally takes output range as a sink.
95 	string customMsg(string msg)
96 	{
97 		if(!base)
98 			return msg;
99 
100 		Appender!string sink;
101 		this.customMsg(sink, msg);
102 		return sink.data;
103 	}
104 
105 	///ditto
106 	void customMsg(Sink)(ref Sink sink, string msg) if(isOutputRange!(Sink,char))
107 	{
108 		if(base)
109 		{
110 			sink.put(base.location.toString());
111 			sink.put(": ");
112 			sink.put(msg);
113 		}
114 		else
115 			sink.put(msg);
116 	}
117 
118 	/// Outputs a message to stderr, prefixed with file/line information
119 	void writeCustomMsg(string msg)
120 	{
121 		stderr.writeln( customMsg(msg) );
122 	}
123 }
124 
125 /// Thrown by the DOM on empty range and out-of-range conditions.
126 class DOMRangeException : DOMException
127 {
128 	this(Tag base, string msg, string file = __FILE__, size_t line = __LINE__)
129 	{
130 		super(base, msg, file, line);
131 	}
132 }
133 
134 /// Compatibility alias
135 deprecated("The new name is DOMRangeException")
136 alias SDLangRangeException = DOMRangeException;
137 
138 /// Abstract parent class of `TagNotFoundException`, `ValueNotFoundException`
139 /// and `AttributeNotFoundException`.
140 ///
141 /// Thrown by the DOM's `sdlang.ast.Tag.expectTag`, etc. functions if a matching element isn't found.
142 abstract class DOMNotFoundException : DOMException
143 {
144 	FullName tagName; /// The tag searched for
145 
146 	this(Tag base, FullName tagName, string msg, string file = __FILE__, size_t line = __LINE__)
147 	{
148 		this.tagName = tagName;
149 		super(base, msg, file, line);
150 	}
151 }
152 
153 /// Thrown by the DOM's `sdlang.ast.Tag.expectTag`, etc. functions if a Tag isn't found.
154 class TagNotFoundException : DOMNotFoundException
155 {
156 	this(Tag base, FullName tagName, string msg, string file = __FILE__, size_t line = __LINE__)
157 	{
158 		super(base, tagName, msg, file, line);
159 	}
160 }
161 
162 /// Thrown by the DOM's `sdlang.ast.Tag.expectValue`, etc. functions if a Value isn't found.
163 class ValueNotFoundException : DOMNotFoundException
164 {
165 	/// Expected type for the not-found value.
166 	TypeInfo valueType;
167 
168 	this(Tag base, FullName tagName, TypeInfo valueType, string msg, string file = __FILE__, size_t line = __LINE__)
169 	{
170 		this.valueType = valueType;
171 		super(base, tagName, msg, file, line);
172 	}
173 }
174 
175 /// Thrown by the DOM's `sdlang.ast.Tag.expectAttribute`, etc. functions if an Attribute isn't found.
176 class AttributeNotFoundException : DOMNotFoundException
177 {
178 	FullName attributeName; /// The attribute searched for
179 
180 	/// Expected type for the not-found attribute's value.
181 	TypeInfo valueType;
182 
183 	this(Tag base, FullName tagName, FullName attributeName, TypeInfo valueType, string msg,
184 		string file = __FILE__, size_t line = __LINE__)
185 	{
186 		this.valueType = valueType;
187 		this.attributeName = attributeName;
188 		super(base, tagName, msg, file, line);
189 	}
190 }