sequence.cpp 3.31 KB
Newer Older
1
2
3
4
5
#include "crt.h"
#include "sequence.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
6
#include "emitter.h"
7
8
9
10
11
12
13
14
15
16
17
18
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

namespace YAML
{
	Sequence::Sequence()
	{

	}

	Sequence::~Sequence()
	{
		Clear();
	}

	void Sequence::Clear()
	{
		for(unsigned i=0;i<m_data.size();i++)
			delete m_data[i];
		m_data.clear();
	}

	bool Sequence::GetBegin(std::vector <Node *>::const_iterator& it) const
	{
		it = m_data.begin();
		return true;
	}

	bool Sequence::GetEnd(std::vector <Node *>::const_iterator& it) const
	{
		it = m_data.end();
		return true;
	}

	Node *Sequence::GetNode(unsigned i) const
	{
		if(i < m_data.size())
			return m_data[i];
		return 0;
	}

	unsigned Sequence::GetSize() const
	{
		return m_data.size();
	}

	void Sequence::Parse(Scanner *pScanner, const ParserState& state)
	{
		Clear();

		// split based on start token
		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;
Jesse Beder's avatar
Jesse Beder committed
60
			default: break;
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
		}
	}

	void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
	{
		// eat start token
		pScanner->pop();

		while(1) {
			if(pScanner->empty())
				throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ);

			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->pop();
			if(token.type == TT_BLOCK_END)
				break;

			Node *pNode = new Node;
			m_data.push_back(pNode);
			pNode->Parse(pScanner, state);
		}
	}

	void Sequence::ParseImplicit(Scanner *pScanner, const ParserState& state)
	{
		while(1) {
			// we're actually *allowed* to have no tokens at some point
			if(pScanner->empty())
				break;

			// and we end at anything other than a block entry
			Token& token = pScanner->peek();
			if(token.type != TT_BLOCK_ENTRY)
				break;

			pScanner->pop();

			Node *pNode = new Node;
			m_data.push_back(pNode);
			pNode->Parse(pScanner, state);
		}
	}

	void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
	{
		// eat start token
		pScanner->pop();

		while(1) {
			if(pScanner->empty())
				throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ_FLOW);

			// first check for end
			if(pScanner->peek().type == TT_FLOW_SEQ_END) {
				pScanner->pop();
				break;
			}

			// then read the node
			Node *pNode = new Node;
			m_data.push_back(pNode);
			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->peek();
			if(token.type == TT_FLOW_ENTRY)
				pScanner->pop();
			else if(token.type != TT_FLOW_SEQ_END)
				throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ_FLOW);
		}
	}

136
	void Sequence::Write(Emitter& out) const
137
	{
138
139
140
141
		out << BeginSeq;
		for(unsigned i=0;i<m_data.size();i++)
			out << *m_data[i];
		out << EndSeq;
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
	}

	int Sequence::Compare(Content *pContent)
	{
		return -pContent->Compare(this);
	}

	int Sequence::Compare(Sequence *pSeq)
	{
		unsigned n = m_data.size(), m = pSeq->m_data.size();
		if(n < m)
			return -1;
		else if(n > m)
			return 1;

		for(unsigned i=0;i<n;i++) {
			int cmp = m_data[i]->Compare(*pSeq->m_data[i]);
			if(cmp != 0)
				return cmp;
		}

		return 0;
	}
}