From 09d7ab365fa4050e07729903389c82c26283119e Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sun, 20 Jul 2008 05:02:01 +0000 Subject: [PATCH] Replaced the queue of Token pointers with values. We were getting memory leaks (as told by the CRT detectors, which I also added), and there's really no reason (as long as we're careful) to use pointers there. --- include/crt.h | 10 +++++ include/exceptions.h | 2 + include/yaml.h | 6 +++ src/content.cpp | 1 + src/exp.cpp | 1 + src/iterator.cpp | 1 + src/map.cpp | 53 +++++++++++++------------- src/node.cpp | 46 +++++++++++----------- src/parser.cpp | 30 ++++++++------- src/parserstate.cpp | 1 + src/regex.cpp | 1 + src/scalar.cpp | 7 ++-- src/scanner.cpp | 81 ++++++++++++++++----------------------- src/scanner.h | 12 +++--- src/scanscalar.cpp | 1 + src/scantoken.cpp | 57 ++++++++++++++-------------- src/sequence.cpp | 46 +++++++++++----------- src/simplekey.cpp | 5 ++- src/stream.cpp | 1 + test.yaml | 3 -- yaml-reader.vcproj | 2 +- yaml-reader/main.cpp | 88 ++++++++----------------------------------- yaml-reader/tests.cpp | 79 ++++++++++++++++++++++++++++++++++++++ yaml-reader/tests.h | 6 +++ yamlcpp.vcproj | 8 ++++ 25 files changed, 297 insertions(+), 251 deletions(-) create mode 100644 include/crt.h create mode 100644 include/yaml.h delete mode 100644 test.yaml create mode 100644 yaml-reader/tests.cpp create mode 100644 yaml-reader/tests.h diff --git a/include/crt.h b/include/crt.h new file mode 100644 index 0000000..e59a20c --- /dev/null +++ b/include/crt.h @@ -0,0 +1,10 @@ +#pragma once + +// for memory leaks +#ifdef _DEBUG + +#define _CRTDBG_MAP_ALLOC +#include +#include + +#endif // _DEBUG \ No newline at end of file diff --git a/include/exceptions.h b/include/exceptions.h index f3a27f0..0e6031e 100644 --- a/include/exceptions.h +++ b/include/exceptions.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace YAML { @@ -9,6 +10,7 @@ namespace YAML public: ParserException(int line_, int column_, const std::string& msg_) : line(line_), column(column_), msg(msg_) {} + int line, column; std::string msg; }; diff --git a/include/yaml.h b/include/yaml.h new file mode 100644 index 0000000..08f79ca --- /dev/null +++ b/include/yaml.h @@ -0,0 +1,6 @@ +#pragma once + +#include "crt.h" +#include "parser.h" +#include "node.h" +#include "exceptions.h" \ No newline at end of file diff --git a/src/content.cpp b/src/content.cpp index b68bb25..4995729 100644 --- a/src/content.cpp +++ b/src/content.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "content.h" namespace YAML diff --git a/src/exp.cpp b/src/exp.cpp index 05b1b24..8ce2af7 100644 --- a/src/exp.cpp +++ b/src/exp.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "exp.h" #include "exceptions.h" #include diff --git a/src/iterator.cpp b/src/iterator.cpp index bd671be..b39cec3 100644 --- a/src/iterator.cpp +++ b/src/iterator.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "node.h" #include "exceptions.h" diff --git a/src/map.cpp b/src/map.cpp index 19a3cb9..cdb5fdf 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "map.h" #include "node.h" #include "scanner.h" @@ -41,9 +42,9 @@ namespace YAML Clear(); // split based on start token - Token *pToken = pScanner->PeekNextToken(); + Token& token = pScanner->PeekToken(); - switch(pToken->type) { + switch(token.type) { case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break; case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break; } @@ -52,18 +53,18 @@ namespace YAML void Map::ParseBlock(Scanner *pScanner, const ParserState& state) { // eat start token - pScanner->EatNextToken(); + pScanner->PopToken(); while(1) { - Token *pToken = pScanner->PeekNextToken(); - if(!pToken) + if(pScanner->IsEmpty()) throw ParserException(-1, -1, ErrorMsg::END_OF_MAP); - if(pToken->type != TT_KEY && pToken->type != TT_BLOCK_END) - throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_MAP); + Token token = pScanner->PeekToken(); + if(token.type != TT_KEY && token.type != TT_BLOCK_END) + throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP); - pScanner->PopNextToken(); - if(pToken->type == TT_BLOCK_END) + pScanner->PopToken(); + if(token.type == TT_BLOCK_END) break; Node *pKey = new Node; @@ -74,8 +75,8 @@ namespace YAML pKey->Parse(pScanner, state); // now grab value (optional) - if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) { - pScanner->PopNextToken(); + if(!pScanner->IsEmpty() && pScanner->PeekToken().type == TT_VALUE) { + pScanner->PopToken(); pValue->Parse(pScanner, state); } @@ -91,24 +92,24 @@ namespace YAML void Map::ParseFlow(Scanner *pScanner, const ParserState& state) { // eat start token - pScanner->EatNextToken(); + pScanner->PopToken(); while(1) { - Token *pToken = pScanner->PeekNextToken(); - if(!pToken) + if(pScanner->IsEmpty()) throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW); + Token& token = pScanner->PeekToken(); // first check for end - if(pToken->type == TT_FLOW_MAP_END) { - pScanner->EatNextToken(); + if(token.type == TT_FLOW_MAP_END) { + pScanner->PopToken(); break; } // now it better be a key - if(pToken->type != TT_KEY) - throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_MAP_FLOW); + if(token.type != TT_KEY) + throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP_FLOW); - pScanner->PopNextToken(); + pScanner->PopToken(); Node *pKey = new Node; Node *pValue = new Node; @@ -118,17 +119,17 @@ namespace YAML pKey->Parse(pScanner, state); // now grab value (optional) - if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) { - pScanner->PopNextToken(); + if(!pScanner->IsEmpty() && pScanner->PeekToken().type == TT_VALUE) { + pScanner->PopToken(); pValue->Parse(pScanner, state); } // now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node) - pToken = pScanner->PeekNextToken(); - if(pToken->type == TT_FLOW_ENTRY) - pScanner->EatNextToken(); - else if(pToken->type != TT_FLOW_MAP_END) - throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_MAP_FLOW); + Token& nextToken = pScanner->PeekToken(); + if(nextToken.type == TT_FLOW_ENTRY) + pScanner->PopToken(); + else if(nextToken.type != TT_FLOW_MAP_END) + throw ParserException(nextToken.line, nextToken.column, ErrorMsg::END_OF_MAP_FLOW); m_data[pKey] = pValue; } catch(Exception& e) { diff --git a/src/node.cpp b/src/node.cpp index c878e9a..1250aa0 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "node.h" #include "token.h" #include "scanner.h" @@ -42,11 +43,7 @@ namespace YAML return; // now split based on what kind of node we should be - Token *pToken = pScanner->PeekNextToken(); - if(pToken->type == TT_DOC_END) - return; - - switch(pToken->type) { + switch(pScanner->PeekToken().type) { case TT_SCALAR: m_pContent = new Scalar; m_pContent->Parse(pScanner, state); @@ -61,6 +58,7 @@ namespace YAML case TT_BLOCK_MAP_START: m_pContent = new Map; m_pContent->Parse(pScanner, state); + break; } } @@ -69,53 +67,53 @@ namespace YAML void Node::ParseHeader(Scanner *pScanner, const ParserState& state) { while(1) { - Token *pToken = pScanner->PeekNextToken(); - if(!pToken || (pToken->type != TT_TAG && pToken->type != TT_ANCHOR && pToken->type != TT_ALIAS)) - break; + if(pScanner->IsEmpty()) + return; - switch(pToken->type) { + switch(pScanner->PeekToken().type) { case TT_TAG: ParseTag(pScanner, state); break; case TT_ANCHOR: ParseAnchor(pScanner, state); break; case TT_ALIAS: ParseAlias(pScanner, state); break; + default: return; } } } void Node::ParseTag(Scanner *pScanner, const ParserState& state) { - Token *pToken = pScanner->PeekNextToken(); + Token& token = pScanner->PeekToken(); if(m_tag != "") - throw ParserException(pToken->line, pToken->column, ErrorMsg::MULTIPLE_TAGS); + throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_TAGS); - m_tag = state.TranslateTag(pToken->value); + m_tag = state.TranslateTag(token.value); - for(unsigned i=0;iparams.size();i++) - m_tag += pToken->params[i]; - pScanner->PopNextToken(); + for(unsigned i=0;iPopToken(); } void Node::ParseAnchor(Scanner *pScanner, const ParserState& state) { - Token *pToken = pScanner->PeekNextToken(); + Token& token = pScanner->PeekToken(); if(m_anchor != "") - throw ParserException(pToken->line, pToken->column, ErrorMsg::MULTIPLE_ANCHORS); + throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ANCHORS); - m_anchor = pToken->value; + m_anchor = token.value; m_alias = false; - pScanner->PopNextToken(); + pScanner->PopToken(); } void Node::ParseAlias(Scanner *pScanner, const ParserState& state) { - Token *pToken = pScanner->PeekNextToken(); + Token& token = pScanner->PeekToken(); if(m_anchor != "") - throw ParserException(pToken->line, pToken->column, ErrorMsg::MULTIPLE_ALIASES); + throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ALIASES); if(m_tag != "") - throw ParserException(pToken->line, pToken->column, ErrorMsg::ALIAS_CONTENT); + throw ParserException(token.line, token.column, ErrorMsg::ALIAS_CONTENT); - m_anchor = pToken->value; + m_anchor = token.value; m_alias = true; - pScanner->PopNextToken(); + pScanner->PopToken(); } void Node::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) const diff --git a/src/parser.cpp b/src/parser.cpp index 2caaa89..9c40430 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "parser.h" #include "scanner.h" #include "token.h" @@ -18,7 +19,7 @@ namespace YAML Parser::operator bool() const { - return m_pScanner->PeekNextToken() != 0; + return !m_pScanner->IsEmpty(); } void Parser::Load(std::istream& in) @@ -40,19 +41,19 @@ namespace YAML ParseDirectives(); // we better have some tokens in the queue - if(!m_pScanner->PeekNextToken()) + if(m_pScanner->IsEmpty()) return; // first eat doc start (optional) - if(m_pScanner->PeekNextToken()->type == TT_DOC_START) - m_pScanner->EatNextToken(); + if(m_pScanner->PeekToken().type == TT_DOC_START) + m_pScanner->PopToken(); // now parse our root node document.Parse(m_pScanner, m_state); // and finally eat any doc ends we see - while(m_pScanner->PeekNextToken() && m_pScanner->PeekNextToken()->type == TT_DOC_END) - m_pScanner->EatNextToken(); + while(!m_pScanner->IsEmpty() && m_pScanner->PeekToken().type == TT_DOC_END) + m_pScanner->PopToken(); } // ParseDirectives @@ -62,8 +63,11 @@ namespace YAML bool readDirective = false; while(1) { - Token *pToken = m_pScanner->PeekNextToken(); - if(!pToken || pToken->type != TT_DIRECTIVE) + if(m_pScanner->IsEmpty()) + break; + + Token& token = m_pScanner->PeekToken(); + if(token.type != TT_DIRECTIVE) break; // we keep the directives from the last document if none are specified; @@ -72,8 +76,8 @@ namespace YAML m_state.Reset(); readDirective = true; - HandleDirective(pToken); - m_pScanner->PopNextToken(); + HandleDirective(&token); + m_pScanner->PopToken(); } } @@ -119,11 +123,11 @@ namespace YAML void Parser::PrintTokens(std::ostream& out) { while(1) { - Token *pToken = m_pScanner->GetNextToken(); - if(!pToken) + if(m_pScanner->IsEmpty()) break; - out << *pToken << std::endl; + out << m_pScanner->PeekToken() << std::endl; + m_pScanner->PopToken(); } } } diff --git a/src/parserstate.cpp b/src/parserstate.cpp index d99b970..4a14b3a 100644 --- a/src/parserstate.cpp +++ b/src/parserstate.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "parserstate.h" namespace YAML diff --git a/src/regex.cpp b/src/regex.cpp index e7f93e1..cbd1eb0 100644 --- a/src/regex.cpp +++ b/src/regex.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "regex.h" namespace YAML diff --git a/src/scalar.cpp b/src/scalar.cpp index 6be1bf4..0038cc1 100644 --- a/src/scalar.cpp +++ b/src/scalar.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "scalar.h" #include "scanner.h" #include "token.h" @@ -16,9 +17,9 @@ namespace YAML void Scalar::Parse(Scanner *pScanner, const ParserState& state) { - Token *pToken = pScanner->GetNextToken(); - m_data = pToken->value; - delete pToken; + Token& token = pScanner->PeekToken(); + m_data = token.value; + pScanner->PopToken(); } void Scalar::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) diff --git a/src/scanner.cpp b/src/scanner.cpp index 110d1a3..bf2a23e 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "scanner.h" #include "token.h" #include "exceptions.h" @@ -12,62 +13,46 @@ namespace YAML Scanner::~Scanner() { - while(!m_tokens.empty()) { - delete m_tokens.front(); - m_tokens.pop(); - } } - // GetNextToken - // . Removes and returns the next token on the queue. - Token *Scanner::GetNextToken() + // IsEmpty + // . Returns true if there are no more tokens to be read + bool Scanner::IsEmpty() { - Token *pToken = PeekNextToken(); + PeekToken(); // to ensure that there are tokens in the queue, if possible + return m_tokens.empty(); + } + + // PopToken + // . Simply removes the next token on the queue. + void Scanner::PopToken() + { + PeekToken(); // to ensure that there are tokens in the queue if(!m_tokens.empty()) m_tokens.pop(); - return pToken; } - // PopNextToken - // . Simply removes the next token on the queue. - void Scanner::PopNextToken() - { - GetNextToken(); - } - - // EatNextToken - // . Removes and deletes the next token on the queue - void Scanner::EatNextToken() - { - delete GetNextToken(); - } - - // PeekNextToken + // PeekToken // . Returns (but does not remove) the next token on the queue, and scans if only we need to. - Token *Scanner::PeekNextToken() + Token& Scanner::PeekToken() { while(1) { - Token *pToken = 0; + if(!m_tokens.empty()) { + Token& token = m_tokens.front(); - // is there a token in the queue? - if(!m_tokens.empty()) - pToken = m_tokens.front(); + // return this guy if it's valid + if(token.status == TS_VALID) + return token; - // (here's where we clean up the impossible tokens) - if(pToken && pToken->status == TS_INVALID) { - m_tokens.pop(); - delete pToken; - continue; + // here's where we clean up the impossible tokens + if(token.status == TS_INVALID) { + m_tokens.pop(); + continue; + } + + // note: what's left are the unverified tokens } - // on unverified tokens, we just have to wait - if(pToken && pToken->status == TS_UNVERIFIED) - pToken = 0; - - // then that's what we want - if(pToken) - return pToken; - // no token? maybe we've actually finished if(m_endedStream) break; @@ -76,7 +61,7 @@ namespace YAML ScanNextToken(); } - return 0; + // TODO: find something to return here, or assert (but can't do that! maybe split into two functions?) } // ScanNextToken @@ -254,14 +239,12 @@ namespace YAML // now push m_indents.push(column); - Token *pToken = 0; if(sequence) - pToken = new Token(TT_BLOCK_SEQ_START, INPUT.line, INPUT.column); + m_tokens.push(Token(TT_BLOCK_SEQ_START, INPUT.line, INPUT.column)); else - pToken = new Token(TT_BLOCK_MAP_START, INPUT.line, INPUT.column); + m_tokens.push(Token(TT_BLOCK_MAP_START, INPUT.line, INPUT.column)); - m_tokens.push(pToken); - return pToken; + return &m_tokens.back(); } // PopIndentTo @@ -276,7 +259,7 @@ namespace YAML // now pop away while(!m_indents.empty() && m_indents.top() > column) { m_indents.pop(); - m_tokens.push(new Token(TT_BLOCK_END, INPUT.line, INPUT.column)); + m_tokens.push(Token(TT_BLOCK_END, INPUT.line, INPUT.column)); } } } diff --git a/src/scanner.h b/src/scanner.h index 63a911b..06fd509 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -6,21 +6,19 @@ #include #include #include "stream.h" +#include "token.h" namespace YAML { - struct Token; - class Scanner { public: Scanner(std::istream& in); ~Scanner(); - Token *GetNextToken(); - void EatNextToken(); - void PopNextToken(); - Token *PeekNextToken(); + bool IsEmpty(); + void PopToken(); + Token& PeekToken(); private: // scanning @@ -72,7 +70,7 @@ namespace YAML Stream INPUT; // the output (tokens) - std::queue m_tokens; + std::queue m_tokens; // state info bool m_startedStream, m_endedStream; diff --git a/src/scanscalar.cpp b/src/scanscalar.cpp index c2cf2b9..70abef4 100644 --- a/src/scanscalar.cpp +++ b/src/scanscalar.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "scanscalar.h" #include "scanner.h" #include "exp.h" diff --git a/src/scantoken.cpp b/src/scantoken.cpp index 5704a0a..31489ae 100644 --- a/src/scantoken.cpp +++ b/src/scantoken.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "scanner.h" #include "token.h" #include "exceptions.h" @@ -49,10 +50,10 @@ namespace YAML params.push_back(param); } - Token *pToken = new Token(TT_DIRECTIVE, line, column); - pToken->value = name; - pToken->params = params; - m_tokens.push(pToken); + Token token(TT_DIRECTIVE, line, column); + token.value = name; + token.params = params; + m_tokens.push(token); } // DocStart @@ -65,7 +66,7 @@ namespace YAML // eat int line = INPUT.line, column = INPUT.column; INPUT.eat(3); - m_tokens.push(new Token(TT_DOC_START, line, column)); + m_tokens.push(Token(TT_DOC_START, line, column)); } // DocEnd @@ -78,7 +79,7 @@ namespace YAML // eat int line = INPUT.line, column = INPUT.column; INPUT.eat(3); - m_tokens.push(new Token(TT_DOC_END, line, column)); + m_tokens.push(Token(TT_DOC_END, line, column)); } // FlowStart @@ -93,7 +94,7 @@ namespace YAML int line = INPUT.line, column = INPUT.column; char ch = INPUT.get(); TOKEN_TYPE type = (ch == Keys::FlowSeqStart ? TT_FLOW_SEQ_START : TT_FLOW_MAP_START); - m_tokens.push(new Token(type, line, column)); + m_tokens.push(Token(type, line, column)); } // FlowEnd @@ -109,7 +110,7 @@ namespace YAML int line = INPUT.line, column = INPUT.column; char ch = INPUT.get(); TOKEN_TYPE type = (ch == Keys::FlowSeqEnd ? TT_FLOW_SEQ_END : TT_FLOW_MAP_END); - m_tokens.push(new Token(type, line, column)); + m_tokens.push(Token(type, line, column)); } // FlowEntry @@ -120,7 +121,7 @@ namespace YAML // eat int line = INPUT.line, column = INPUT.column; INPUT.eat(1); - m_tokens.push(new Token(TT_FLOW_ENTRY, line, column)); + m_tokens.push(Token(TT_FLOW_ENTRY, line, column)); } // BlockEntry @@ -140,7 +141,7 @@ namespace YAML // eat int line = INPUT.line, column = INPUT.column; INPUT.eat(1); - m_tokens.push(new Token(TT_BLOCK_ENTRY, line, column)); + m_tokens.push(Token(TT_BLOCK_ENTRY, line, column)); } // Key @@ -163,7 +164,7 @@ namespace YAML // eat int line = INPUT.line, column = INPUT.column; INPUT.eat(1); - m_tokens.push(new Token(TT_KEY, line, column)); + m_tokens.push(Token(TT_KEY, line, column)); } // Value @@ -192,7 +193,7 @@ namespace YAML // eat int line = INPUT.line, column = INPUT.column; INPUT.eat(1); - m_tokens.push(new Token(TT_VALUE, line, column)); + m_tokens.push(Token(TT_VALUE, line, column)); } // AnchorOrAlias @@ -224,9 +225,9 @@ namespace YAML throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR); // and we're done - Token *pToken = new Token(alias ? TT_ALIAS : TT_ANCHOR, line, column); - pToken->value = name; - m_tokens.push(pToken); + Token token(alias ? TT_ALIAS : TT_ANCHOR, line, column); + token.value = name; + m_tokens.push(token); } // Tag @@ -261,10 +262,10 @@ namespace YAML handle = "!"; } - Token *pToken = new Token(TT_TAG, line, column); - pToken->value = handle; - pToken->params.push_back(suffix); - m_tokens.push(pToken); + Token token(TT_TAG, line, column); + token.value = handle; + token.params.push_back(suffix); + m_tokens.push(token); } // PlainScalar @@ -298,9 +299,9 @@ namespace YAML //if(Exp::IllegalCharInScalar.Matches(INPUT)) // throw ParserException(INPUT.line, INPUT.column, ErrorMsg::CHAR_IN_SCALAR); - Token *pToken = new Token(TT_SCALAR, line, column); - pToken->value = scalar; - m_tokens.push(pToken); + Token token(TT_SCALAR, line, column); + token.value = scalar; + m_tokens.push(token); } // QuotedScalar @@ -332,9 +333,9 @@ namespace YAML scalar = ScanScalar(INPUT, params); m_simpleKeyAllowed = false; - Token *pToken = new Token(TT_SCALAR, line, column); - pToken->value = scalar; - m_tokens.push(pToken); + Token token(TT_SCALAR, line, column); + token.value = scalar; + m_tokens.push(token); } // BlockScalarToken @@ -397,8 +398,8 @@ namespace YAML // simple keys always ok after block scalars (since we're gonna start a new line anyways) m_simpleKeyAllowed = true; - Token *pToken = new Token(TT_SCALAR, line, column); - pToken->value = scalar; - m_tokens.push(pToken); + Token token(TT_SCALAR, line, column); + token.value = scalar; + m_tokens.push(token); } } diff --git a/src/sequence.cpp b/src/sequence.cpp index 8c1e3ca..fed6a97 100644 --- a/src/sequence.cpp +++ b/src/sequence.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "sequence.h" #include "node.h" #include "scanner.h" @@ -51,9 +52,9 @@ namespace YAML Clear(); // split based on start token - Token *pToken = pScanner->PeekNextToken(); + Token& token = pScanner->PeekToken(); - switch(pToken->type) { + switch(token.type) { case TT_BLOCK_SEQ_START: ParseBlock(pScanner, state); break; case TT_BLOCK_ENTRY: ParseImplicit(pScanner, state); break; case TT_FLOW_SEQ_START: ParseFlow(pScanner, state); break; @@ -63,18 +64,18 @@ namespace YAML void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state) { // eat start token - pScanner->EatNextToken(); + pScanner->PopToken(); while(1) { - Token *pToken = pScanner->PeekNextToken(); - if(!pToken) + if(pScanner->IsEmpty()) throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ); - if(pToken->type != TT_BLOCK_ENTRY && pToken->type != TT_BLOCK_END) - throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_SEQ); + Token token = pScanner->PeekToken(); + if(token.type != TT_BLOCK_ENTRY && token.type != TT_BLOCK_END) + throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ); - pScanner->PopNextToken(); - if(pToken->type == TT_BLOCK_END) + pScanner->PopToken(); + if(token.type == TT_BLOCK_END) break; Node *pNode = new Node; @@ -86,16 +87,16 @@ namespace YAML void Sequence::ParseImplicit(Scanner *pScanner, const ParserState& state) { while(1) { - Token *pToken = pScanner->PeekNextToken(); // we're actually *allowed* to have no tokens at some point - if(!pToken) + if(pScanner->IsEmpty()) break; // and we end at anything other than a block entry - if(pToken->type != TT_BLOCK_ENTRY) + Token& token = pScanner->PeekToken(); + if(token.type != TT_BLOCK_ENTRY) break; - pScanner->PopNextToken(); + pScanner->PopToken(); Node *pNode = new Node; m_data.push_back(pNode); @@ -106,16 +107,15 @@ namespace YAML void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state) { // eat start token - pScanner->EatNextToken(); + pScanner->PopToken(); while(1) { - Token *pToken = pScanner->PeekNextToken(); - if(!pToken) + if(pScanner->IsEmpty()) throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ_FLOW); // first check for end - if(pToken->type == TT_FLOW_SEQ_END) { - pScanner->PopNextToken(); + if(pScanner->PeekToken().type == TT_FLOW_SEQ_END) { + pScanner->PopToken(); break; } @@ -125,11 +125,11 @@ namespace YAML pNode->Parse(pScanner, state); // now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node) - pToken = pScanner->PeekNextToken(); - if(pToken->type == TT_FLOW_ENTRY) - pScanner->EatNextToken(); - else if(pToken->type != TT_FLOW_SEQ_END) - throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_SEQ_FLOW); + Token& token = pScanner->PeekToken(); + if(token.type == TT_FLOW_ENTRY) + pScanner->PopToken(); + else if(token.type != TT_FLOW_SEQ_END) + throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ_FLOW); } } diff --git a/src/simplekey.cpp b/src/simplekey.cpp index a5e6bc3..e9d25ee 100644 --- a/src/simplekey.cpp +++ b/src/simplekey.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "scanner.h" #include "token.h" #include "exceptions.h" @@ -39,9 +40,9 @@ namespace YAML key.pMapStart->status = TS_UNVERIFIED; // then add the (now unverified) key - key.pKey = new Token(TT_KEY, INPUT.line, INPUT.column); + m_tokens.push(Token(TT_KEY, INPUT.line, INPUT.column)); + key.pKey = &m_tokens.back(); key.pKey->status = TS_UNVERIFIED; - m_tokens.push(key.pKey); m_simpleKeys.push(key); } diff --git a/src/stream.cpp b/src/stream.cpp index f3668fe..38f4c8e 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -1,3 +1,4 @@ +#include "crt.h" #include "stream.h" namespace YAML diff --git a/test.yaml b/test.yaml deleted file mode 100644 index 28e1b7d..0000000 --- a/test.yaml +++ /dev/null @@ -1,3 +0,0 @@ -abeginning: value -zend: value -middle: value \ No newline at end of file diff --git a/yaml-reader.vcproj b/yaml-reader.vcproj index d5d72e5..b864dc6 100644 --- a/yaml-reader.vcproj +++ b/yaml-reader.vcproj @@ -206,7 +206,7 @@ > diff --git a/yaml-reader/main.cpp b/yaml-reader/main.cpp index 2da42f0..3f47840 100644 --- a/yaml-reader/main.cpp +++ b/yaml-reader/main.cpp @@ -1,4 +1,4 @@ -#include "parser.h" +#include "yaml.h" #include "tests.h" #include #include @@ -9,85 +9,29 @@ #pragma comment(lib, "yamlcpp.lib") #endif -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) +void run() { - node[0] >> v.x; - node[1] >> v.y; - node[2] >> v.z; -} + std::ifstream fin("yaml-reader/tests/test.yaml"); -struct Room { - std::string name; - Vec3 pos, size; - float height; + try { + YAML::Parser parser(fin); + if(!parser) + return; - 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(unsigned i=0;i> room; - level.rooms.push_back(room); + YAML::Node doc; + parser.GetNextDocument(doc); + std::cout << doc; + } catch(YAML::Exception&) { + std::cout << "Error parsing the yaml!\n"; } } int main() -{ - YAML::Test::RunAll(); - - //std::ifstream fin("test.yaml"); - - //try { - // YAML::Parser parser(fin); - // if(!parser) - // return 0; - - // YAML::Node doc; - // parser.GetNextDocument(doc); - // std::cout << doc; - //} catch(YAML::Exception&) { - // std::cout << "Error parsing the yaml!\n"; - //} +{ + _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF); + Test::RunAll(); + run(); getchar(); - return 0; } diff --git a/yaml-reader/tests.cpp b/yaml-reader/tests.cpp new file mode 100644 index 0000000..48ce8ef --- /dev/null +++ b/yaml-reader/tests.cpp @@ -0,0 +1,79 @@ +#include "yaml.h" +#include "tests.h" +#include "parser.h" +#include +#include +#include +#include + +namespace Test +{ + // runs all the tests on all data we have + void RunAll() + { + std::vector files; + files.push_back("yaml-reader/tests/simple.yaml"); + files.push_back("yaml-reader/tests/mixed.yaml"); + files.push_back("yaml-reader/tests/scalars.yaml"); + files.push_back("yaml-reader/tests/directives.yaml"); + + bool passed = true; + for(unsigned i=0;i + +namespace Test { + void RunAll(); + bool Inout(const std::string& file); +} diff --git a/yamlcpp.vcproj b/yamlcpp.vcproj index 2c9ed53..0bd0e81 100644 --- a/yamlcpp.vcproj +++ b/yamlcpp.vcproj @@ -230,10 +230,18 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + + +