diff --git a/map.cpp b/map.cpp index ef93d35f46..d3cba8f1da 100644 --- a/map.cpp +++ b/map.cpp @@ -10,28 +10,37 @@ namespace YAML } Map::~Map() + { + Clear(); + } + + void Map::Clear() { for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) { delete it->first; delete it->second; } + m_data.clear(); } void Map::Parse(Scanner *pScanner) { - // grab start token - Token *pToken = pScanner->GetNextToken(); + Clear(); + + // split based on start token + Token *pToken = pScanner->PeekNextToken(); switch(pToken->type) { case TT_BLOCK_MAP_START: ParseBlock(pScanner); break; case TT_FLOW_MAP_START: ParseFlow(pScanner); break; } - - delete pToken; } void Map::ParseBlock(Scanner *pScanner) { + // eat start token + pScanner->EatNextToken(); + while(1) { Token *pToken = pScanner->PeekNextToken(); if(!pToken) @@ -61,6 +70,9 @@ namespace YAML void Map::ParseFlow(Scanner *pScanner) { + // eat start token + pScanner->EatNextToken(); + while(1) { Token *pToken = pScanner->PeekNextToken(); if(!pToken) diff --git a/map.h b/map.h index 391d3f23d0..0da12b3648 100644 --- a/map.h +++ b/map.h @@ -13,6 +13,7 @@ namespace YAML Map(); virtual ~Map(); + void Clear(); virtual void Parse(Scanner *pScanner); virtual void Write(std::ostream& out, int indent); diff --git a/node.cpp b/node.cpp index 844f045a0f..439bdd6f27 100644 --- a/node.cpp +++ b/node.cpp @@ -9,7 +9,7 @@ namespace YAML { - Node::Node(): m_pContent(0) + Node::Node(): m_pContent(0), m_alias(false) { } @@ -22,12 +22,19 @@ namespace YAML { delete m_pContent; m_pContent = 0; + m_alias = false; } void Node::Parse(Scanner *pScanner) { + Clear(); + ParseHeader(pScanner); + // is this an alias? if so, it can have no content + if(m_alias) + return; + // now split based on what kind of node we should be Token *pToken = pScanner->PeekNextToken(); if(pToken->type == TT_DOC_END) @@ -57,29 +64,75 @@ namespace YAML { while(1) { Token *pToken = pScanner->PeekNextToken(); - if(!pToken || pToken->type != TT_TAG || pToken->type != TT_ANCHOR || pToken->type != TT_ALIAS) + if(!pToken || (pToken->type != TT_TAG && pToken->type != TT_ANCHOR && pToken->type != TT_ALIAS)) break; - pScanner->PopNextToken(); switch(pToken->type) { - case TT_TAG: - break; - case TT_ANCHOR: - break; - case TT_ALIAS: - break; + case TT_TAG: ParseTag(pScanner); break; + case TT_ANCHOR: ParseAnchor(pScanner); break; + case TT_ALIAS: ParseAlias(pScanner); break; } - delete pToken; } } + void Node::ParseTag(Scanner *pScanner) + { + if(m_tag != "") + return; // TODO: throw + + Token *pToken = pScanner->PeekNextToken(); + m_tag = pToken->value; + for(unsigned i=0;iparams.size();i++) + m_tag += pToken->params[i]; + pScanner->PopNextToken(); + } + + void Node::ParseAnchor(Scanner *pScanner) + { + if(m_anchor != "") + return; // TODO: throw + + Token *pToken = pScanner->PeekNextToken(); + m_anchor = pToken->value; + m_alias = false; + pScanner->PopNextToken(); + } + + void Node::ParseAlias(Scanner *pScanner) + { + if(m_anchor != "") + return; // TODO: throw + if(m_tag != "") + return; // TODO: throw (aliases can't have any content, *including* tags) + + Token *pToken = pScanner->PeekNextToken(); + m_anchor = pToken->value; + m_alias = true; + pScanner->PopNextToken(); + } + void Node::Write(std::ostream& out, int indent) { + if(m_tag != "") { + for(int i=0;iWrite(out, indent); + } } } diff --git a/node.h b/node.h index ab15fbf495..d6e872719e 100644 --- a/node.h +++ b/node.h @@ -24,9 +24,13 @@ namespace YAML private: void ParseHeader(Scanner *pScanner); + void ParseTag(Scanner *pScanner); + void ParseAnchor(Scanner *pScanner); + void ParseAlias(Scanner *pScanner); private: - std::string m_tag; + bool m_alias; + std::string m_anchor, m_tag; Content *m_pContent; }; } diff --git a/parser.cpp b/parser.cpp index 4b4411da6d..8db28eae15 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1,5 +1,7 @@ #include "parser.h" #include "scanner.h" +#include "token.h" +#include namespace YAML { @@ -17,4 +19,15 @@ namespace YAML { document.Parse(m_pScanner); } + + void Parser::PrintTokens() + { + while(1) { + Token *pToken = m_pScanner->GetNextToken(); + if(!pToken) + break; + + std::cout << *pToken << std::endl; + } + } } diff --git a/parser.h b/parser.h index 4f198522bc..95bb663fd5 100644 --- a/parser.h +++ b/parser.h @@ -15,6 +15,7 @@ namespace YAML ~Parser(); void GetNextDocument(Document& document); + void PrintTokens(); private: Scanner *m_pScanner; diff --git a/scanner.cpp b/scanner.cpp index d44ec7caa1..a231b9d830 100644 --- a/scanner.cpp +++ b/scanner.cpp @@ -254,12 +254,14 @@ namespace YAML // now push m_indents.push(column); + Token *pToken = 0; if(sequence) - m_tokens.push(new Token(TT_BLOCK_SEQ_START)); + pToken = new Token(TT_BLOCK_SEQ_START); else - m_tokens.push(new Token(TT_BLOCK_MAP_START)); + pToken = new Token(TT_BLOCK_MAP_START); - return m_tokens.front(); + m_tokens.push(pToken); + return pToken; } // PopIndentTo diff --git a/sequence.cpp b/sequence.cpp index df4a178785..8332e130a0 100644 --- a/sequence.cpp +++ b/sequence.cpp @@ -11,27 +11,36 @@ namespace YAML } Sequence::~Sequence() + { + Clear(); + } + + void Sequence::Clear() { for(unsigned i=0;iGetNextToken(); + Clear(); + + // split based on start token + Token *pToken = pScanner->PeekNextToken(); switch(pToken->type) { case TT_BLOCK_SEQ_START: ParseBlock(pScanner); break; case TT_BLOCK_ENTRY: ParseImplicit(pScanner); break; case TT_FLOW_SEQ_START: ParseFlow(pScanner); break; } - - delete pToken; } void Sequence::ParseBlock(Scanner *pScanner) { + // eat start token + pScanner->EatNextToken(); + while(1) { Token *pToken = pScanner->PeekNextToken(); if(!pToken) @@ -52,11 +61,29 @@ namespace YAML void Sequence::ParseImplicit(Scanner *pScanner) { - // TODO + while(1) { + Token *pToken = pScanner->PeekNextToken(); + // we're actually *allowed* to have no tokens at some point + if(!pToken) + break; + + // and we end at anything other than a block entry + if(pToken->type != TT_BLOCK_ENTRY) + break; + + pScanner->PopNextToken(); + + Node *pNode = new Node; + m_data.push_back(pNode); + pNode->Parse(pScanner); + } } void Sequence::ParseFlow(Scanner *pScanner) { + // eat start token + pScanner->EatNextToken(); + while(1) { Token *pToken = pScanner->PeekNextToken(); if(!pToken) diff --git a/sequence.h b/sequence.h index 928f53c952..42e9fbb932 100644 --- a/sequence.h +++ b/sequence.h @@ -13,6 +13,7 @@ namespace YAML Sequence(); virtual ~Sequence(); + void Clear(); virtual void Parse(Scanner *pScanner); virtual void Write(std::ostream& out, int indent); diff --git a/test.yaml b/test.yaml index 1840d58a8b..4b98eeaec1 100644 --- a/test.yaml +++ b/test.yaml @@ -1,10 +1,29 @@ ---- -here's a sequence: - - item 1 - - item 2 -now an inline sequence: [1, 2, 3] -and here's a map: - name: Jesse - age: 23 -and here's an inline map: {state: Illinois, city: Urbana-Champaign} -... \ No newline at end of file +--- ! +invoice: 34843 +date : 2001-01-23 +bill-to: &id001 + given : Chris + family : Dumars + address: + lines: | + 458 Walkman Dr. + Suite #292 + city : Royal Oak + state : MI + postal : 48046 +ship-to: *id001 +product: + - sku : BL394D + quantity : 4 + description : Basketball + price : 450.00 + - sku : BL4438H + quantity : 1 + description : Super Hoop + price : 2392.00 +tax : 251.42 +total: 4443.52 +comments: + Late afternoon is best. + Backup contact is Nancy + Billsmer @ 338-4338. \ No newline at end of file