]> git.localhorst.tv Git - l2e.git/blob - src/loader/ParsedSource.cpp
made high level parser errors a bit more expressive
[l2e.git] / src / loader / ParsedSource.cpp
1 /*
2  * ParsedSource.cpp
3  *
4  *  Created on: Aug 26, 2012
5  *      Author: holy
6  */
7
8 #include "ParsedSource.h"
9
10 #include "utility.h"
11
12 #include <ostream>
13 #include <stdexcept>
14
15 using std::map;
16 using std::runtime_error;
17 using std::string;
18 using std::vector;
19
20 namespace loader {
21
22 ParsedSource::~ParsedSource() {
23         for (map<string, Declaration *>::const_iterator i(declarations.begin()), end(declarations.end()); i != end; ++i) {
24                 delete i->second;
25         }
26 }
27
28 void ParsedSource::AddDeclaration(Declaration *d) {
29         map<string, Declaration *>::iterator i(declarations.find(d->Identifier()));
30         if (i != declarations.end()) {
31                 if (d->TypeName() != i->second->TypeName()) {
32                         throw runtime_error("invalid redeclaration of " + i->second->TypeName() + " " + d->Identifier());
33                 }
34         } else {
35                 declarations.insert(std::make_pair(d->Identifier(), d));
36         }
37 }
38
39 void ParsedSource::AddDefinition(Definition *d) {
40         map<string, Definition *>::iterator i(definitions.find(d->Identifier()));
41         if (i != definitions.end()) {
42                 throw runtime_error("redefinition of " + i->second->TypeName() + " " + d->Identifier());
43         } else {
44                 definitions.insert(std::make_pair(d->Identifier(), d));
45         }
46 }
47
48 void ParsedSource::ExportDeclaration(Declaration *d) {
49         AddDeclaration(d);
50         exports.insert(d->Identifier());
51 }
52
53 void ParsedSource::ExportIdentifier(const std::string &i) {
54         if (declarations.count(i)) {
55                 exports.insert(i);
56         } else {
57                 throw runtime_error("cannot export undeclared identifier " + i);
58         }
59 }
60
61
62 bool ParsedSource::IsDeclared(const std::string &name) const {
63         return declarations.count(name);
64 }
65
66 Declaration &ParsedSource::GetDeclaration(const std::string &name) {
67         map<string, Declaration *>::const_iterator i(declarations.find(name));
68         if (i != declarations.end()) {
69                 return *i->second;
70         } else {
71                 throw runtime_error("undeclared identifier " + name);
72         }
73 }
74
75 const Declaration &ParsedSource::GetDeclaration(const std::string &name) const {
76         map<string, Declaration *>::const_iterator i(declarations.find(name));
77         if (i != declarations.end()) {
78                 return *i->second;
79         } else {
80                 throw runtime_error("undeclared identifier " + name);
81         }
82 }
83
84 bool ParsedSource::IsDefined(const std::string &name) const {
85         return definitions.count(name);
86 }
87
88 Definition &ParsedSource::GetDefinition(const std::string &name) {
89         map<string, Definition *>::const_iterator i(definitions.find(name));
90         if (i != definitions.end()) {
91                 return *i->second;
92         } else {
93                 string msg("undefined identifier " + name);
94                 map<string, Declaration *>::const_iterator i(declarations.find(name));
95                 if (i != declarations.end()) {
96                         msg += ", declared as " + i->second->TypeName();
97                 } else {
98                         msg += ", not declared";
99                 }
100                 throw runtime_error(msg);
101         }
102 }
103
104 const Definition &ParsedSource::GetDefinition(const std::string &name) const {
105         map<string, Definition *>::const_iterator i(definitions.find(name));
106         if (i != definitions.end()) {
107                 return *i->second;
108         } else {
109                 string msg("undefined identifier " + name);
110                 map<string, Declaration *>::const_iterator i(declarations.find(name));
111                 if (i != declarations.end()) {
112                         msg += ", declared as " + i->second->TypeName();
113                 } else {
114                         msg += ", not declared";
115                 }
116                 throw runtime_error(msg);
117         }
118 }
119
120 void ParsedSource::WriteHeader(std::ostream &out) const {
121         for (std::set<string>::const_iterator i(exports.begin()), end(exports.end()); i != end; ++i) {
122                 out << GetDeclaration(*i).TypeName() << ' ' << *i << std::endl;
123         }
124 }
125
126
127 Definition::~Definition() {
128         if (isLiteral) {
129                 delete reinterpret_cast<Literal *>(value);
130         } else {
131                 delete reinterpret_cast<PropertyList *>(value);
132         }
133 }
134
135 void Definition::SetValue(Literal *v) {
136         value = v;
137         isLiteral = true;
138 }
139
140 void Definition::SetValue(PropertyList *v) {
141         value = v;
142         isLiteral = false;
143 }
144
145 Literal *Definition::GetLiteral() {
146         if (isLiteral) {
147                 return reinterpret_cast<Literal *>(value);
148         } else {
149                 throw runtime_error("tried to access properties as literal");
150         }
151 }
152
153 const Literal *Definition::GetLiteral() const {
154         if (isLiteral) {
155                 return reinterpret_cast<Literal *>(value);
156         } else {
157                 throw runtime_error("tried to access properties as literal");
158         }
159 }
160
161 PropertyList *Definition::GetProperties() {
162         if (!isLiteral) {
163                 return reinterpret_cast<PropertyList *>(value);
164         } else {
165                 throw runtime_error("tried to access literal value as property list");
166         }
167 }
168
169 const PropertyList *Definition::GetProperties() const {
170         if (!isLiteral) {
171                 return reinterpret_cast<PropertyList *>(value);
172         } else if (GetLiteral()->GetType() == Literal::OBJECT) {
173                 return GetLiteral()->GetProperties();
174         } else {
175                 throw runtime_error("tried to access literal value as property list");
176         }
177 }
178
179
180 PropertyList::~PropertyList() {
181         for (map<string, Value *>::iterator i(props.begin()), end(props.end()); i != end; ++i) {
182                 delete i->second;
183         }
184 }
185
186
187 Literal::Literal(const vector<Value *> &v)
188 : props(0)
189 , values(v)
190 , i1(0), i2(0)
191 , i3(0), i4(0)
192 , b(false)
193 , type(ARRAY_VALUES) {
194
195 }
196
197 Literal::Literal(const std::vector<PropertyList *> &pls)
198 : props(0)
199 , propertyLists(pls)
200 , i1(0), i2(0)
201 , i3(0), i4(0)
202 , b(false)
203 , type(ARRAY_PROPS) {
204
205 }
206
207 Literal::Literal(bool b)
208 : props(0)
209 , i1(0), i2(0)
210 , i3(0), i4(0)
211 , b(b)
212 , type(BOOLEAN) {
213
214 }
215
216 Literal::Literal(int r, int g, int b, int a)
217 : props(0)
218 , i1(r), i2(g)
219 , i3(b), i4(a)
220 , b(false)
221 , type(COLOR) {
222
223 }
224
225 Literal::Literal(int number)
226 : props(0)
227 , i1(number), i2(0)
228 , i3(0), i4(0)
229 , b(false)
230 , type(NUMBER) {
231
232 }
233
234 Literal::Literal(const string &dir, const string &path)
235 : props(0)
236 , str(CatPath(dir, path))
237 , i1(0), i2(0)
238 , i3(0), i4(0)
239 , b(false)
240 , type(STRING) {
241
242 }
243
244 Literal::Literal(const string &str)
245 : props(0)
246 , str(str)
247 , i1(0), i2(0)
248 , i3(0), i4(0)
249 , b(false)
250 , type(STRING) {
251
252 }
253
254 Literal::Literal(int x, int y)
255 : props(0)
256 , i1(x), i2(y)
257 , i3(0), i4(0)
258 , b(false)
259 , type(VECTOR) {
260
261 }
262
263 Literal::Literal(const string &typeName, PropertyList *properties)
264 : props(properties)
265 , str(typeName)
266 , i1(0), i2(0)
267 , i3(0), i4(0)
268 , b(false)
269 , type(OBJECT) {
270
271 }
272
273 Literal::~Literal() {
274         switch (type) {
275                 case ARRAY_VALUES:
276                         for (vector<Value *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
277                                 delete *i;
278                         }
279                         break;
280                 case ARRAY_PROPS:
281                         for (vector<PropertyList *>::const_iterator i(propertyLists.begin()), end(propertyLists.end()); i != end; ++i) {
282                                 delete *i;
283                         }
284                         break;
285                 case OBJECT:
286                         delete props;
287                         break;
288                 default:
289                         break;
290         }
291 }
292
293
294 const vector<Value *> &Literal::GetValues() const {
295         if (type == ARRAY_VALUES) {
296                 return values;
297         } else {
298                 throw runtime_error("tried to access values of non-array literal");
299         }
300 }
301
302 const vector<PropertyList *> &Literal::GetPropertyLists() const {
303         if (type == ARRAY_PROPS) {
304                 return propertyLists;
305         } else {
306                 throw runtime_error("tried to access property lists of non-array literal");
307         }
308 }
309
310 bool Literal::GetBoolean() const {
311         if (type == BOOLEAN) {
312                 return b;
313         } else {
314                 throw runtime_error("tried to access boolean value of non-boolean literal");
315         }
316 }
317
318 int Literal::GetRed() const {
319         if (type == COLOR) {
320                 return i1;
321         } else {
322                 throw runtime_error("tried to access red component of non-color literal");
323         }
324 }
325
326 int Literal::GetGreen() const {
327         if (type == COLOR) {
328                 return i2;
329         } else {
330                 throw runtime_error("tried to access green component of non-color literal");
331         }
332 }
333
334 int Literal::GetBlue() const {
335         if (type == COLOR) {
336                 return i3;
337         } else {
338                 throw runtime_error("tried to access blue component of non-color literal");
339         }
340 }
341
342 int Literal::GetAlpha() const {
343         if (type == COLOR) {
344                 return i4;
345         } else {
346                 throw runtime_error("tried to access alpha component of non-color literal");
347         }
348 }
349
350 int Literal::GetNumber() const {
351         if (type == NUMBER) {
352                 return i1;
353         } else {
354                 throw runtime_error("tried to access numerical value of non-number literal");
355         }
356 }
357
358 const string &Literal::GetString() const {
359         if (type == STRING) {
360                 return str;
361         } else {
362                 throw runtime_error("tried to access string value of non-color literal");
363         }
364 }
365
366 int Literal::GetX() const {
367         if (type == VECTOR) {
368                 return i1;
369         } else {
370                 throw runtime_error("tried to access x component of non-vector literal");
371         }
372 }
373
374 int Literal::GetY() const {
375         if (type == VECTOR) {
376                 return i2;
377         } else {
378                 throw runtime_error("tried to access y component of non-vector literal");
379         }
380 }
381
382 const string &Literal::GetTypeName() const {
383         if (type == OBJECT) {
384                 return str;
385         } else {
386                 throw runtime_error("tried to access type name of non-object literal");
387         }
388 }
389
390 const PropertyList *Literal::GetProperties() const {
391         if (type == OBJECT) {
392                 return props;
393         } else {
394                 throw runtime_error("tried to access properties of non-object literal");
395         }
396 }
397
398
399 Value::~Value() {
400         if (isLiteral) {
401                 delete literal;
402         }
403 }
404
405 const Literal &Value::GetLiteral() const {
406         if (isLiteral) {
407                 return *literal;
408         } else {
409                 throw runtime_error("tried to access literal of identifier value");
410         }
411 }
412
413 const std::string &Value::GetIdentifier() const {
414         if (!isLiteral) {
415                 return identifier;
416         } else {
417                 throw runtime_error("tried to access identifier of literal value");
418         }
419 }
420
421 }
422
423
424 namespace std {
425
426 ostream &operator <<(ostream &out, const loader::ParsedSource &source) {
427         out << "parsed source file" << endl;
428         out << "declared objects: " << endl;
429         for (map<string, loader::Declaration *>::const_iterator i(source.Declarations().begin()), end(source.Declarations().end()); i != end; ++i) {
430                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
431         }
432         out << "defined objects: " << endl;
433         for (map<string, loader::Definition *>::const_iterator i(source.Definitions().begin()), end(source.Definitions().end()); i != end; ++i) {
434                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
435                 if (i->second->HasLiteralValue()) {
436                         out << "     literal value: " << *i->second->GetLiteral() << endl;
437                 }
438         }
439         out << "exported objects: " << endl;
440         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
441                 out << " - " << *i << endl;
442         }
443         return out;
444 }
445
446 ostream &operator <<(ostream &out, const loader::Literal &l) {
447         switch (l.GetType()) {
448                 case loader::Literal::ARRAY_VALUES:
449                         out << "array of values";
450                         break;
451                 case loader::Literal::ARRAY_PROPS:
452                         out << "array of property lists";
453                         break;
454                 case loader::Literal::BOOLEAN:
455                         out << "boolean, " << (l.GetBoolean() ? "true" : "false");
456                         break;
457                 case loader::Literal::COLOR:
458                         out << "color, (" << l.GetRed() << ',' << l.GetGreen() << ',' << l.GetBlue() << ',' << l.GetAlpha() << ')';
459                         break;
460                 case loader::Literal::NUMBER:
461                         out << "number, " << l.GetNumber();
462                         break;
463                 case loader::Literal::PATH:
464                         out << "path, \"" << l.GetString() << '"';
465                         break;
466                 case loader::Literal::STRING:
467                         out << "string, \"" << l.GetString() << '"';
468                         break;
469                 case loader::Literal::VECTOR:
470                         out << "vector, <" << l.GetX() << ',' << l.GetY() << '>';
471                         break;
472                 case loader::Literal::OBJECT:
473                         out << "object of type " << l.GetTypeName();
474                         break;
475         }
476         return out;
477 }
478
479 }