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