diff --git a/exceptions.h b/exceptions.h index 2998d08353..585963b9ea 100644 --- a/exceptions.h +++ b/exceptions.h @@ -6,6 +6,7 @@ namespace YAML { class Exception: public std::exception {}; class ScannerException: public Exception {}; + class ParserException: public Exception {}; class RepresentationException: public Exception {}; // scanner exceptions @@ -40,6 +41,12 @@ namespace YAML unsigned value; }; + // parser exceptions + class MapEndNotFound: public ParserException {}; + class SeqEndNotFound: public ParserException {}; + class BadYAMLDirective: public ParserException {}; + class BadTAGDirective: public ParserException {}; + // representation exceptions class InvalidScalar: public RepresentationException {}; class BadDereference: public RepresentationException {}; diff --git a/iterator.cpp b/iterator.cpp index a9161cd892..67d050d2b5 100644 --- a/iterator.cpp +++ b/iterator.cpp @@ -29,6 +29,18 @@ namespace YAML return *this; } + Node::Iterator Node::Iterator::operator ++ (int) + { + Iterator temp = *this; + + if(type == IT_SEQ) + ++seqIter; + else if(type == IT_MAP) + ++mapIter; + + return temp; + } + const Node& Node::Iterator::operator * () { if(type == IT_SEQ) diff --git a/main.cpp b/main.cpp index 3639503c5a..3b0fd885c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,71 @@ #include "parser.h" #include "node.h" -#include "exceptions.h" #include #include +struct Vec3 { + float x, y, z; + + friend std::ostream& operator << (std::ostream& out, const Vec3& v) { + out << v.x << " " << v.y << " " << v.z; + return out; + } +}; + +void operator >> (const YAML::Node& node, Vec3& v) +{ + YAML::Node::Iterator it = node.begin(); + *it >> v.x; + ++it; + *it >> v.y; + ++it; + *it >> v.z; +} + +struct Room { + std::string name; + Vec3 pos, size; + float height; + + friend std::ostream& operator << (std::ostream& out, const Room& room) { + out << "Name: " << room.name << std::endl; + out << "Pos: " << room.pos << std::endl; + out << "Size: " << room.size << std::endl; + out << "Height: " << room.height << std::endl; + return out; + } +}; + +void operator >> (const YAML::Node& node, Room& room) +{ + node["name"] >> room.name; + node["pos"] >> room.pos; + node["size"] >> room.size; + node["height"] >> room.height; +} + +struct Level { + std::vector rooms; + + friend std::ostream& operator << (std::ostream& out, const Level& level) { + for(unsigned i=0;i> (const YAML::Node& node, Level& level) +{ + const YAML::Node& rooms = node["rooms"]; + for(YAML::Node::Iterator it=rooms.begin();it!=rooms.end();++it) { + Room room; + *it >> room; + level.rooms.push_back(room); + } +} + int main() { std::ifstream fin("test.yaml"); @@ -17,16 +79,10 @@ int main() parser.GetNextDocument(doc); const YAML::Node& root = doc.GetRoot(); - for(YAML::Node::Iterator it=root.begin();it!=root.end();++it) { - std::cout << "Sequence:"; - for(YAML::Node::Iterator jt=it->begin();jt!=it->end();++jt) { - int value; - *jt >> value; - std::cout << " " << value; - } - std::cout << std::endl; - } - } catch(YAML::Exception& e) { + Level level; + root >> level; + std::cout << level; + } catch(YAML::Exception&) { std::cout << "Error parsing the yaml!\n"; } diff --git a/map.cpp b/map.cpp index 6cc511c5a7..a6da682db4 100644 --- a/map.cpp +++ b/map.cpp @@ -2,6 +2,7 @@ #include "node.h" #include "scanner.h" #include "token.h" +#include "exceptions.h" namespace YAML { @@ -56,10 +57,10 @@ namespace YAML while(1) { Token *pToken = pScanner->PeekNextToken(); if(!pToken) - break; // TODO: throw? + throw MapEndNotFound(); if(pToken->type != TT_KEY && pToken->type != TT_BLOCK_END) - break; // TODO: throw? + throw MapEndNotFound(); pScanner->PopNextToken(); if(pToken->type == TT_BLOCK_END) @@ -88,7 +89,7 @@ namespace YAML while(1) { Token *pToken = pScanner->PeekNextToken(); if(!pToken) - break; // TODO: throw? + throw MapEndNotFound(); // first check for end if(pToken->type == TT_FLOW_MAP_END) { @@ -98,7 +99,7 @@ namespace YAML // now it better be a key if(pToken->type != TT_KEY) - break; // TODO: throw? + throw MapEndNotFound(); pScanner->PopNextToken(); @@ -120,7 +121,7 @@ namespace YAML if(pToken->type == TT_FLOW_ENTRY) pScanner->EatNextToken(); else if(pToken->type != TT_FLOW_MAP_END) - break; // TODO: throw? + throw MapEndNotFound(); } } diff --git a/node.h b/node.h index dc2d60306f..8a76c7191f 100644 --- a/node.h +++ b/node.h @@ -26,6 +26,7 @@ namespace YAML friend bool operator == (const Iterator& it, const Iterator& jt); friend bool operator != (const Iterator& it, const Iterator& jt); Iterator& operator ++ (); + Iterator operator ++ (int); const Node& operator * (); const Node *operator -> (); const Node& first(); @@ -61,7 +62,7 @@ namespace YAML it.first() >> t; if(key == t) return it.second(); - } catch(InvalidScalar&) { + } catch(RepresentationException&) { } } diff --git a/parser.cpp b/parser.cpp index 053c83eaee..7b42d43550 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1,6 +1,7 @@ #include "parser.h" #include "scanner.h" #include "token.h" +#include "exceptions.h" #include namespace YAML @@ -62,23 +63,23 @@ namespace YAML // . Should be of the form 'major.minor' (like a version number) void Parser::HandleYamlDirective(const std::vector & params) { - if(params.empty()) - return; // TODO: throw? (or throw on params.size() > 1?) + if(params.size() != 1) + throw BadYAMLDirective(); std::stringstream str(params[0]); str >> m_state.version.major; str.get(); str >> m_state.version.minor; if(!str) - return; // TODO: throw? (or throw if there are any more characters in the stream?) + throw BadYAMLDirective(); // TODO: or throw if there are any more characters in the stream? - // TODO: throw on major > 1? warning on major == 1, minor > 1? + // TODO: throw on major > 1? warning on major == 1, minor > 2? } void Parser::HandleTagDirective(const std::vector & params) { if(params.size() != 2) - return; // TODO: throw? + throw BadTAGDirective(); std::string handle = params[0], prefix = params[1]; m_state.tags[handle] = prefix; diff --git a/parserstate.cpp b/parserstate.cpp index d0b5209209..d99b970c01 100644 --- a/parserstate.cpp +++ b/parserstate.cpp @@ -6,7 +6,7 @@ namespace YAML { // version version.major = 1; - version.minor = 1; + version.minor = 2; // and tags tags.clear(); diff --git a/sequence.cpp b/sequence.cpp index 16acfa4fcd..40dc3e058d 100644 --- a/sequence.cpp +++ b/sequence.cpp @@ -56,10 +56,10 @@ namespace YAML while(1) { Token *pToken = pScanner->PeekNextToken(); if(!pToken) - break; // TODO: throw? + throw SeqEndNotFound(); if(pToken->type != TT_BLOCK_ENTRY && pToken->type != TT_BLOCK_END) - break; // TODO: throw? + throw SeqEndNotFound(); pScanner->PopNextToken(); if(pToken->type == TT_BLOCK_END) @@ -99,7 +99,7 @@ namespace YAML while(1) { Token *pToken = pScanner->PeekNextToken(); if(!pToken) - break; // TODO: throw? + throw SeqEndNotFound(); // first check for end if(pToken->type == TT_FLOW_SEQ_END) { @@ -117,7 +117,7 @@ namespace YAML if(pToken->type == TT_FLOW_ENTRY) pScanner->EatNextToken(); else if(pToken->type != TT_FLOW_SEQ_END) - break; // TODO: throw? + throw SeqEndNotFound(); } } diff --git a/test.yaml b/test.yaml index f18974185d..8a9714cfc8 100644 --- a/test.yaml +++ b/test.yaml @@ -1,4 +1,97 @@ --- -- [1, 2, 3] -- [2, 4, 6] -... \ No newline at end of file +model: + file: data/models/compound.model + textures: data/materials/compound +rooms: + - name: "Room #1" + pos: [0, 0, 0] + size: [1000, 1000, 500] + height: 500 + stairtype: none + display: [] + pathfinding: + tilesize: 50 + size: [24, 24] + map: | + ----------------------- + -+++++++++++++++++++++- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+--------------------- + -+--------------------- + -+--------------------- + -+--------------------- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+++++++++++++++++++++- + ----------------------- + - name: Doorway + pos: [1000, 400, 0] + size: [50, 200, 500] + height: 500 + stairtype: none + display: [] + pathfinding: + tilesize: 50 + size: [5, 9] + map: | + ----- + -+++- + ----- + ----- + ----- + ----- + ----- + -+++- + ----- + - name: "Room #2" + pos: [1050, 0, 0] + size: [1000, 1000, 500] + height: 500 + stairtype: none + display: [] + pathfinding: + tilesize: 50 + size: [24, 24] + map: | + ----------------------- + -+++++++++++++++++++++- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + ---------------------+- + ---------------------+- + ---------------------+- + ---------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+-------------------+- + -+++++++++++++++++++++- + ----------------------- +exits: + - room1: "Room #1" + room2: "Room #2" + dir: e + pos: [400, 600]