simplekey.cpp 3.14 KB
Newer Older
1
2
3
4
5
6
7
8
#include "crt.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "exp.h"

namespace YAML
{
9
	Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_)
10
		: mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0)
11
12
13
14
15
	{
	}

	void Scanner::SimpleKey::Validate()
	{
16
17
18
		// Note: pIndent will *not* be garbage here; see below
		if(pIndent)
			pIndent->isValid = true;
19
		if(pMapStart)
20
			pMapStart->status = Token::VALID;
21
		if(pKey)
22
			pKey->status = Token::VALID;
23
24
25
26
	}

	void Scanner::SimpleKey::Invalidate()
	{
27
28
		// Note: pIndent might be a garbage pointer here, but that's ok
		//       An indent will only be popped if the simple key is invalid
29
		if(pMapStart)
30
			pMapStart->status = Token::INVALID;
31
		if(pKey)
32
			pKey->status = Token::INVALID;
33
34
	}

35
36
37
38
	// ExistsActiveSimpleKey
	// . Returns true if there's a potential simple key at our flow level
	//   (there's allowed at most one per flow level, i.e., at the start of the flow start token)
	bool Scanner::ExistsActiveSimpleKey() const
39
	{
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
		if(m_simpleKeys.empty())
			return false;
		
		const SimpleKey& key = m_simpleKeys.top();
		return key.flowLevel == m_flowLevel;
	}

	// InsertPotentialSimpleKey
	// . If we can, add a potential simple key to the queue,
	//   and save it on a stack.
	void Scanner::InsertPotentialSimpleKey()
	{
		if(ExistsActiveSimpleKey())
			return;
		
55
		SimpleKey key(INPUT.mark(), m_flowLevel);
56
57

		// first add a map start, if necessary
58
59
60
61
		key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
		if(key.pIndent) {
			key.pIndent->isValid = false;
			key.pMapStart = key.pIndent->pStartToken;
62
			key.pMapStart->status = Token::UNVERIFIED;
63
		}
64
65

		// then add the (now unverified) key
66
		m_tokens.push(Token(Token::KEY, INPUT.mark()));
67
		key.pKey = &m_tokens.back();
68
		key.pKey->status = Token::UNVERIFIED;
69
70
71
72

		m_simpleKeys.push(key);
	}

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	// InvalidateSimpleKey
	// . Automatically invalidate the simple key in our flow level
	void Scanner::InvalidateSimpleKey()
	{
		if(m_simpleKeys.empty())
			return;
		
		// grab top key
		SimpleKey& key = m_simpleKeys.top();
		if(key.flowLevel != m_flowLevel)
			return;
		
		key.Invalidate();
		m_simpleKeys.pop();
	}

89
90
91
	// VerifySimpleKey
	// . Determines whether the latest simple key to be added is valid,
	//   and if so, makes it valid.
92
	bool Scanner::VerifySimpleKey()
93
94
95
96
97
98
99
100
101
	{
		m_isLastKeyValid = false;
		if(m_simpleKeys.empty())
			return m_isLastKeyValid;

		// grab top key
		SimpleKey key = m_simpleKeys.top();

		// only validate if we're in the correct flow level
102
		if(key.flowLevel != m_flowLevel)
103
104
105
106
107
108
109
110
111
112
113
114
115
			return false;

		m_simpleKeys.pop();

		bool isValid = true;

		// needs to be followed immediately by a value
		if(m_flowLevel > 0 && !Exp::ValueInFlow.Matches(INPUT))
			isValid = false;
		if(m_flowLevel == 0 && !Exp::Value.Matches(INPUT))
			isValid = false;

		// also needs to be less than 1024 characters and inline
116
		if(INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
117
118
119
120
121
122
123
124
125
126
127
128
			isValid = false;

		// invalidate key
		if(isValid)
			key.Validate();
		else
			key.Invalidate();

		m_isLastKeyValid = isValid;
		return isValid;
	}

129
	void Scanner::PopAllSimpleKeys()
130
131
	{
		while(!m_simpleKeys.empty())
132
			m_simpleKeys.pop();
133
134
	}
}