]> git.localhorst.tv Git - l2e.git/blob - src/loader/ParsedSource.cpp
added utility function to create headers
[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                 throw runtime_error("undefined identifier " + name);
94         }
95 }
96
97 const Definition &ParsedSource::GetDefinition(const std::string &name) const {
98         map<string, Definition *>::const_iterator i(definitions.find(name));
99         if (i != definitions.end()) {
100                 return *i->second;
101         } else {
102                 throw runtime_error("undefined identifier " + name);
103         }
104 }
105
106 void ParsedSource::WriteHeader(std::ostream &out) const {
107         for (std::set<string>::const_iterator i(exports.begin()), end(exports.end()); i != end; ++i) {
108                 out << GetDeclaration(*i).TypeName() << ' ' << *i << std::endl;
109         }
110 }
111
112
113 Definition::~Definition() {
114         if (isLiteral) {
115                 delete reinterpret_cast<Literal *>(value);
116         } else {
117                 delete reinterpret_cast<PropertyList *>(value);
118         }
119 }
120
121 void Definition::SetValue(Literal *v) {
122         value = v;
123         isLiteral = true;
124 }
125
126 void Definition::SetValue(PropertyList *v) {
127         value = v;
128         isLiteral = false;
129 }
130
131 Literal *Definition::GetLiteral() {
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 const Literal *Definition::GetLiteral() const {
140         if (isLiteral) {
141                 return reinterpret_cast<Literal *>(value);
142         } else {
143                 throw runtime_error("tried to access properties as literal");
144         }
145 }
146
147 PropertyList *Definition::GetProperties() {
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 const PropertyList *Definition::GetProperties() const {
156         if (!isLiteral) {
157                 return reinterpret_cast<PropertyList *>(value);
158         } else if (GetLiteral()->GetType() == Literal::OBJECT) {
159                 return GetLiteral()->GetProperties();
160         } else {
161                 throw runtime_error("tried to access literal value as property list");
162         }
163 }
164
165
166 PropertyList::~PropertyList() {
167         for (map<string, Value *>::iterator i(props.begin()), end(props.end()); i != end; ++i) {
168                 delete i->second;
169         }
170 }
171
172
173 Literal::Literal(const vector<Value *> &v)
174 : props(0)
175 , values(v)
176 , i1(0), i2(0)
177 , i3(0), i4(0)
178 , b(false)
179 , type(ARRAY_VALUES) {
180
181 }
182
183 Literal::Literal(const std::vector<PropertyList *> &pls)
184 : props(0)
185 , propertyLists(pls)
186 , i1(0), i2(0)
187 , i3(0), i4(0)
188 , b(false)
189 , type(ARRAY_PROPS) {
190
191 }
192
193 Literal::Literal(bool b)
194 : props(0)
195 , i1(0), i2(0)
196 , i3(0), i4(0)
197 , b(b)
198 , type(BOOLEAN) {
199
200 }
201
202 Literal::Literal(int r, int g, int b, int a)
203 : props(0)
204 , i1(r), i2(g)
205 , i3(b), i4(a)
206 , b(false)
207 , type(COLOR) {
208
209 }
210
211 Literal::Literal(int number)
212 : props(0)
213 , i1(number), i2(0)
214 , i3(0), i4(0)
215 , b(false)
216 , type(NUMBER) {
217
218 }
219
220 Literal::Literal(const string &dir, const string &path)
221 : props(0)
222 , str(CatPath(dir, path))
223 , i1(0), i2(0)
224 , i3(0), i4(0)
225 , b(false)
226 , type(STRING) {
227
228 }
229
230 Literal::Literal(const string &str)
231 : props(0)
232 , str(str)
233 , i1(0), i2(0)
234 , i3(0), i4(0)
235 , b(false)
236 , type(STRING) {
237
238 }
239
240 Literal::Literal(int x, int y)
241 : props(0)
242 , i1(x), i2(y)
243 , i3(0), i4(0)
244 , b(false)
245 , type(VECTOR) {
246
247 }
248
249 Literal::Literal(const string &typeName, PropertyList *properties)
250 : props(properties)
251 , str(typeName)
252 , i1(0), i2(0)
253 , i3(0), i4(0)
254 , b(false)
255 , type(OBJECT) {
256
257 }
258
259 Literal::~Literal() {
260         switch (type) {
261                 case ARRAY_VALUES:
262                         for (vector<Value *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
263                                 delete *i;
264                         }
265                         break;
266                 case ARRAY_PROPS:
267                         for (vector<PropertyList *>::const_iterator i(propertyLists.begin()), end(propertyLists.end()); i != end; ++i) {
268                                 delete *i;
269                         }
270                         break;
271                 case OBJECT:
272                         delete props;
273                         break;
274                 default:
275                         break;
276         }
277 }
278
279
280 const vector<Value *> &Literal::GetValues() const {
281         if (type == ARRAY_VALUES) {
282                 return values;
283         } else {
284                 throw runtime_error("tried to access values of non-array literal");
285         }
286 }
287
288 const vector<PropertyList *> &Literal::GetPropertyLists() const {
289         if (type == ARRAY_PROPS) {
290                 return propertyLists;
291         } else {
292                 throw runtime_error("tried to access property lists of non-array literal");
293         }
294 }
295
296 bool Literal::GetBoolean() const {
297         if (type == BOOLEAN) {
298                 return b;
299         } else {
300                 throw runtime_error("tried to access boolean value of non-boolean literal");
301         }
302 }
303
304 int Literal::GetRed() const {
305         if (type == COLOR) {
306                 return i1;
307         } else {
308                 throw runtime_error("tried to access red component of non-color literal");
309         }
310 }
311
312 int Literal::GetGreen() const {
313         if (type == COLOR) {
314                 return i2;
315         } else {
316                 throw runtime_error("tried to access green component of non-color literal");
317         }
318 }
319
320 int Literal::GetBlue() const {
321         if (type == COLOR) {
322                 return i3;
323         } else {
324                 throw runtime_error("tried to access blue component of non-color literal");
325         }
326 }
327
328 int Literal::GetAlpha() const {
329         if (type == COLOR) {
330                 return i4;
331         } else {
332                 throw runtime_error("tried to access alpha component of non-color literal");
333         }
334 }
335
336 int Literal::GetNumber() const {
337         if (type == NUMBER) {
338                 return i1;
339         } else {
340                 throw runtime_error("tried to access numerical value of non-number literal");
341         }
342 }
343
344 const string &Literal::GetString() const {
345         if (type == STRING) {
346                 return str;
347         } else {
348                 throw runtime_error("tried to access string value of non-color literal");
349         }
350 }
351
352 int Literal::GetX() const {
353         if (type == VECTOR) {
354                 return i1;
355         } else {
356                 throw runtime_error("tried to access x component of non-vector literal");
357         }
358 }
359
360 int Literal::GetY() const {
361         if (type == VECTOR) {
362                 return i2;
363         } else {
364                 throw runtime_error("tried to access y component of non-vector literal");
365         }
366 }
367
368 const string &Literal::GetTypeName() const {
369         if (type == OBJECT) {
370                 return str;
371         } else {
372                 throw runtime_error("tried to access type name of non-object literal");
373         }
374 }
375
376 const PropertyList *Literal::GetProperties() const {
377         if (type == OBJECT) {
378                 return props;
379         } else {
380                 throw runtime_error("tried to access properties of non-object literal");
381         }
382 }
383
384
385 Value::~Value() {
386         if (isLiteral) {
387                 delete literal;
388         }
389 }
390
391 const Literal &Value::GetLiteral() const {
392         if (isLiteral) {
393                 return *literal;
394         } else {
395                 throw runtime_error("tried to access literal of identifier value");
396         }
397 }
398
399 const std::string &Value::GetIdentifier() const {
400         if (!isLiteral) {
401                 return identifier;
402         } else {
403                 throw runtime_error("tried to access identifier of literal value");
404         }
405 }
406
407 }
408
409
410 namespace std {
411
412 ostream &operator <<(ostream &out, const loader::ParsedSource &source) {
413         out << "parsed source file" << endl;
414         out << "declared objects: " << endl;
415         for (map<string, loader::Declaration *>::const_iterator i(source.Declarations().begin()), end(source.Declarations().end()); i != end; ++i) {
416                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
417         }
418         out << "defined objects: " << endl;
419         for (map<string, loader::Definition *>::const_iterator i(source.Definitions().begin()), end(source.Definitions().end()); i != end; ++i) {
420                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
421                 if (i->second->HasLiteralValue()) {
422                         out << "     literal value: " << *i->second->GetLiteral() << endl;
423                 }
424         }
425         out << "exported objects: " << endl;
426         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
427                 out << " - " << *i << endl;
428         }
429         return out;
430 }
431
432 ostream &operator <<(ostream &out, const loader::Literal &l) {
433         switch (l.GetType()) {
434                 case loader::Literal::ARRAY_VALUES:
435                         out << "array of values";
436                         break;
437                 case loader::Literal::ARRAY_PROPS:
438                         out << "array of property lists";
439                         break;
440                 case loader::Literal::BOOLEAN:
441                         out << "boolean, " << (l.GetBoolean() ? "true" : "false");
442                         break;
443                 case loader::Literal::COLOR:
444                         out << "color, (" << l.GetRed() << ',' << l.GetGreen() << ',' << l.GetBlue() << ',' << l.GetAlpha() << ')';
445                         break;
446                 case loader::Literal::NUMBER:
447                         out << "number, " << l.GetNumber();
448                         break;
449                 case loader::Literal::PATH:
450                         out << "path, \"" << l.GetString() << '"';
451                         break;
452                 case loader::Literal::STRING:
453                         out << "string, \"" << l.GetString() << '"';
454                         break;
455                 case loader::Literal::VECTOR:
456                         out << "vector, <" << l.GetX() << ',' << l.GetY() << '>';
457                         break;
458                 case loader::Literal::OBJECT:
459                         out << "object of type " << l.GetTypeName();
460                         break;
461         }
462         return out;
463 }
464
465 }