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