map.cpp 2.6 KB
Newer Older
1
2
#include "map.h"
#include "node.h"
3
4
#include "scanner.h"
#include "token.h"
5
6
7
8
9
10
11
12
13
14
15
16
17
18

namespace YAML
{
	Map::Map()
	{
	}

	Map::~Map()
	{
		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
			delete it->first;
			delete it->second;
		}
	}
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

	void Map::Parse(Scanner *pScanner)
	{
		// grab start token
		Token *pToken = pScanner->GetNextToken();

		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)
	{
		while(1) {
			Token *pToken = pScanner->PeekNextToken();
			if(!pToken)
				break;  // TODO: throw?

			if(pToken->type != TT_KEY && pToken->type != TT_BLOCK_END)
				break;  // TODO: throw?

			pScanner->PopNextToken();
			if(pToken->type == TT_BLOCK_END)
				break;

			Node *pKey = new Node;
			Node *pValue = new Node;
			m_data[pKey] = pValue;

			// grab key
			pKey->Parse(pScanner);

			// now grab value (optional)
			if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) {
				pScanner->PopNextToken();
				pValue->Parse(pScanner);
			}
		}
	}

	void Map::ParseFlow(Scanner *pScanner)
	{
		while(1) {
			Token *pToken = pScanner->PeekNextToken();
			if(!pToken)
				break;  // TODO: throw?

			// first check for end
			if(pToken->type == TT_FLOW_MAP_END) {
				pScanner->EatNextToken();
				break;
			}

			// now it better be a key
			if(pToken->type != TT_KEY)
				break;  // TODO: throw?

			pScanner->PopNextToken();

			Node *pKey = new Node;
			Node *pValue = new Node;
			m_data[pKey] = pValue;

			// grab key
			pKey->Parse(pScanner);

			// now grab value (optional)
			if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) {
				pScanner->PopNextToken();
				pValue->Parse(pScanner);
			}

			// 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)
				break;  // TODO: throw?
		}
	}

	void Map::Write(std::ostream& out, int indent)
	{
		for(int i=0;i<indent;i++)
			out << "  ";
		out << "{map}\n";

		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
			for(int i=0;i<indent + 1;i++)
				out << "  ";
			out << "{key}\n";
			it->first->Write(out, indent + 2);

			for(int i=0;i<indent + 1;i++)
				out << "  ";
			out << "{value}\n";
			it->second->Write(out, indent + 2);
		}
	}
121
}