"git@developer.sourcefind.cn:modelzoo/unet_migraphx.git" did not exist on "eac0c647283129c2aa56c3e54baad9a2f28712f7"
scanner.cpp 6.88 KB
Newer Older
beder's avatar
beder committed
1
2
#include "scanner.h"
#include "token.h"
beder's avatar
beder committed
3
#include "exceptions.h"
4
#include "exp.h"
beder's avatar
beder committed
5
6
7
8

namespace YAML
{
	Scanner::Scanner(std::istream& in)
9
		: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_flowLevel(0)
beder's avatar
beder committed
10
11
12
13
14
	{
	}

	Scanner::~Scanner()
	{
beder's avatar
beder committed
15
16
17
18
19
20
21
22
		while(!m_tokens.empty()) {
			delete m_tokens.front();
			m_tokens.pop();
		}

		// delete limbo tokens (they're here for RAII)
		for(std::set <Token *>::const_iterator it=m_limboTokens.begin();it!=m_limboTokens.end();++it)
			delete *it;
beder's avatar
beder committed
23
24
	}

25
26
27
28
29
30
31
32
33
	// GetNextToken
	// . Removes and returns the next token on the queue.
	Token *Scanner::GetNextToken()
	{
		Token *pToken = PeekNextToken();
		if(!m_tokens.empty())
			m_tokens.pop();
		return pToken;
	}
beder's avatar
beder committed
34

35
36
37
	// PeekNextToken
	// . Returns (but does not remove) the next token on the queue, and scans if only we need to.
	Token *Scanner::PeekNextToken()
beder's avatar
beder committed
38
	{
39
40
		while(1) {
			Token *pToken = 0;
beder's avatar
beder committed
41

42
43
44
			// is there a token in the queue?
			if(!m_tokens.empty())
				pToken = m_tokens.front();
beder's avatar
beder committed
45

46
47
48
49
50
51
			// (here's where we clean up the impossible tokens)
			if(pToken && pToken->status == TS_INVALID) {
				m_tokens.pop();
				delete pToken;
				continue;
			}
beder's avatar
beder committed
52

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
			// on unverified tokens, we just have to wait
			if(pToken && pToken->status == TS_UNVERIFIED)
				pToken = 0;

			// then that's what we want
			if(pToken)
				return pToken;

			// no token? maybe we've actually finished
			if(m_endedStream)
				break;

			// no? then scan...
			ScanNextToken();
		}

		return 0;
beder's avatar
beder committed
70
71
	}

beder's avatar
beder committed
72
73
74
	// ScanNextToken
	// . The main scanning function; here we branch out and
	//   scan whatever the next token should be.
beder's avatar
beder committed
75
	void Scanner::ScanNextToken()
beder's avatar
beder committed
76
	{
77
78
79
		if(m_endedStream)
			return;

beder's avatar
beder committed
80
		if(!m_startedStream)
beder's avatar
beder committed
81
			return ScanAndEnqueue(new StreamStartToken);
beder's avatar
beder committed
82

beder's avatar
beder committed
83
		// get rid of whitespace, etc. (in between tokens it should be irrelevent)
beder's avatar
beder committed
84
		ScanToNextToken();
beder's avatar
beder committed
85
86

		// check the latest simple key
87
		VerifySimpleKey();
beder's avatar
beder committed
88
89

		// maybe need to end some blocks
90
		PopIndentTo(INPUT.column);
beder's avatar
beder committed
91

beder's avatar
beder committed
92
93
94
95
96
		// *****
		// And now branch based on the next few characters!
		// *****

		// end of stream
beder's avatar
beder committed
97
		if(INPUT.peek() == EOF)
beder's avatar
beder committed
98
			return ScanAndEnqueue(new StreamEndToken);
beder's avatar
beder committed
99

beder's avatar
beder committed
100
101
102
		if(INPUT.column == 0 && INPUT.peek() == Keys::Directive)
			return ScanAndEnqueue(new DirectiveToken);

beder's avatar
beder committed
103
		// document token
beder's avatar
beder committed
104
		if(INPUT.column == 0 && Exp::DocStart.Matches(INPUT))
beder's avatar
beder committed
105
			return ScanAndEnqueue(new DocumentStartToken);
beder's avatar
beder committed
106

beder's avatar
beder committed
107
		if(INPUT.column == 0 && Exp::DocEnd.Matches(INPUT))
beder's avatar
beder committed
108
			return ScanAndEnqueue(new DocumentEndToken);
beder's avatar
beder committed
109

beder's avatar
beder committed
110
		// flow start/end/entry
beder's avatar
beder committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
		if(INPUT.peek() == Keys::FlowSeqStart)
			return ScanAndEnqueue(new FlowSeqStartToken);

		if(INPUT.peek() == Keys::FlowSeqEnd)
			return ScanAndEnqueue(new FlowSeqEndToken);
		
		if(INPUT.peek() == Keys::FlowMapStart)
			return ScanAndEnqueue(new FlowMapStartToken);
		
		if(INPUT.peek() == Keys::FlowMapEnd)
			return ScanAndEnqueue(new FlowMapEndToken);

		if(INPUT.peek() == Keys::FlowEntry)
			return ScanAndEnqueue(new FlowEntryToken);

beder's avatar
beder committed
126
		// block/map stuff
beder's avatar
beder committed
127
		if(Exp::BlockEntry.Matches(INPUT))
beder's avatar
beder committed
128
129
			return ScanAndEnqueue(new BlockEntryToken);

beder's avatar
beder committed
130
		if((m_flowLevel == 0 ? Exp::Key : Exp::KeyInFlow).Matches(INPUT))
beder's avatar
beder committed
131
132
			return ScanAndEnqueue(new KeyToken);

beder's avatar
beder committed
133
		if((m_flowLevel == 0 ? Exp::Value : Exp::ValueInFlow).Matches(INPUT))
beder's avatar
beder committed
134
135
			return ScanAndEnqueue(new ValueToken);

beder's avatar
beder committed
136
		// alias/anchor
beder's avatar
beder committed
137
138
139
		if(INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor)
			return ScanAndEnqueue(new AnchorToken);

beder's avatar
beder committed
140
141
142
		// tag
		if(INPUT.peek() == Keys::Tag)
			return ScanAndEnqueue(new TagToken);
beder's avatar
beder committed
143

beder's avatar
beder committed
144
145
146
		// special scalars
		if(m_flowLevel == 0 && (INPUT.peek() == Keys::LiteralScalar || INPUT.peek() == Keys::FoldedScalar))
			return ScanAndEnqueue(new BlockScalarToken);
beder's avatar
beder committed
147

beder's avatar
beder committed
148
149
		if(INPUT.peek() == '\'' || INPUT.peek() == '\"')
			return ScanAndEnqueue(new QuotedScalarToken);
beder's avatar
beder committed
150
151

		// plain scalars
beder's avatar
beder committed
152
		if((m_flowLevel == 0 ? Exp::PlainScalar : Exp::PlainScalarInFlow).Matches(INPUT))
beder's avatar
beder committed
153
154
155
156
			return ScanAndEnqueue(new PlainScalarToken);

		// don't know what it is!
		throw UnknownToken();
beder's avatar
beder committed
157
158
159
160
161
162
163
164
	}

