]> git.localhorst.tv Git - l2e.git/blob - src/loader/ParsedSource.cpp
removed stupid file headers that eclipse put in
[l2e.git] / src / loader / ParsedSource.cpp
1 #include "ParsedSource.h"
2
3 #include "utility.h"
4
5 #include <ostream>
6 #include <stdexcept>
7
8 using std::map;
9 using std::runtime_error;
10 using std::string;
11 using std::vector;
12
13 namespace loader {
14
15 ParsedSource::~ParsedSource() {
16         for (map<string, Declaration *>::const_iterator i(declarations.begin()), end(declarations.end()); i != end; ++i) {
17                 delete i->second;
18         }
19 }
20
21 void ParsedSource::AddDeclaration(Declaration *d) {
22         map<string, Declaration *>::iterator i(declarations.find(d->Identifier()));
23         if (i != declarations.end()) {
24                 if (d->TypeName() != i->second->TypeName()) {
25                         throw runtime_error("invalid redeclaration of " + i->second->TypeName() + " " + d->Identifier());
26                 }
27         } else {
28                 declarations.insert(std::make_pair(d->Identifier(), d));
29         }
30 }
31
32 void ParsedSource::AddDefinition(Definition *d) {
33         map<string, Definition *>::iterator i(definitions.find(d->Identifier()));
34         if (i != definitions.end()) {
35                 throw runtime_error("redefinition of " + i->second->TypeName() + " " + d->Identifier());
36         } else {
37                 definitions.insert(std::make_pair(d->Identifier(), d));
38         }
39 }
40
41 void ParsedSource::ExportDeclaration(Declaration *d) {
42         AddDeclaration(d);
43         exports.insert(d->Identifier());
44 }
45
46 void ParsedSource::ExportIdentifier(const std::string &i) {
47         if (declarations.count(i)) {
48                 exports.insert(i);
49         } else {
50                 throw runtime_error("cannot export undeclared identifier " + i);
51         }
52 }
53
54
55 bool ParsedSource::IsDeclared(const std::string &name) const {
56         return declarations.count(name);
57 }
58
59 Declaration &ParsedSource::GetDeclaration(const std::string &name) {
60         map<string, Declaration *>::const_iterator i(declarations.find(name));
61         if (i != declarations.end()) {
62                 return *i->second;
63         } else {
64                 throw runtime_error("undeclared identifier " + name);
65         }
66 }
67
68 const Declaration &ParsedSource::GetDeclaration(const std::string &name) const {
69         map<string, Declaration *>::const_iterator i(declarations.find(name));
70         if (i != declarations.end()) {
71                 return *i->second;
72         } else {
73                 throw runtime_error("undeclared identifier " + name);
74         }
75 }
76
77 bool ParsedSource::IsDefined(const std::string &name) const {
78         return definitions.count(name);
79 }
80
81 Definition &ParsedSource::GetDefinition(const std::string &name) {
82         map<string, Definition *>::const_iterator i(definitions.find(name));
83         if (i != definitions.end()) {
84                 return *i->second;
85         } else {
86                 string msg("undefined identifier " + name);
87                 map<string, Declaration *>::const_iterator i(declarations.find(name));
88                 if (i != declarations.end()) {
89                         msg += ", declared as " + i->second->TypeName();
90                 } else {
91                         msg += ", not declared";
92                 }
93                 throw runtime_error(msg);
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                 string msg("undefined identifier " + name);
103                 map<string, Declaration *>::const_iterator i(declarations.find(name));
104                 if (i != declarations.end()) {
105                         msg += ", declared as " + i->second->TypeName();
106                 } else {
107                         msg += ", not declared";
108                 }
109                 throw runtime_error(msg);
110         }
111 }
112
113 void ParsedSource::WriteHeader(std::ostream &out) const {
114         for (std::set<string>::const_iterator i(exports.begin()), end(exports.end()); i != end; ++i) {
115                 out << GetDeclaration(*i).TypeName() << ' ' << *i << std::endl;
116         }
117 }
118
119
120 Definition::~Definition() {
121         if (isLiteral) {
122                 delete reinterpret_cast<Literal *>(value);
123         } else {
124                 delete reinterpret_cast<PropertyList *>(value);
125         }
126 }
127
128 void Definition::SetValue(Literal *v) {
129         value = v;
130         isLiteral = true;
131 }
132
133 void Definition::SetValue(PropertyList *v) {
134         value = v;
135         isLiteral = false;
136 }
137
138 Literal *Definition::GetLiteral() {
139         if (isLiteral) {
140                 return reinterpret_cast<Literal *>(value);
141         } else {
142                 throw runtime_error("tried to access properties as literal");
143         }
144 }
145
146 const Literal *Definition::GetLiteral() const {
147         if (isLiteral) {
148                 return reinterpret_cast<Literal *>(value);
149         } else {
150                 throw runtime_error("tried to access properties as literal");
151         }
152 }
153
154 PropertyList *Definition::GetProperties() {
155         if (!isLiteral) {
156                 return reinterpret_cast<PropertyList *>(value);
157         } else {
158                 throw runtime_error("tried to access literal value as property list");
159         }
160 }
161
162 const PropertyList *Definition::GetProperties() const {
163         if (!isLiteral) {
164                 return reinterpret_cast<PropertyList *>(value);
165         } else if (GetLiteral()->GetType() == Literal::OBJECT) {
166                 return GetLiteral()->GetProperties();
167         } else {
168                 throw runtime_error("tried to access literal value as property list");
169         }
170 }
171
172
173 PropertyList::~PropertyList() {
174         for (map<string, Value *>::iterator i(props.begin()), end(props.end()); i != end; ++i) {
175                 delete i->second;
176         }
177 }
178
179
180 Literal::Literal(const vector<Value *> &v)
181 : props(0)
182 , values(v)
183 , i1(0), i2(0)
184 , i3(0), i4(0)
185 , b(false)
186 , type(ARRAY_VALUES) {
187         if (!v.empty()) {
188                 typeName = v.front()->GetLiteral().GetTypeName();
189         }
190 }
191
192 Literal::Literal(const string &typeName, const vector<PropertyList *> &pls)
193 : props(0)
194 , typeName(typeName)
195 , propertyLists(pls)
196 , i1(0), i2(0)
197 , i3(0), i4(0)
198 , b(false)
199 , type(ARRAY_PROPS) {
200
201 }
202
203 Literal::Literal(bool b)
204 : props(0)
205 , typeName("Boolean")
206 , i1(0), i2(0)
207 , i3(0), i4(0)
208 , b(b)
209 , type(BOOLEAN) {
210
211 }
212
213 Literal::Literal(int r, int g, int b, int a)
214 : props(0)
215 , typeName("Color")
216 , i1(r), i2(g)
217 , i3(b), i4(a)
218 , b(false)
219 , type(COLOR) {
220
221 }
222
223 Literal::Literal(int number)
224 : props(0)
225 , typeName("Number")
226 , i1(number), i2(0)
227 , i3(0), i4(0)
228 , b(false)
229 , type(NUMBER) {
230
231 }
232
233 Literal::Literal(const string &dir, const string &path)
234 : props(0)
235 , typeName("Path")
236 , str(CatPath(dir, path))
237 , i1(0), i2(0)
238 , i3(0), i4(0)
239 , b(false)
240 , type(STRING) {
241
242 }
243
244 Literal::Literal(const string &str)
245 : props(0)
246 , typeName("String")
247 , str(str)
248 , i1(0), i2(0)
249 , i3(0), i4(0)
250 , b(false)
251 , type(STRING) {
252
253 }
254
255 Literal::Literal(int x, int y)
256 : props(0)
257 , typeName("Vector")
258 , i1(x), i2(y)
259 , i3(0), i4(0)
260 , b(false)
261 , type(VECTOR) {
262
263 }
264
265 Literal::Literal(const string &typeName, PropertyList *properties)
266 : props(properties)
267 , typeName(typeName)
268 , i1(0), i2(0)
269 , i3(0), i4(0)
270 , b(false)
271 , type(OBJECT) {
272
273 }
274
275 Literal::Literal(const vector<ScriptToken *> &s)
276 : props(0)
277 , script(s)
278 , i1(0), i2(0)
279 , i3(0), i4(0)
280 , b(false)
281 , type(SCRIPT) {
282
283 }
284
285 Literal::~Literal() {
286         switch (type) {
287                 case ARRAY_VALUES:
288                         for (vector<Value *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
289                                 delete *i;
290                         }
291                         break;
292                 case ARRAY_PROPS:
293                         for (vector<PropertyList *>::const_iterator i(propertyLists.begin()), end(propertyLists.end()); i != end; ++i) {
294                                 delete *i;
295                         }
296                         break;
297                 case OBJECT:
298                         delete props;
299                         break;
300                 case SCRIPT:
301                         for (vector<ScriptToken *>::const_iterator i(script.begin()), end(script.end()); i != end; ++i) {
302                                 delete *i;
303                         }
304                         break;
305                 default:
306                         break;
307         }
308 }
309
310
311 const vector<Value *> &Literal::GetValues() const {
312         if (type == ARRAY_VALUES) {
313                 return values;
314         } else {
315                 throw runtime_error("tried to access values of non-array literal");
316         }
317 }
318
319 const vector<PropertyList *> &Literal::GetPropertyLists() const {
320         if (type == ARRAY_PROPS) {
321                 return propertyLists;
322         } else {
323                 throw runtime_error("tried to access property lists of non-array literal");
324         }
325 }
326
327 bool Literal::GetBoolean() const {
328         if (type == BOOLEAN) {
329                 return b;
330         } else {
331                 throw runtime_error("tried to access boolean value of non-boolean literal");
332         }
333 }
334
335 int Literal::GetRed() const {
336         if (type == COLOR) {
337                 return i1;
338         } else {
339                 throw runtime_error("tried to access red component of non-color literal");
340         }
341 }
342
343 int Literal::GetGreen() const {
344         if (type == COLOR) {
345                 return i2;
346         } else {
347                 throw runtime_error("tried to access green component of non-color literal");
348         }
349 }
350
351 int Literal::GetBlue() const {
352         if (type == COLOR) {
353                 return i3;
354         } else {
355                 throw runtime_error("tried to access blue component of non-color literal");
356         }
357 }
358
359 int Literal::GetAlpha() const {
360         if (type == COLOR) {
361                 return i4;
362         } else {
363                 throw runtime_error("tried to access alpha component of non-color literal");
364         }
365 }
366
367 int Literal::GetNumber() const {
368         if (type == NUMBER) {
369                 return i1;
370         } else {
371                 throw runtime_error("tried to access numerical value of non-number literal");
372         }
373 }
374
375 const string &Literal::GetString() const {
376         if (type == STRING) {
377                 return str;
378         } else {
379                 throw runtime_error("tried to access string value of non-color literal");
380         }
381 }
382
383 int Literal::GetX() const {
384         if (type == VECTOR) {
385                 return i1;
386         } else {
387                 throw runtime_error("tried to access x component of non-vector literal");
388         }
389 }
390
391 int Literal::GetY() const {
392         if (type == VECTOR) {
393                 return i2;
394         } else {
395                 throw runtime_error("tried to access y component of non-vector literal");
396         }
397 }
398
399 const string &Literal::GetTypeName() const {
400         return typeName;
401 }
402
403 const PropertyList *Literal::GetProperties() const {
404         if (type == OBJECT) {
405                 return props;
406         } else {
407                 throw runtime_error("tried to access properties of non-object literal");
408         }
409 }
410
411 const vector<ScriptToken *> &Literal::GetScript() const {
412         if (type == SCRIPT) {
413                 return script;
414         } else {
415                 throw runtime_error("tried to access script of non-script literal");
416         }
417 }
418
419
420 Value::~Value() {
421         if (isLiteral) {
422                 delete literal;
423         }
424 }
425
426 const Literal &Value::GetLiteral() const {
427         if (isLiteral) {
428                 return *literal;
429         } else {
430                 throw runtime_error("tried to access literal of identifier value");
431         }
432 }
433
434 const std::string &Value::GetIdentifier() const {
435         if (!isLiteral) {
436                 return identifier;
437         } else {
438                 throw runtime_error("tried to access identifier of literal value");
439         }
440 }
441
442
443 ScriptToken::ScriptToken(const string &s, Type t)
444 : literal(0)
445 , str(s)
446 , type(t) {
447         if (type == LITERAL) {
448                 throw runtime_error("cannot create script literal without literal");
449         }
450 }
451
452 ScriptToken::ScriptToken(Literal *l)
453 : literal(l)
454 , str()
455 , type(LITERAL) {
456         if (!literal) {
457                 throw runtime_error("cannot create script literal without literal");
458         }
459 }
460
461 ScriptToken::~ScriptToken() {
462         delete literal;
463 }
464
465 const string &ScriptToken::RegisterName() const {
466         if (type == REGISTER) {
467                 return str;
468         } else {
469                 throw runtime_error("access to register name of non-register script token");
470         }
471 }
472
473 const string &ScriptToken::CommandName() const {
474         if (type == COMMAND) {
475                 return str;
476         } else {
477                 throw runtime_error("access to command name of non-command script token");
478         }
479 }
480
481 const string &ScriptToken::Identifier() const {
482         if (type == IDENTIFIER) {
483                 return str;
484         } else {
485                 throw runtime_error("access to identifier of non-identifier script token");
486         }
487 }
488
489 const string &ScriptToken::Label() const {
490         if (type == LABEL) {
491                 return str;
492         } else {
493                 throw runtime_error("access to label of non-label script token");
494         }
495 }
496
497 const Literal *ScriptToken::GetLiteral() const {
498         if (type == LITERAL) {
499                 return literal;
500         } else {
501                 throw runtime_error("access to literal value of non-literal script token");
502         }
503 }
504
505 }
506
507
508 namespace std {
509
510 ostream &operator <<(ostream &out, const loader::ParsedSource &source) {
511         out << "parsed source file" << endl;
512         out << "declared objects: " << endl;
513         for (map<string, loader::Declaration *>::const_iterator i(source.Declarations().begin()), end(source.Declarations().end()); i != end; ++i) {
514                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
515         }
516         out << "defined objects: " << endl;
517         for (map<string, loader::Definition *>::const_iterator i(source.Definitions().begin()), end(source.Definitions().end()); i != end; ++i) {
518                 out << " - " << i->first << " of type " << i->second->TypeName() << endl;
519                 if (i->second->HasLiteralValue()) {
520                         out << "     literal value: " << *i->second->GetLiteral() << endl;
521                 }
522         }
523         out << "exported objects: " << endl;
524         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
525                 out << " - " << *i << endl;
526         }
527         return out;
528 }
529
530 ostream &operator <<(ostream &out, const loader::Literal &l) {
531         switch (l.GetType()) {
532                 case loader::Literal::ARRAY_VALUES:
533                         out << "array of values";
534                         break;
535                 case loader::Literal::ARRAY_PROPS:
536                         out << "array of property lists";
537                         break;
538                 case loader::Literal::BOOLEAN:
539                         out << "boolean, " << (l.GetBoolean() ? "true" : "false");
540                         break;
541                 case loader::Literal::COLOR:
542                         out << "color, (" << l.GetRed() << ',' << l.GetGreen() << ',' << l.GetBlue() << ',' << l.GetAlpha() << ')';
543                         break;
544                 case loader::Literal::NUMBER:
545                         out << "number, " << l.GetNumber();
546                         break;
547                 case loader::Literal::PATH:
548                         out << "path, \"" << l.GetString() << '"';
549                         break;
550                 case loader::Literal::STRING:
551                         out << "string, \"" << l.GetString() << '"';
552                         break;
553                 case loader::Literal::VECTOR:
554                         out << "vector, <" << l.GetX() << ',' << l.GetY() << '>';
555                         break;
556                 case loader::Literal::OBJECT:
557                         out << "object of type " << l.GetTypeName();
558                         break;
559                 case loader::Literal::SCRIPT:
560                         out << "script";
561                         break;
562         }
563         return out;
564 }
565
566 }