Added parsing of anchors, aliases, and tags (still no semantics yet).

Fixed a silly bug in the simple key pushing (queues are FIFO!).
This commit is contained in:
Jesse Beder 2008-07-01 01:17:10 +00:00
parent 121c2e577f
commit 8180a85a3b
10 changed files with 167 additions and 34 deletions

20
map.cpp
View file

@ -10,28 +10,37 @@ namespace YAML
} }
Map::~Map() Map::~Map()
{
Clear();
}
void Map::Clear()
{ {
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) { for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
delete it->first; delete it->first;
delete it->second; delete it->second;
} }
m_data.clear();
} }
void Map::Parse(Scanner *pScanner) void Map::Parse(Scanner *pScanner)
{ {
// grab start token Clear();
Token *pToken = pScanner->GetNextToken();
// split based on start token
Token *pToken = pScanner->PeekNextToken();
switch(pToken->type) { switch(pToken->type) {
case TT_BLOCK_MAP_START: ParseBlock(pScanner); break; case TT_BLOCK_MAP_START: ParseBlock(pScanner); break;
case TT_FLOW_MAP_START: ParseFlow(pScanner); break; case TT_FLOW_MAP_START: ParseFlow(pScanner); break;
} }
delete pToken;
} }
void Map::ParseBlock(Scanner *pScanner) void Map::ParseBlock(Scanner *pScanner)
{ {
// eat start token
pScanner->EatNextToken();
while(1) { while(1) {
Token *pToken = pScanner->PeekNextToken(); Token *pToken = pScanner->PeekNextToken();
if(!pToken) if(!pToken)
@ -61,6 +70,9 @@ namespace YAML
void Map::ParseFlow(Scanner *pScanner) void Map::ParseFlow(Scanner *pScanner)
{ {
// eat start token
pScanner->EatNextToken();
while(1) { while(1) {
Token *pToken = pScanner->PeekNextToken(); Token *pToken = pScanner->PeekNextToken();
if(!pToken) if(!pToken)

1
map.h
View file

@ -13,6 +13,7 @@ namespace YAML
Map(); Map();
virtual ~Map(); virtual ~Map();
void Clear();
virtual void Parse(Scanner *pScanner); virtual void Parse(Scanner *pScanner);
virtual void Write(std::ostream& out, int indent); virtual void Write(std::ostream& out, int indent);

View file

@ -9,7 +9,7 @@
namespace YAML namespace YAML
{ {
Node::Node(): m_pContent(0) Node::Node(): m_pContent(0), m_alias(false)
{ {
} }
@ -22,12 +22,19 @@ namespace YAML
{ {
delete m_pContent; delete m_pContent;
m_pContent = 0; m_pContent = 0;
m_alias = false;
} }
void Node::Parse(Scanner *pScanner) void Node::Parse(Scanner *pScanner)
{ {
Clear();
ParseHeader(pScanner); 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 // now split based on what kind of node we should be
Token *pToken = pScanner->PeekNextToken(); Token *pToken = pScanner->PeekNextToken();
if(pToken->type == TT_DOC_END) if(pToken->type == TT_DOC_END)
@ -57,29 +64,75 @@ namespace YAML
{ {
while(1) { while(1) {
Token *pToken = pScanner->PeekNextToken(); 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; break;
pScanner->PopNextToken();
switch(pToken->type) { switch(pToken->type) {
case TT_TAG: case TT_TAG: ParseTag(pScanner); break;
break; case TT_ANCHOR: ParseAnchor(pScanner); break;
case TT_ANCHOR: case TT_ALIAS: ParseAlias(pScanner); break;
break;
case TT_ALIAS:
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;i<pToken->params.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) void Node::Write(std::ostream& out, int indent)
{ {
if(m_tag != "") {
for(int i=0;i<indent;i++)
out << " ";
out << "{tag: " << m_tag << "}\n";
}
if(m_anchor != "") {
for(int i=0;i<indent;i++)
out << " ";
if(m_alias)
out << "{alias: " << m_anchor << "}\n";
else
out << "{anchor: " << m_anchor << "}\n";
}
if(!m_pContent) { if(!m_pContent) {
for(int i=0;i<indent;i++) for(int i=0;i<indent;i++)
out << " "; out << " ";
out << "{no content}\n"; out << "{no content}\n";
} else } else {
m_pContent->Write(out, indent); m_pContent->Write(out, indent);
} }
}
} }

6
node.h
View file

@ -24,9 +24,13 @@ namespace YAML
private: private:
void ParseHeader(Scanner *pScanner); void ParseHeader(Scanner *pScanner);
void ParseTag(Scanner *pScanner);
void ParseAnchor(Scanner *pScanner);
void ParseAlias(Scanner *pScanner);
private: private:
std::string m_tag; bool m_alias;
std::string m_anchor, m_tag;
Content *m_pContent; Content *m_pContent;
}; };
} }

View file

@ -1,5 +1,7 @@
#include "parser.h" #include "parser.h"
#include "scanner.h" #include "scanner.h"
#include "token.h"
#include <iostream>
namespace YAML namespace YAML
{ {
@ -17,4 +19,15 @@ namespace YAML
{ {
document.Parse(m_pScanner); document.Parse(m_pScanner);
} }
void Parser::PrintTokens()
{
while(1) {
Token *pToken = m_pScanner->GetNextToken();
if(!pToken)
break;
std::cout << *pToken << std::endl;
}
}
} }

View file

@ -15,6 +15,7 @@ namespace YAML
~Parser(); ~Parser();
void GetNextDocument(Document& document); void GetNextDocument(Document& document);
void PrintTokens();
private: private:
Scanner *m_pScanner; Scanner *m_pScanner;

View file

@ -254,12 +254,14 @@ namespace YAML
// now push // now push
m_indents.push(column); m_indents.push(column);
Token *pToken = 0;
if(sequence) if(sequence)
m_tokens.push(new Token(TT_BLOCK_SEQ_START)); pToken = new Token(TT_BLOCK_SEQ_START);
else 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 // PopIndentTo

View file

@ -11,27 +11,36 @@ namespace YAML
} }
Sequence::~Sequence() Sequence::~Sequence()
{
Clear();
}
void Sequence::Clear()
{ {
for(unsigned i=0;i<m_data.size();i++) for(unsigned i=0;i<m_data.size();i++)
delete m_data[i]; delete m_data[i];
m_data.clear();
} }
void Sequence::Parse(Scanner *pScanner) void Sequence::Parse(Scanner *pScanner)
{ {
// grab start token Clear();
Token *pToken = pScanner->GetNextToken();
// split based on start token
Token *pToken = pScanner->PeekNextToken();
switch(pToken->type) { switch(pToken->type) {
case TT_BLOCK_SEQ_START: ParseBlock(pScanner); break; case TT_BLOCK_SEQ_START: ParseBlock(pScanner); break;
case TT_BLOCK_ENTRY: ParseImplicit(pScanner); break; case TT_BLOCK_ENTRY: ParseImplicit(pScanner); break;
case TT_FLOW_SEQ_START: ParseFlow(pScanner); break; case TT_FLOW_SEQ_START: ParseFlow(pScanner); break;
} }
delete pToken;
} }
void Sequence::ParseBlock(Scanner *pScanner) void Sequence::ParseBlock(Scanner *pScanner)
{ {
// eat start token
pScanner->EatNextToken();
while(1) { while(1) {
Token *pToken = pScanner->PeekNextToken(); Token *pToken = pScanner->PeekNextToken();
if(!pToken) if(!pToken)
@ -52,11 +61,29 @@ namespace YAML
void Sequence::ParseImplicit(Scanner *pScanner) 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) void Sequence::ParseFlow(Scanner *pScanner)
{ {
// eat start token
pScanner->EatNextToken();
while(1) { while(1) {
Token *pToken = pScanner->PeekNextToken(); Token *pToken = pScanner->PeekNextToken();
if(!pToken) if(!pToken)

View file

@ -13,6 +13,7 @@ namespace YAML
Sequence(); Sequence();
virtual ~Sequence(); virtual ~Sequence();
void Clear();
virtual void Parse(Scanner *pScanner); virtual void Parse(Scanner *pScanner);
virtual void Write(std::ostream& out, int indent); virtual void Write(std::ostream& out, int indent);

View file

@ -1,10 +1,29 @@
--- --- !<tag:clarkevans.com,2002:invoice>
here's a sequence: invoice: 34843
- item 1 date : 2001-01-23
- item 2 bill-to: &id001
now an inline sequence: [1, 2, 3] given : Chris
and here's a map: family : Dumars
name: Jesse address:
age: 23 lines: |
and here's an inline map: {state: Illinois, city: Urbana-Champaign} 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.