	// ScanToNextToken
	// . Eats input until we reach the next token-like thing.
	void Scanner::ScanToNextToken()
	{
		while(1) {
			// first eat whitespace
beder's avatar
beder committed
165
			while(IsWhitespaceToBeEaten(INPUT.peek()))
166
				INPUT.Eat(1);
beder's avatar
beder committed
167
168

			// then eat a comment
beder's avatar
beder committed
169
			if(Exp::Comment.Matches(INPUT)) {
beder's avatar
beder committed
170
				// eat until line break
beder's avatar
beder committed
171
				while(INPUT && !Exp::Break.Matches(INPUT))
172
					INPUT.Eat(1);
beder's avatar
beder committed
173
174
175
			}

			// if it's NOT a line break, then we're done!
beder's avatar
beder committed
176
			if(!Exp::Break.Matches(INPUT))
beder's avatar
beder committed
177
178
179
				break;

			// otherwise, let's eat the line break and keep going
180
181
			int n = Exp::Break.Match(INPUT);
			INPUT.Eat(n);
beder's avatar
beder committed
182

beder's avatar
beder committed
183
			// oh yeah, and let's get rid of that simple key
184
			VerifySimpleKey();
beder's avatar
beder committed
185

beder's avatar
beder committed
186
187
188
189
190
191
			// new line - we may be able to accept a simple key now
			if(m_flowLevel == 0)
				m_simpleKeyAllowed = true;
        }
	}

192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
	///////////////////////////////////////////////////////////////////////
	// Misc. helpers

	// IsWhitespaceToBeEaten
	// . We can eat whitespace if:
	//   1. It's a space
	//   2. It's a tab, and we're either:
	//      a. In the flow context
	//      b. In the block context but not where a simple key could be allowed
	//         (i.e., not at the beginning of a line, or following '-', '?', or ':')
	bool Scanner::IsWhitespaceToBeEaten(char ch)
	{
		if(ch == ' ')
			return true;

		if(ch == '\t' && (m_flowLevel >= 0 || !m_simpleKeyAllowed))
			return true;

		return false;
	}

	// ScanAndEnqueue
	// . Scans the token, then pushes it in the queue.
	// . Note: we also use a set of "limbo tokens", i.e., tokens
	//   that haven't yet been pushed. This way, if ScanToken()
	//   throws an exception, we'll be keeping track of 'pToken'
	//   somewhere, and it will be automatically cleaned up when
	//   the Scanner destructs.
	template <typename T> void Scanner::ScanAndEnqueue(T *pToken)
	{
		m_limboTokens.insert(pToken);
		m_tokens.push(ScanToken(pToken));
		m_limboTokens.erase(pToken);
	}

beder's avatar
beder committed
227
228
229
	// PushIndentTo
	// . Pushes an indentation onto the stack, and enqueues the
	//   proper token (sequence start or mapping start).
beder's avatar
beder committed
230
231
	// . Returns the token it generates (if any).
	Token *Scanner::PushIndentTo(int column, bool sequence)
beder's avatar
beder committed
232
233
234
	{
		// are we in flow?
		if(m_flowLevel > 0)
beder's avatar
beder committed
235
			return 0;
beder's avatar
beder committed
236
237
238

		// is this actually an indentation?
		if(column <= m_indents.top())
beder's avatar
beder committed
239
			return 0;
beder's avatar
beder committed
240
241
242
243
244
245
246

		// now push
		m_indents.push(column);
		if(sequence)
			m_tokens.push(new BlockSeqStartToken);
		else
			m_tokens.push(new BlockMapStartToken);
beder's avatar
beder committed
247
248

		return m_tokens.front();
beder's avatar
beder committed
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
	}

	// PopIndentTo
	// . Pops indentations off the stack until we reach 'column' indentation,
	//   and enqueues the proper token each time.
	void Scanner::PopIndentTo(int column)
	{
		// are we in flow?
		if(m_flowLevel > 0)
			return;

		// now pop away
		while(!m_indents.empty() && m_indents.top() > column) {
			m_indents.pop();
			m_tokens.push(new BlockEndToken);
		}
	}
beder's avatar
beder committed
266
}