mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03:00
Small changes in the iterator code.
Changed the public interface of Scanner to resemble an STL container.
This commit is contained in:
parent
cc87c83b01
commit
d45bb667b6
14 changed files with 108 additions and 112 deletions
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
// for memory leaks
|
||||
// for detecting memory leaks
|
||||
#ifdef _DEBUG
|
||||
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#include "crt.h"
|
||||
#include "iterpriv.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
IterPriv::IterPriv(): type(IT_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
IterPriv::IterPriv(std::vector <Node *>::const_iterator it): seqIter(it), type(IT_SEQ)
|
||||
{
|
||||
}
|
||||
|
||||
IterPriv::IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it): mapIter(it), type(IT_MAP)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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 <Node *>::const_iterator it);
|
||||
IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it);
|
||||
IterPriv(): type(IT_NONE) {}
|
||||
IterPriv(std::vector <Node *>::const_iterator it): seqIter(it), type(IT_SEQ) {}
|
||||
IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it): mapIter(it), type(IT_MAP) {}
|
||||
|
||||
enum ITER_TYPE { IT_NONE, IT_SEQ, IT_MAP };
|
||||
ITER_TYPE type;
|
||||
|
|
34
src/map.cpp
34
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);
|
||||
|
||||
|
|
18
src/node.cpp
18
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;i<token.params.size();i++)
|
||||
m_tag += token.params[i];
|
||||
pScanner->PopToken();
|
||||
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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "token.h"
|
||||
#include "exceptions.h"
|
||||
#include "exp.h"
|
||||
#include <cassert>
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -175,10 +175,6 @@
|
|||
RelativePath=".\src\iterator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\iterpriv.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\map.cpp"
|
||||
>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue