]> git.localhorst.tv Git - l2e.git/blob - src/loader/ParsedSource.cpp
8c3d3bd17415d5cd4fe7ff92df6b42a45204127a
[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(const vector<ScriptToken *> &s)
283 : props(0)
284 , script(s)
285 , i1(0), i2(0)
286 , i3(0), i4(0)
287 , b(false)
288 , type(SCRIPT) {
289
290 }
291
292 Literal::~Literal() {
293         switch (type) {
294                 case ARRAY_VALUES:
295                         for (vector<Value *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
296                                 delete *i;
297                         }
298                         break;
299                 case ARRAY_PROPS:
300                         for (vector<PropertyList *>::const_iterator i(propertyLists.begin()), end(propertyLists.end()); i != end; ++i) {
301                                 delete *i;
302                         }
303                         break;
304                 case OBJECT:
305                         delete props;
306                         break;
307                 case SCRIPT:
308                         for (vector<ScriptToken *>::const_iterator i(script.begin()), end(script.end()); i != end; ++i) {
309                                 delete *i;
310                         }
311                         break;
312                 default:
313                         break;
314         }
315 }
316
317
318 const vector<Value *> &Literal::GetValues() const {
319         if (type == ARRAY_VALUES) {
320                 return values;
321         } else {
322                 throw runtime_error("tried to access values of non-array literal");
323         }
324 }
325
326 const vector<PropertyList *> &Literal::GetPropertyLists() const {
327         if (type == ARRAY_PROPS) {
328                 return propertyLists;
329         } else {
330                 throw runtime_error("tried to access property lists of non-array literal");
331         }
332 }
333
334 bool Literal::GetBoolean() const {
335         if (type == BOOLEAN) {
336                 return b;
337         } else {
338                 throw runtime_error("tried to access boolean value of non-boolean literal");
339         }
340 }
341
342 int Literal::GetRed() const {
343         if (type == COLOR) {
344                 return i1;
345         } else {
346                 throw runtime_error("tried to access red component of non-color literal");
347         }
348 }
349
350 int Literal::GetGreen() const {
351         if (type == COLOR) {
352                 return i2;
353         } else {
354                 throw runtime_error("tried to access green component of non-color literal");
355         }
356 }
357
358 int Literal::GetBlue() const {
359         if (type == COLOR) {
360                 return i3;
361         } else {
362                 throw runtime_error("tried to access blue component of non-color literal");
363         }
364 }
365
366 int Literal::GetAlpha() const {
367         if (type == COLOR) {
368                 return i4;
369         } else {
370                 throw runtime_error("tried to access alpha component of non-color literal");
371         }
372 }
373
374 int Literal::GetNumber() const {
375         if (type == NUMBER) {
376                 return i1;
377         } else {
378                 throw runtime_error("tried to access numerical value of non-number literal");
379         }
380 }
381
382 const string &Literal::GetString() const {
383         if (type == STRING) {
384                 return str;
385         } else {
386                 throw runtime_error("tried to access string value of non-color literal");
387         }
388 }
389
390 int Literal::GetX() const {
391         if (type == VECTOR) {
392                 return i1;
393         } else {
394                 throw runtime_error("tried to access x component of non-vector literal");
395         }
396 }
397
398 int Literal::GetY() const {
399         if (type == VECTOR) {
400                 return i2;
401         } else {
402                 throw runtime_error("tried to access y component of non-vector literal");
403         }
404 }
405
406 const string &Literal::GetTypeName() const {
407         return typeName;
408 }
409
410 const PropertyList *Literal::GetProperties() const {
411         if (type == OBJECT) {
412                 return props;
413         } else {
414                 throw runtime_error("tried to access properties of non-object literal");
415         }
416 }
417
418 const vector<ScriptToken *> &Literal::GetScript() const {
419         if (type == SCRIPT) {
420                 return script;
421         } else {
422                 throw runtime_error("tried to access script of non-script literal");
423         }
424 }
425
426
427 Value::~Value() {
428         if (isLiteral) {
429                 delete literal;
430         }
431 }
432
433 const Literal &Value::GetLiteral() const {
434         if (isLiteral) {
435                 return *literal;
436         } else {
437                 throw runtime_error("tried to access literal of identifier value");
438         }
439 }
440
441 const std::string &Value::GetIdentifier() const {
442         if (!isLiteral) {
443                 return identifier;
444         } else {
445                 throw runtime_error("tried to access identifier of literal value");
446         }
447 }
448
449
450 ScriptToken::ScriptToken(const string &s, Type t)
451 : literal(0)
452 , str(s)
453 , type(t) {
454         if (type == LITERAL) {
455                 throw runtime_error("cannot create script literal without literal");
456         }
457 }
458
459 ScriptToken::ScriptToken(Literal *l)
460 : literal(l)
461 , str()
462 , type(LITERAL) {
463         if (!literal) {
464                 throw runtime_error("cannot create script literal without literal");
465         }
466 }
467
468 ScriptToken::~ScriptToken() {
469         delete literal;
470 }
471
472 const string &ScriptToken::RegisterName() const {
473         if (type == REGISTER) {
474                 return str;
475         } else {
476                 throw runtime_error("access to register name of non-register script token");
477         }
478 }
479
480 const string &ScriptToken::CommandName() const {
481         if (type == COMMAND) {
482                 return str;
483         } else {
484                 throw runtime_error("access to command name of non-command script token");
485         }
486 }
487
488 const string &ScriptToken::Identifier() const {
489         if (type == IDENTIFIER) {
490                 return str;
491         } else {
492                 throw runtime_error("access to identifier of non-identifier script token");
493         }
494 }
495
496 const string &ScriptToken::Label() const {
497         if (type == LABEL) {
498                 return str;
499         } else {
500                 throw runtime_error("access to label of non-label script token");
501         }
502 }
503
504 const Literal *ScriptToken::GetLiteral() const {
505         if (type == LITERAL) {
506                 return literal;
507         } else {
508                 throw runtime_error("access to literal value of non-literal script token");
509         }
510 }
511
512 }
513
514
515 namespace std {
516
517 ostream &operator <<(ostream &out, const loader::ParsedSource &source) {
518         out << "parsed source file" << endl;
519         out << "declared objects: " << endl;
520         for (map<string, loader::Declaration *>::const_iterator i(source.Declarations().begin()), end(source.Declarations().end()); i != end; ++i) {
521                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
522         }
523         out << "defined objects: " << endl;
524         for (map<string, loader::Definition *>::const_iterator i(source.Definitions().begin()), end(source.Definitions().end()); i != end; ++i) {
525                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
526                 if (i->second->HasLiteralValue()) {
527                         out << "     literal value: " << *i->second->GetLiteral() << endl;
528                 }
529         }
530         out << "exported objects: " << endl;
531         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
532                 out << " - " << *i << endl;
533         }
534         return out;
535 }
536
537 ostream &operator <<(ostream &out, const loader::Literal &l) {
538         switch (l.GetType()) {
539                 case loader::Literal::ARRAY_VALUES:
540                         out << "array of values";
541                         break;
542                 case loader::Literal::ARRAY_PROPS:
543                         out << "array of property lists";
544                         break;
545                 case loader::Literal::BOOLEAN:
546                         out << "boolean, " << (l.GetBoolean() ? "true" : "false");
547                         break;
548                 case loader::Literal::COLOR:
549                         out << "color, (" << l.GetRed() << ',' << l.GetGreen() << ',' << l.GetBlue() << ',' << l.GetAlpha() << ')';
550                         break;
551                 case loader::Literal::NUMBER:
552                         out << "number, " << l.GetNumber();
553                         break;
554                 case loader::Literal::PATH:
555                         out << "path, \"" << l.GetString() << '"';
556                         break;
557                 case loader::Literal::STRING:
558                         out << "string, \"" << l.GetString() << '"';
559                         break;
560                 case loader::Literal::VECTOR:
561                         out << "vector, <" << l.GetX() << ',' << l.GetY() << '>';
562                         break;
563                 case loader::Literal::OBJECT:
564                         out << "object of type " << l.GetTypeName();
565                         break;
566                 case loader::Literal::SCRIPT:
567                         out << "script";
568                         break;
569         }
570         return out;
571 }
572
573 }