sequence.cpp 3.33 KB
Newer Older
1
2
#include "sequence.h"
#include "node.h"
3
4
#include "scanner.h"
#include "token.h"
5
6
7

namespace YAML
{
Jesse Beder's avatar
Jesse Beder committed
8
	Sequence::Sequence()
9
	{
Jesse Beder's avatar
Jesse Beder committed
10

11
12
13
	}

	Sequence::~Sequence()
14
15
16
17
18
	{
		Clear();
	}

	void Sequence::Clear()
19
20
21
	{
		for(unsigned i=0;i<m_data.size();i++)
			delete m_data[i];
22
		m_data.clear();
23
	}
24

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

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

37
38
39
40
41
42
43
44
45
46
47
48
	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();
	}

49
	void Sequence::Parse(Scanner *pScanner, const ParserState& state)
50
	{
51
52
53
54
		Clear();

		// split based on start token
		Token *pToken = pScanner->PeekNextToken();
55
56

		switch(pToken->type) {
57
58
59
			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;
60
61
62
		}
	}

63
	void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
64
	{
65
66
67
		// eat start token
		pScanner->EatNextToken();

68
69
70
		while(1) {
			Token *pToken = pScanner->PeekNextToken();
			if(!pToken)
Jesse Beder's avatar
Jesse Beder committed
71
				throw SeqEndNotFound();
72
73

			if(pToken->type != TT_BLOCK_ENTRY && pToken->type != TT_BLOCK_END)
Jesse Beder's avatar
Jesse Beder committed
74
				throw SeqEndNotFound();
75
76
77
78
79
80
81

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

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

86
	void Sequence::ParseImplicit(Scanner *pScanner, const ParserState& state)
87
	{
88
89
90
91
92
93
94
95
96
97
98
99
100
101
		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);
102
			pNode->Parse(pScanner, state);
103
		}
104
105
	}

106
	void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
107
	{
108
109
110
		// eat start token
		pScanner->EatNextToken();

111
112
113
		while(1) {
			Token *pToken = pScanner->PeekNextToken();
			if(!pToken)
Jesse Beder's avatar
Jesse Beder committed
114
				throw SeqEndNotFound();
115
116
117
118
119
120
121
122
123
124

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

			// then read the node
			Node *pNode = new Node;
			m_data.push_back(pNode);
125
			pNode->Parse(pScanner, state);
126
127
128
129
130
131

			// now eat the separator (or could be a sequence 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_SEQ_END)
Jesse Beder's avatar
Jesse Beder committed
132
				throw SeqEndNotFound();
133
134
135
		}
	}

136
	void Sequence::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
137
	{
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
		if(startedLine && !onlyOneCharOnLine)
			out << std::endl;

		for(unsigned i=0;i<m_data.size();i++) {
			if((startedLine && !onlyOneCharOnLine) || i > 0) {
				for(int j=0;j<indent;j++)
					out  << "  ";
			}

			out << "- ";
			m_data[i]->Write(out, indent + 1, true, i > 0 || !startedLine || onlyOneCharOnLine);
		}

		if(m_data.empty())
			out << std::endl;
153
	}
154
}