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