#include "ParsedSource.h"
#include "../battle/Hero.h"
#include "../battle/Monster.h"
+#include "../battle/PartyLayout.h"
#include "../graphics/ComplexAnimation.h"
#include "../graphics/SimpleAnimation.h"
#include "../graphics/Sprite.h"
#include <algorithm>
+#include <cstring>
#include <SDL_image.h>
using battle::Hero;
using battle::Monster;
+using battle::PartyLayout;
using battle::Stats;
using graphics::Animation;
using graphics::ComplexAnimation;
namespace loader {
Interpreter::~Interpreter() {
- for (vector<Animation *>::const_iterator i(animations.begin()), end(animations.end()); i != end; ++i) {
+ for (vector<ComplexAnimation *>::const_iterator i(complexAnimations.begin()), end(complexAnimations.end()); i != end; ++i) {
delete *i;
}
for (vector<Hero *>::const_iterator i(heroes.begin()), end(heroes.end()); i != end; ++i) {
for (vector<Monster *>::const_iterator i(monsters.begin()), end(monsters.end()); i != end; ++i) {
delete *i;
}
+ for (vector<PartyLayout *>::const_iterator i(partyLayouts.begin()), end(partyLayouts.end()); i != end; ++i) {
+ delete *i;
+ }
+ for (vector<SimpleAnimation *>::const_iterator i(simpleAnimations.begin()), end(simpleAnimations.end()); i != end; ++i) {
+ delete *i;
+ }
for (vector<Sprite *>::const_iterator i(sprites.begin()), end(sprites.end()); i != end; ++i) {
delete *i;
}
-}
-
-
-bool Interpreter::ParsedDefinition::IsCompatible(DynamicType with) const {
- return type == with
- || (with == ANIMATION
- && (type == COMPLEX_ANIMATION || type == SIMPLE_ANIMATION));
+ for (vector<const char *>::const_iterator i(strings.begin()), end(strings.end()); i != end; ++i) {
+ delete *i;
+ }
}
Animation *Interpreter::GetAnimation(const std::string &name) {
map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
if (i != parsedDefinitions.end()) {
- if (i->second.IsCompatible(ANIMATION)) {
- return animations[i->second.index];
+ if (i->second.type == COMPLEX_ANIMATION) {
+ return complexAnimations[i->second.index];
+ } else if (i->second.type == SIMPLE_ANIMATION) {
+ return simpleAnimations[i->second.index];
} else {
throw Error("cannot cast " + i->second.dfn->TypeName() + " to Animation");
}
}
}
+bool Interpreter::GetBoolean(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == BOOLEAN) {
+ return booleans[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Boolean");
+ }
+ } else {
+ throw Error("access to undefined Boolean " + name);
+ }
+}
+
Hero *Interpreter::GetHero(const std::string &name) {
map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
if (i != parsedDefinitions.end()) {
- if (i->second.IsCompatible(HERO)) {
+ if (i->second.type == HERO) {
return heroes[i->second.index];
} else {
throw Error("cannot cast " + i->second.dfn->TypeName() + " to Hero");
Monster *Interpreter::GetMonster(const std::string &name) {
map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
if (i != parsedDefinitions.end()) {
- if (i->second.IsCompatible(MONSTER)) {
+ if (i->second.type == MONSTER) {
return monsters[i->second.index];
} else {
throw Error("cannot cast " + i->second.dfn->TypeName() + " to Monster");
int Interpreter::GetNumber(const std::string &name) const {
map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
if (i != parsedDefinitions.end()) {
- if (i->second.IsCompatible(NUMBER)) {
+ if (i->second.type == NUMBER) {
return numbers[i->second.index];
} else {
throw Error("cannot cast " + i->second.dfn->TypeName() + " to Number");
}
}
+PartyLayout *Interpreter::GetPartyLayout(const std::string &name) {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == PARTY_LAYOUT) {
+ return partyLayouts[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to PartyLayout");
+ }
+ } else {
+ throw Error("access to undefined PartyLayout " + name);
+ }
+}
+
Sprite *Interpreter::GetSprite(const std::string &name) {
map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
if (i != parsedDefinitions.end()) {
- if (i->second.IsCompatible(SPRITE)) {
+ if (i->second.type == SPRITE) {
return sprites[i->second.index];
} else {
throw Error("cannot cast " + i->second.dfn->TypeName() + " to Sprite");
}
}
+const char *Interpreter::GetString(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == STRING) {
+ return strings[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to String");
+ }
+ } else {
+ throw Error("access to undefined String " + name);
+ }
+}
+
+Vector<int> Interpreter::GetVector(const std::string &name) const {
+ map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ if (i->second.type == VECTOR) {
+ return vectors[i->second.index];
+ } else {
+ throw Error("cannot cast " + i->second.dfn->TypeName() + " to Vector");
+ }
+ } else {
+ throw Error("access to undefined Vector " + name);
+ }
+}
+
void Interpreter::ReadSource() {
for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
void Interpreter::ReadLiteral(const Definition &dfn) {
switch (dfn.GetLiteral()->GetType()) {
case Literal::ARRAY_VALUES:
- throw Error("unhandled literal: array of values");
+ valueArrays.push_back(dfn.GetLiteral()->GetValues());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VALUE_ARRAY, valueArrays.size() - 1)));
break;
case Literal::ARRAY_PROPS:
- throw Error("unhandled literal: array of properties");
+ propertyListArrays.push_back(dfn.GetLiteral()->GetPropertyLists());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PROPERTY_LIST_ARRAY, propertyListArrays.size() - 1)));
break;
case Literal::BOOLEAN:
- throw Error("unhandled literal: boolean");
+ booleans.push_back(dfn.GetLiteral()->GetBoolean());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, BOOLEAN, booleans.size() - 1)));
break;
case Literal::COLOR:
throw Error("unhandled literal: color");
parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, NUMBER, numbers.size() - 1)));
break;
case Literal::STRING:
- throw Error("unhandled literal: string");
+ {
+ char *str(new char[dfn.GetLiteral()->GetString().size() + 1]);
+ std::memcpy(str, dfn.GetLiteral()->GetString().c_str(), dfn.GetLiteral()->GetString().size());
+ str[dfn.GetLiteral()->GetString().size()] = '\0';
+ strings.push_back(str);
+ }
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, STRING, strings.size() - 1)));
break;
case Literal::VECTOR:
- throw Error("unhandled literal: vector");
+ vectors.push_back(Vector<int>(dfn.GetLiteral()->GetX(), dfn.GetLiteral()->GetY()));
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, VECTOR, vectors.size() - 1)));
break;
case Literal::OBJECT:
- throw Error("unhandled literal: object");
+ ReadObject(dfn);
break;
}
}
if (v.GetLiteral().GetTypeName() == "ComplexAnimation") {
ComplexAnimation *a(new ComplexAnimation);
ReadComplexAnimation(*a, *v.GetLiteral().GetProperties());
- animations.push_back(a);
+ complexAnimations.push_back(a);
return a;
} else {
SimpleAnimation *a(new SimpleAnimation);
ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties());
- animations.push_back(a);
+ simpleAnimations.push_back(a);
return a;
}
} else {
}
}
-const vector<Value *> &Interpreter::GetValueArray(const Value &v) {
- if (v.IsLiteral()) {
- return v.GetLiteral().GetValues();
- } else {
- throw Error("identifier resolution not implemented for arrays of values");
- }
-}
-
-const vector<PropertyList *> &Interpreter::GetPropertyListArray(const Value &v) {
- if (v.IsLiteral()) {
- return v.GetLiteral().GetPropertyLists();
- } else {
- throw Error("identifier resolution not implemented for arrays of property lists");
- }
-}
-
bool Interpreter::GetBoolean(const Value &v) {
if (v.IsLiteral()) {
return v.GetLiteral().GetBoolean();
} else {
- throw Error("identifier resolution not implemented for booleans");
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetBoolean(v.GetIdentifier());
}
}
}
}
+PartyLayout *Interpreter::GetPartyLayout(const Value &v) {
+ if (v.IsLiteral()) {
+ PartyLayout *l(new PartyLayout);
+ ReadPartyLayout(*l, *v.GetLiteral().GetProperties());
+ return l;
+ } else {
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetPartyLayout(v.GetIdentifier());
+ }
+}
+
const PropertyList *Interpreter::GetPropertyList(const Value &v) {
if (v.IsLiteral()) {
return v.GetLiteral().GetProperties();
} else {
- throw Error("identifier resolution not implemented for property lists");
+ throw Error("cannot reference property lists");
+ }
+}
+
+const vector<PropertyList *> &Interpreter::GetPropertyListArray(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetPropertyLists();
+ } else {
+ throw Error("cannot reference property list arrays");
}
}
if (v.IsLiteral()) {
return v.GetLiteral().GetString().c_str();
} else {
- throw Error("identifier resolution not implemented for strings");
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetString(v.GetIdentifier());
}
}
if (v.IsLiteral()) {
return Vector<int>(v.GetLiteral().GetX(), v.GetLiteral().GetY());
} else {
- throw Error("identifier resolution not implemented for vectors");
+ ReadDefinition(source.GetDefinition(v.GetIdentifier()));
+ return GetVector(v.GetIdentifier());
+ }
+}
+
+const vector<Value *> &Interpreter::GetValueArray(const Value &v) {
+ if (v.IsLiteral()) {
+ return v.GetLiteral().GetValues();
+ } else {
+ throw Error("cannot reference value arrays");
}
}
void Interpreter::ReadObject(const Definition &dfn) {
- if (dfn.TypeName() == "Hero") {
+ if (dfn.TypeName() == "ComplexAnimation") {
+ ComplexAnimation *animation(new ComplexAnimation);
+ int index(complexAnimations.size());
+ complexAnimations.push_back(animation);
+ ReadComplexAnimation(*animation, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, COMPLEX_ANIMATION, index)));
+ } else if (dfn.TypeName() == "Hero") {
Hero *hero(new Hero);
int index(heroes.size());
heroes.push_back(hero);
monsters.push_back(monster);
ReadMonster(*monster, *dfn.GetProperties());
parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, MONSTER, index)));
+ } else if (dfn.TypeName() == "PartyLayout") {
+ PartyLayout *layout(new PartyLayout);
+ int index(partyLayouts.size());
+ partyLayouts.push_back(layout);
+ ReadPartyLayout(*layout, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, PARTY_LAYOUT, index)));
+ } else if (dfn.TypeName() == "SimpleAnimation") {
+ SimpleAnimation *animation(new SimpleAnimation);
+ int index(simpleAnimations.size());
+ simpleAnimations.push_back(animation);
+ ReadSimpleAnimation(*animation, *dfn.GetProperties());
+ parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, SIMPLE_ANIMATION, index)));
} else if (dfn.TypeName() == "Sprite") {
Sprite *sprite(new Sprite);
int index(sprites.size());
}
}
+void Interpreter::ReadPartyLayout(PartyLayout &p, const PropertyList &props) {
+ for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
+ if (i->first == "positions") {
+ const vector<Value *> &positions(GetValueArray(*i->second));
+ for (vector<Value *>::const_iterator j(positions.begin()), end(positions.end()); j != end; ++j) {
+ p.AddPosition(GetVector(**j));
+ }
+ } else {
+ throw Error("unknown PartyLayout property: " + i->first);
+ }
+ }
+}
+
void Interpreter::ReadSimpleAnimation(SimpleAnimation &a, const PropertyList &props) {
for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
if (i->first == "sprite") {