simplekey.cpp 2.74 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
10
	Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_)
		: mark(mark_), flowLevel(flowLevel_), pMapStart(0), pKey(0)
11
12
13
14
15
16
	{
	}

	void Scanner::SimpleKey::Validate()
	{
		if(pMapStart)
jbeder's avatar
jbeder committed
17
			pMapStart->status = Token::VALID;
18
		if(pKey)
jbeder's avatar
jbeder committed
19
			pKey->status = Token::VALID;
20
21
22
23
24
	}

	void Scanner::SimpleKey::Invalidate()
	{
		if(pMapStart)
jbeder's avatar
jbeder committed
25
			pMapStart->status = Token::INVALID;
26
		if(pKey)
jbeder's avatar
jbeder committed
27
			pKey->status = Token::INVALID;
28
29
30
31
32
33
34
	}

	// InsertSimpleKey
	// . Adds a potential simple key to the queue,
	//   and saves it on a stack.
	void Scanner::InsertSimpleKey()
	{
35
		SimpleKey key(INPUT.mark(), m_flowLevel);
36
37

		// first add a map start, if necessary
38
		key.pMapStart = PushIndentTo(INPUT.column(), IndentMarker::MAP);
39
		if(key.pMapStart)
jbeder's avatar
jbeder committed
40
			key.pMapStart->status = Token::UNVERIFIED;
41
42

		// then add the (now unverified) key
jbeder's avatar
jbeder committed
43
		m_tokens.push(Token(Token::KEY, INPUT.mark()));
44
		key.pKey = &m_tokens.back();
jbeder's avatar
jbeder committed
45
		key.pKey->status = Token::UNVERIFIED;
46
47
48
49
50
51
52

		m_simpleKeys.push(key);
	}

	// VerifySimpleKey
	// . Determines whether the latest simple key to be added is valid,
	//   and if so, makes it valid.
53
54
	// . If 'force' is true, then we'll pop no matter what (whether we can verify it or not).
	bool Scanner::VerifySimpleKey(bool force)
55
56
57
58
59
60
61
62
63
	{
		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
64
65
66
		if(key.flowLevel != m_flowLevel) {
			if(force)
				m_simpleKeys.pop();
67
			return false;
68
		}
69
70
71
72
73
74
75
76
77
78
79
80

		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
81
		if(INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
			isValid = false;

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

		// In block style, remember that we've pushed an indent for this potential simple key (if it was starting).
		// If it was invalid, then we need to pop it off.
		// Note: we're guaranteed to be popping the right one (i.e., there couldn't have been anything in
		//       between) since keys have to be inline, and will be invalidated immediately on a newline.
		if(!isValid && m_flowLevel == 0)
			m_indents.pop();

		m_isLastKeyValid = isValid;
		return isValid;
	}

101
102
	// VerifyAllSimplyKeys
	// . Pops all simple keys (with checking, but if we can't verify one, then pop it anyways).
103
104
105
	void Scanner::VerifyAllSimpleKeys()
	{
		while(!m_simpleKeys.empty())
106
			VerifySimpleKey(true);
107
108
	}
}