node.cpp 2.89 KB
Newer Older
Jesse Beder's avatar
Jesse Beder committed
1
#include "node.h"
2
3
#include "token.h"
#include "scanner.h"
4
#include "content.h"
5
6
7
#include "parser.h"
#include "scalar.h"
#include "sequence.h"
8
#include "map.h"
Jesse Beder's avatar
Jesse Beder committed
9
10
11

namespace YAML
{
12
	Node::Node(): m_pContent(0), m_alias(false)
Jesse Beder's avatar
Jesse Beder committed
13
14
15
16
	{
	}

	Node::~Node()
17
18
19
20
21
22
23
24
	{
		Clear();
	}

	void Node::Clear()
	{
		delete m_pContent;
		m_pContent = 0;
25
		m_alias = false;
26
	}
27
28
29

	void Node::Parse(Scanner *pScanner)
	{
30
31
		Clear();

32
33
		ParseHeader(pScanner);

34
35
36
37
		// is this an alias? if so, it can have no content
		if(m_alias)
			return;

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
		// now split based on what kind of node we should be
		Token *pToken = pScanner->PeekNextToken();
		if(pToken->type == TT_DOC_END)
			return;

		switch(pToken->type) {
			case TT_SCALAR:
				m_pContent = new Scalar;
				m_pContent->Parse(pScanner);
				break;
			case TT_FLOW_SEQ_START:
			case TT_BLOCK_SEQ_START:
			case TT_BLOCK_ENTRY:
				m_pContent = new Sequence;
				m_pContent->Parse(pScanner);
				break;
			case TT_FLOW_MAP_START:
			case TT_BLOCK_MAP_START:
				m_pContent = new Map;
				m_pContent->Parse(pScanner);
		}
	}

	// ParseHeader
	// . Grabs any tag, alias, or anchor tokens and deals with them.
	void Node::ParseHeader(Scanner *pScanner)
	{
		while(1) {
			Token *pToken = pScanner->PeekNextToken();
67
			if(!pToken || (pToken->type != TT_TAG && pToken->type != TT_ANCHOR && pToken->type != TT_ALIAS))
68
69
70
				break;

			switch(pToken->type) {
71
72
73
				case TT_TAG: ParseTag(pScanner); break;
				case TT_ANCHOR: ParseAnchor(pScanner); break;
				case TT_ALIAS: ParseAlias(pScanner); break;
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
	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();
	}

114
115
	void Node::Write(std::ostream& out, int indent)
	{
116
117
118
119
120
121
122
123
124
125
126
127
128
129
		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";
		}

130
131
132
133
		if(!m_pContent) {
			for(int i=0;i<indent;i++)
				out << "  ";
			out << "{no content}\n";
134
		} else {
135
			m_pContent->Write(out, indent);
136
		}
137
	}
Jesse Beder's avatar
Jesse Beder committed
138
}