]> git.localhorst.tv Git - l2e.git/blob - src/loader/ParsedSource.cpp
revised array type notation
[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         if (!v.empty()) {
195                 typeName = v.front()->GetLiteral().GetTypeName();
196         }
197 }
198
199 Literal::Literal(const string &typeName, const vector<PropertyList *> &pls)
200 : props(0)
201 , typeName(typeName)
202 , propertyLists(pls)
203 , i1(0), i2(0)
204 , i3(0), i4(0)
205 , b(false)
206 , type(ARRAY_PROPS) {
207
208 }
209
210 Literal::Literal(bool b)
211 : props(0)
212 , typeName("Boolean")
213 , i1(0), i2(0)
214 , i3(0), i4(0)
215 , b(b)
216 , type(BOOLEAN) {
217
218 }
219
220 Literal::Literal(int r, int g, int b, int a)
221 : props(0)
222 , typeName("Color")
223 , i1(r), i2(g)
224 , i3(b), i4(a)
225 , b(false)
226 , type(COLOR) {
227
228 }
229
230 Literal::Literal(int number)
231 : props(0)
232 , typeName("Number")
233 , i1(number), i2(0)
234 , i3(0), i4(0)
235 , b(false)
236 , type(NUMBER) {
237
238 }
239
240 Literal::Literal(const string &dir, const string &path)
241 : props(0)
242 , typeName("Path")
243 , str(CatPath(dir, path))
244 , i1(0), i2(0)
245 , i3(0), i4(0)
246 , b(false)
247 , type(STRING) {
248
249 }
250
251 Literal::Literal(const string &str)
252 : props(0)
253 , typeName("String")
254 , str(str)
255 , i1(0), i2(0)
256 , i3(0), i4(0)
257 , b(false)
258 , type(STRING) {
259
260 }
261
262 Literal::Literal(int x, int y)
263 : props(0)
264 , typeName("Vector")
265 , i1(x), i2(y)
266 , i3(0), i4(0)
267 , b(false)
268 , type(VECTOR) {
269
270 }
271
272 Literal::Literal(const string &typeName, PropertyList *properties)
273 : props(properties)
274 , typeName(typeName)
275 , i1(0), i2(0)
276 , i3(0), i4(0)
277 , b(false)
278 , type(OBJECT) {
279
280 }
281
282 Literal::~Literal() {
283         switch (type) {
284                 case ARRAY_VALUES:
285                         for (vector<Value *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
286                                 delete *i;
287                         }
288                         break;
289                 case ARRAY_PROPS:
290                         for (vector<PropertyList *>::const_iterator i(propertyLists.begin()), end(propertyLists.end()); i != end; ++i) {
291                                 delete *i;
292                         }
293                         break;
294                 case OBJECT:
295                         delete props;
296                         break;
297                 default:
298                         break;
299         }
300 }
301
302
303 const vector<Value *> &Literal::GetValues() const {
304         if (type == ARRAY_VALUES) {
305                 return values;
306         } else {
307                 throw runtime_error("tried to access values of non-array literal");
308         }
309 }
310
311 const vector<PropertyList *> &Literal::GetPropertyLists() const {
312         if (type == ARRAY_PROPS) {
313                 return propertyLists;
314         } else {
315                 throw runtime_error("tried to access property lists of non-array literal");
316         }
317 }
318
319 bool Literal::GetBoolean() const {
320         if (type == BOOLEAN) {
321                 return b;
322         } else {
323                 throw runtime_error("tried to access boolean value of non-boolean literal");
324         }
325 }
326
327 int Literal::GetRed() const {
328         if (type == COLOR) {
329                 return i1;
330         } else {
331                 throw runtime_error("tried to access red component of non-color literal");
332         }
333 }
334
335 int Literal::GetGreen() const {
336         if (type == COLOR) {
337                 return i2;
338         } else {
339                 throw runtime_error("tried to access green component of non-color literal");
340         }
341 }
342
343 int Literal::GetBlue() const {
344         if (type == COLOR) {
345                 return i3;
346         } else {
347                 throw runtime_error("tried to access blue component of non-color literal");
348         }
349 }
350
351 int Literal::GetAlpha() const {
352         if (type == COLOR) {
353                 return i4;
354         } else {
355                 throw runtime_error("tried to access alpha component of non-color literal");
356         }
357 }
358
359 int Literal::GetNumber() const {
360         if (type == NUMBER) {
361                 return i1;
362         } else {
363                 throw runtime_error("tried to access numerical value of non-number literal");
364         }
365 }
366
367 const string &Literal::GetString() const {
368         if (type == STRING) {
369                 return str;
370         } else {
371                 throw runtime_error("tried to access string value of non-color literal");
372         }
373 }
374
375 int Literal::GetX() const {
376         if (type == VECTOR) {
377                 return i1;
378         } else {
379                 throw runtime_error("tried to access x component of non-vector literal");
380         }
381 }
382
383 int Literal::GetY() const {
384         if (type == VECTOR) {
385                 return i2;
386         } else {
387                 throw runtime_error("tried to access y component of non-vector literal");
388         }
389 }
390
391 const string &Literal::GetTypeName() const {
392         return typeName;
393 }
394
395 const PropertyList *Literal::GetProperties() const {
396         if (type == OBJECT) {
397                 return props;
398         } else {
399                 throw runtime_error("tried to access properties of non-object literal");
400         }
401 }
402
403
404 Value::~Value() {
405         if (isLiteral) {
406                 delete literal;
407         }
408 }
409
410 const Literal &Value::GetLiteral() const {
411         if (isLiteral) {
412                 return *literal;
413         } else {
414                 throw runtime_error("tried to access literal of identifier value");
415         }
416 }
417
418 const std::string &Value::GetIdentifier() const {
419         if (!isLiteral) {
420                 return identifier;
421         } else {
422                 throw runtime_error("tried to access identifier of literal value");
423         }
424 }
425
426 }
427
428
429 namespace std {
430
431 ostream &operator <<(ostream &out, const loader::ParsedSource &source) {
432         out << "parsed source file" << endl;
433         out << "declared objects: " << endl;
434         for (map<string, loader::Declaration *>::const_iterator i(source.Declarations().begin()), end(source.Declarations().end()); i != end; ++i) {
435                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
436         }
437         out << "defined objects: " << endl;
438         for (map<string, loader::Definition *>::const_iterator i(source.Definitions().begin()), end(source.Definitions().end()); i != end; ++i) {
439                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
440                 if (i->second->HasLiteralValue()) {
441                         out << "     literal value: " << *i->second->GetLiteral() << endl;
442                 }
443         }
444         out << "exported objects: " << endl;
445         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
446                 out << " - " << *i << endl;
447         }
448         return out;
449 }
450
451 ostream &operator <<(ostream &out, const loader::Literal &l) {
452         switch (l.GetType()) {
453                 case loader::Literal::ARRAY_VALUES:
454                         out << "array of values";
455                         break;
456                 case loader::Literal::ARRAY_PROPS:
457                         out << "array of property lists";
458                         break;
459                 case loader::Literal::BOOLEAN:
460                         out << "boolean, " << (l.GetBoolean() ? "true" : "false");
461                         break;
462                 case loader::Literal::COLOR:
463                         out << "color, (" << l.GetRed() << ',' << l.GetGreen() << ',' << l.GetBlue() << ',' << l.GetAlpha() << ')';
464                         break;
465                 case loader::Literal::NUMBER:
466                         out << "number, " << l.GetNumber();
467                         break;
468                 case loader::Literal::PATH:
469                         out << "path, \"" << l.GetString() << '"';
470                         break;
471                 case loader::Literal::STRING:
472                         out << "string, \"" << l.GetString() << '"';
473                         break;
474                 case loader::Literal::VECTOR:
475                         out << "vector, <" << l.GetX() << ',' << l.GetY() << '>';
476                         break;
477                 case loader::Literal::OBJECT:
478                         out << "object of type " << l.GetTypeName();
479                         break;
480         }
481         return out;
482 }
483
484 }