From 89ed418b8366066a8d54d4c2ae98454919fbc207 Mon Sep 17 00:00:00 2001 From: beder Date: Wed, 23 Jul 2008 04:38:18 +0000 Subject: [PATCH] Small changes in the iterator code. Changed the public interface of Scanner to resemble an STL container. --- include/crt.h | 2 +- include/iterator.h | 13 +++++++------ include/parser.h | 5 +++++ src/iterator.cpp | 10 +++++----- src/iterpriv.cpp | 17 ----------------- src/iterpriv.h | 8 +++++--- src/map.cpp | 34 ++++++++++++++++------------------ src/node.cpp | 18 +++++++++--------- src/parser.cpp | 24 ++++++++++++------------ src/scalar.cpp | 4 ++-- src/scanner.cpp | 39 +++++++++++++++++++++++++-------------- src/scanner.h | 12 +++++++----- src/sequence.cpp | 30 ++++++++++++++---------------- yamlcpp.vcproj | 4 ---- 14 files changed, 108 insertions(+), 112 deletions(-) delete mode 100644 src/iterpriv.cpp diff --git a/include/crt.h b/include/crt.h index e59a20c..82f13ec 100644 --- a/include/crt.h +++ b/include/crt.h @@ -1,6 +1,6 @@ #pragma once -// for memory leaks +// for detecting memory leaks #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC diff --git a/include/iterator.h b/include/iterator.h index b0b7e34..afaddb6 100644 --- a/include/iterator.h +++ b/include/iterator.h @@ -13,15 +13,16 @@ namespace YAML Iterator(const Iterator& rhs); ~Iterator(); - friend bool operator == (const Iterator& it, const Iterator& jt); - friend bool operator != (const Iterator& it, const Iterator& jt); Iterator& operator = (const Iterator& rhs); Iterator& operator ++ (); Iterator operator ++ (int); - const Node& operator * (); - const Node *operator -> (); - const Node& first(); - const Node& second(); + const Node& operator * () const; + const Node *operator -> () const; + const Node& first() const; + const Node& second() const; + + friend bool operator == (const Iterator& it, const Iterator& jt); + friend bool operator != (const Iterator& it, const Iterator& jt); private: IterPriv *m_pData; diff --git a/include/parser.h b/include/parser.h index 2b9b8ea..ef4d656 100644 --- a/include/parser.h +++ b/include/parser.h @@ -30,6 +30,11 @@ namespace YAML void HandleYamlDirective(Token *pToken); void HandleTagDirective(Token *pToken); + private: + // can't copy this + Parser(const Parser& rhs) {} + Parser& operator = (const Parser& rhs) { return *this; } + private: Scanner *m_pScanner; ParserState m_state; diff --git a/src/iterator.cpp b/src/iterator.cpp index bc3233a..1ce3dc0 100644 --- a/src/iterator.cpp +++ b/src/iterator.cpp @@ -56,7 +56,7 @@ namespace YAML return temp; } - const Node& Iterator::operator * () + const Node& Iterator::operator * () const { if(m_pData->type == IterPriv::IT_SEQ) return **m_pData->seqIter; @@ -64,15 +64,15 @@ namespace YAML throw BadDereference(); } - const Node *Iterator::operator -> () + const Node *Iterator::operator -> () const { if(m_pData->type == IterPriv::IT_SEQ) - return &**m_pData->seqIter; + return *m_pData->seqIter; throw BadDereference(); } - const Node& Iterator::first() + const Node& Iterator::first() const { if(m_pData->type == IterPriv::IT_MAP) return *m_pData->mapIter->first; @@ -80,7 +80,7 @@ namespace YAML throw BadDereference(); } - const Node& Iterator::second() + const Node& Iterator::second() const { if(m_pData->type == IterPriv::IT_MAP) return *m_pData->mapIter->second; diff --git a/src/iterpriv.cpp b/src/iterpriv.cpp deleted file mode 100644 index e2ff8f2..0000000 --- a/src/iterpriv.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "crt.h" -#include "iterpriv.h" - -namespace YAML -{ - IterPriv::IterPriv(): type(IT_NONE) - { - } - - IterPriv::IterPriv(std::vector ::const_iterator it): seqIter(it), type(IT_SEQ) - { - } - - IterPriv::IterPriv(std::map ::const_iterator it): mapIter(it), type(IT_MAP) - { - } -} diff --git a/src/iterpriv.h b/src/iterpriv.h index 5946ee9..80d7d6a 100644 --- a/src/iterpriv.h +++ b/src/iterpriv.h @@ -8,11 +8,13 @@ namespace YAML { class Node; + // IterPriv + // . The implementation for iterators - essentially a union of sequence and map iterators. struct IterPriv { - IterPriv(); - IterPriv(std::vector ::const_iterator it); - IterPriv(std::map ::const_iterator it); + IterPriv(): type(IT_NONE) {} + IterPriv(std::vector ::const_iterator it): seqIter(it), type(IT_SEQ) {} + IterPriv(std::map ::const_iterator it): mapIter(it), type(IT_MAP) {} enum ITER_TYPE { IT_NONE, IT_SEQ, IT_MAP }; ITER_TYPE type; diff --git a/src/map.cpp b/src/map.cpp index cdb5fdf..bfd8b6f 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -42,9 +42,7 @@ namespace YAML Clear(); // split based on start token - Token& token = pScanner->PeekToken(); - - switch(token.type) { + switch(pScanner->peek().type) { case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break; case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break; } @@ -53,17 +51,17 @@ namespace YAML void Map::ParseBlock(Scanner *pScanner, const ParserState& state) { // eat start token - pScanner->PopToken(); + pScanner->pop(); while(1) { - if(pScanner->IsEmpty()) + if(pScanner->empty()) throw ParserException(-1, -1, ErrorMsg::END_OF_MAP); - Token token = pScanner->PeekToken(); + Token token = pScanner->peek(); if(token.type != TT_KEY && token.type != TT_BLOCK_END) throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP); - pScanner->PopToken(); + pScanner->pop(); if(token.type == TT_BLOCK_END) break; @@ -75,8 +73,8 @@ namespace YAML pKey->Parse(pScanner, state); // now grab value (optional) - if(!pScanner->IsEmpty() && pScanner->PeekToken().type == TT_VALUE) { - pScanner->PopToken(); + if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) { + pScanner->pop(); pValue->Parse(pScanner, state); } @@ -92,16 +90,16 @@ namespace YAML void Map::ParseFlow(Scanner *pScanner, const ParserState& state) { // eat start token - pScanner->PopToken(); + pScanner->pop(); while(1) { - if(pScanner->IsEmpty()) + if(pScanner->empty()) throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW); - Token& token = pScanner->PeekToken(); + Token& token = pScanner->peek(); // first check for end if(token.type == TT_FLOW_MAP_END) { - pScanner->PopToken(); + pScanner->pop(); break; } @@ -109,7 +107,7 @@ namespace YAML if(token.type != TT_KEY) throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP_FLOW); - pScanner->PopToken(); + pScanner->pop(); Node *pKey = new Node; Node *pValue = new Node; @@ -119,15 +117,15 @@ namespace YAML pKey->Parse(pScanner, state); // now grab value (optional) - if(!pScanner->IsEmpty() && pScanner->PeekToken().type == TT_VALUE) { - pScanner->PopToken(); + if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) { + pScanner->pop(); 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) - Token& nextToken = pScanner->PeekToken(); + Token& nextToken = pScanner->peek(); if(nextToken.type == TT_FLOW_ENTRY) - pScanner->PopToken(); + pScanner->pop(); else if(nextToken.type != TT_FLOW_MAP_END) throw ParserException(nextToken.line, nextToken.column, ErrorMsg::END_OF_MAP_FLOW); diff --git a/src/node.cpp b/src/node.cpp index c66d001..f67ab55 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -44,7 +44,7 @@ namespace YAML return; // now split based on what kind of node we should be - switch(pScanner->PeekToken().type) { + switch(pScanner->peek().type) { case TT_SCALAR: m_pContent = new Scalar; m_pContent->Parse(pScanner, state); @@ -68,10 +68,10 @@ namespace YAML void Node::ParseHeader(Scanner *pScanner, const ParserState& state) { while(1) { - if(pScanner->IsEmpty()) + if(pScanner->empty()) return; - switch(pScanner->PeekToken().type) { + switch(pScanner->peek().type) { case TT_TAG: ParseTag(pScanner, state); break; case TT_ANCHOR: ParseAnchor(pScanner, state); break; case TT_ALIAS: ParseAlias(pScanner, state); break; @@ -82,7 +82,7 @@ namespace YAML void Node::ParseTag(Scanner *pScanner, const ParserState& state) { - Token& token = pScanner->PeekToken(); + Token& token = pScanner->peek(); if(m_tag != "") throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_TAGS); @@ -90,23 +90,23 @@ namespace YAML for(unsigned i=0;iPopToken(); + pScanner->pop(); } void Node::ParseAnchor(Scanner *pScanner, const ParserState& state) { - Token& token = pScanner->PeekToken(); + Token& token = pScanner->peek(); if(m_anchor != "") throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ANCHORS); m_anchor = token.value; m_alias = false; - pScanner->PopToken(); + pScanner->pop(); } void Node::ParseAlias(Scanner *pScanner, const ParserState& state) { - Token& token = pScanner->PeekToken(); + Token& token = pScanner->peek(); if(m_anchor != "") throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ALIASES); if(m_tag != "") @@ -114,7 +114,7 @@ namespace YAML m_anchor = token.value; m_alias = true; - pScanner->PopToken(); + pScanner->pop(); } void Node::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) const diff --git a/src/parser.cpp b/src/parser.cpp index 9c40430..7d4169d 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -19,7 +19,7 @@ namespace YAML Parser::operator bool() const { - return !m_pScanner->IsEmpty(); + return !m_pScanner->empty(); } void Parser::Load(std::istream& in) @@ -41,19 +41,19 @@ namespace YAML ParseDirectives(); // we better have some tokens in the queue - if(m_pScanner->IsEmpty()) + if(m_pScanner->empty()) return; // first eat doc start (optional) - if(m_pScanner->PeekToken().type == TT_DOC_START) - m_pScanner->PopToken(); + if(m_pScanner->peek().type == TT_DOC_START) + m_pScanner->pop(); // now parse our root node document.Parse(m_pScanner, m_state); // and finally eat any doc ends we see - while(!m_pScanner->IsEmpty() && m_pScanner->PeekToken().type == TT_DOC_END) - m_pScanner->PopToken(); + while(!m_pScanner->empty() && m_pScanner->peek().type == TT_DOC_END) + m_pScanner->pop(); } // ParseDirectives @@ -63,10 +63,10 @@ namespace YAML bool readDirective = false; while(1) { - if(m_pScanner->IsEmpty()) + if(m_pScanner->empty()) break; - Token& token = m_pScanner->PeekToken(); + Token& token = m_pScanner->peek(); if(token.type != TT_DIRECTIVE) break; @@ -77,7 +77,7 @@ namespace YAML readDirective = true; HandleDirective(&token); - m_pScanner->PopToken(); + m_pScanner->pop(); } } @@ -123,11 +123,11 @@ namespace YAML void Parser::PrintTokens(std::ostream& out) { while(1) { - if(m_pScanner->IsEmpty()) + if(m_pScanner->empty()) break; - out << m_pScanner->PeekToken() << std::endl; - m_pScanner->PopToken(); + out << m_pScanner->peek() << std::endl; + m_pScanner->pop(); } } } diff --git a/src/scalar.cpp b/src/scalar.cpp index 0038cc1..e560fb8 100644 --- a/src/scalar.cpp +++ b/src/scalar.cpp @@ -17,9 +17,9 @@ namespace YAML void Scalar::Parse(Scanner *pScanner, const ParserState& state) { - Token& token = pScanner->PeekToken(); + Token& token = pScanner->peek(); m_data = token.value; - pScanner->PopToken(); + pScanner->pop(); } void Scalar::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) diff --git a/src/scanner.cpp b/src/scanner.cpp index bf2a23e..b800840 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -3,6 +3,7 @@ #include "token.h" #include "exceptions.h" #include "exp.h" +#include namespace YAML { @@ -15,34 +16,46 @@ namespace YAML { } - // IsEmpty + // empty // . Returns true if there are no more tokens to be read - bool Scanner::IsEmpty() + bool Scanner::empty() { - PeekToken(); // to ensure that there are tokens in the queue, if possible + EnsureTokensInQueue(); return m_tokens.empty(); } - // PopToken + // pop // . Simply removes the next token on the queue. - void Scanner::PopToken() + void Scanner::pop() { - PeekToken(); // to ensure that there are tokens in the queue + EnsureTokensInQueue(); if(!m_tokens.empty()) m_tokens.pop(); } - // PeekToken - // . Returns (but does not remove) the next token on the queue, and scans if only we need to. - Token& Scanner::PeekToken() + // peek + // . Returns (but does not remove) the next token on the queue. + Token& Scanner::peek() + { + EnsureTokensInQueue(); + assert(!m_tokens.empty()); // should we be asserting here? I mean, we really just be checking + // if it's empty before peeking. + + return m_tokens.front(); + } + + // EnsureTokensInQueue + // . Scan until there's a valid token at the front of the queue, + // or we're sure the queue is empty. + void Scanner::EnsureTokensInQueue() { while(1) { if(!m_tokens.empty()) { Token& token = m_tokens.front(); - // return this guy if it's valid + // if this guy's valid, then we're done if(token.status == TS_VALID) - return token; + return; // here's where we clean up the impossible tokens if(token.status == TS_INVALID) { @@ -55,13 +68,11 @@ namespace YAML // no token? maybe we've actually finished if(m_endedStream) - break; + return; // no? then scan... ScanNextToken(); } - - // TODO: find something to return here, or assert (but can't do that! maybe split into two functions?) } // ScanNextToken diff --git a/src/scanner.h b/src/scanner.h index 06fd509..805b82d 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -16,16 +16,18 @@ namespace YAML Scanner(std::istream& in); ~Scanner(); - bool IsEmpty(); - void PopToken(); - Token& PeekToken(); + // token queue management (hopefully this looks kinda stl-ish) + bool empty(); + void pop(); + Token& peek(); private: // scanning - void StartStream(); - void EndStream(); + void EnsureTokensInQueue(); void ScanNextToken(); void ScanToNextToken(); + void StartStream(); + void EndStream(); Token *PushIndentTo(int column, bool sequence); void PopIndentTo(int column); diff --git a/src/sequence.cpp b/src/sequence.cpp index fed6a97..2f4ff95 100644 --- a/src/sequence.cpp +++ b/src/sequence.cpp @@ -52,9 +52,7 @@ namespace YAML Clear(); // split based on start token - Token& token = pScanner->PeekToken(); - - switch(token.type) { + switch(pScanner->peek().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; @@ -64,17 +62,17 @@ namespace YAML void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state) { // eat start token - pScanner->PopToken(); + pScanner->pop(); while(1) { - if(pScanner->IsEmpty()) + if(pScanner->empty()) throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ); - Token token = pScanner->PeekToken(); + Token token = pScanner->peek(); if(token.type != TT_BLOCK_ENTRY && token.type != TT_BLOCK_END) throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ); - pScanner->PopToken(); + pScanner->pop(); if(token.type == TT_BLOCK_END) break; @@ -88,15 +86,15 @@ namespace YAML { while(1) { // we're actually *allowed* to have no tokens at some point - if(pScanner->IsEmpty()) + if(pScanner->empty()) break; // and we end at anything other than a block entry - Token& token = pScanner->PeekToken(); + Token& token = pScanner->peek(); if(token.type != TT_BLOCK_ENTRY) break; - pScanner->PopToken(); + pScanner->pop(); Node *pNode = new Node; m_data.push_back(pNode); @@ -107,15 +105,15 @@ namespace YAML void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state) { // eat start token - pScanner->PopToken(); + pScanner->pop(); while(1) { - if(pScanner->IsEmpty()) + if(pScanner->empty()) throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ_FLOW); // first check for end - if(pScanner->PeekToken().type == TT_FLOW_SEQ_END) { - pScanner->PopToken(); + if(pScanner->peek().type == TT_FLOW_SEQ_END) { + pScanner->pop(); break; } @@ -125,9 +123,9 @@ 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) - Token& token = pScanner->PeekToken(); + Token& token = pScanner->peek(); if(token.type == TT_FLOW_ENTRY) - pScanner->PopToken(); + pScanner->pop(); else if(token.type != TT_FLOW_SEQ_END) throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ_FLOW); } diff --git a/yamlcpp.vcproj b/yamlcpp.vcproj index 7d82294..9e4fac3 100644 --- a/yamlcpp.vcproj +++ b/yamlcpp.vcproj @@ -175,10 +175,6 @@ RelativePath=".\src\iterator.cpp" > - -