"...composable_kernel_rocm.git" did not exist on "7c284291ddb01c75f67e4ac517d6c2f6b259ee64"
scanner.cpp 12.7 KB
Newer Older
Jesse Beder's avatar
Jesse Beder committed
1
2
#include "scanner.h"
#include "token.h"
Jesse Beder's avatar
Jesse Beder committed
3
#include "exceptions.h"
Jesse Beder's avatar
Jesse Beder committed
4
#include <iostream>
Jesse Beder's avatar
Jesse 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), m_column(0)
Jesse Beder's avatar
Jesse Beder committed
10
11
12
13
14
	{
	}

	Scanner::~Scanner()
	{
Jesse Beder's avatar
Jesse 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;
Jesse Beder's avatar
Jesse Beder committed
23
24
25
26
27
28
29
30
31
32
	}

	///////////////////////////////////////////////////////////////////////
	// Misc. helpers

	// GetChar
	// . Extracts a character from the stream and updates our position
	char Scanner::GetChar()
	{
		m_column++;
33
34
35
36
		char ch = INPUT.get();
		if(ch == '\n')
			m_column = 0;
		return ch;
Jesse Beder's avatar
Jesse Beder committed
37
38
	}

Jesse Beder's avatar
Jesse Beder committed
39
40
41
	// Eat
	// . Eats 'n' characters and updates our position.
	void Scanner::Eat(int n)
Jesse Beder's avatar
Jesse Beder committed
42
	{
Jesse Beder's avatar
Jesse Beder committed
43
44
45
46
47
48
		for(int i=0;i<n;i++) {
			m_column++;
			char ch = INPUT.get();
			if(ch == '\n')
				m_column = 0;
		}
Jesse Beder's avatar
Jesse Beder committed
49
50
	}

Jesse Beder's avatar
Jesse Beder committed
51
	// GetLineBreak
Jesse Beder's avatar
Jesse Beder committed
52
	// . Eats with no checking
Jesse Beder's avatar
Jesse Beder committed
53
	void Scanner::EatLineBreak()
Jesse Beder's avatar
Jesse Beder committed
54
	{
Jesse Beder's avatar
Jesse Beder committed
55
56
		Eat(1);
		m_column = 0;
Jesse Beder's avatar
Jesse Beder committed
57
58
59
60
61
62
63
64
65
	}

	// 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 ':')
Jesse Beder's avatar
Jesse Beder committed
66
	bool Scanner::IsWhitespaceToBeEaten(char ch)
Jesse Beder's avatar
Jesse Beder committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
	{
		if(ch == ' ')
			return true;

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

		return false;
	}

	// IsDocumentStart
	bool Scanner::IsDocumentStart()
	{
		// needs to be at the start of a new line
		if(m_column != 0)
			return false;

84
		return Exp::DocStart.Matches(INPUT);
Jesse Beder's avatar
Jesse Beder committed
85
86
87
88
89
90
91
92
93
	}

	// IsDocumentEnd
	bool Scanner::IsDocumentEnd()
	{
		// needs to be at the start of a new line
		if(m_column != 0)
			return false;

94
		return Exp::DocEnd.Matches(INPUT);
Jesse Beder's avatar
Jesse Beder committed
95
96
	}

Jesse Beder's avatar
Jesse Beder committed
97
98
99
	// IsBlockEntry
	bool Scanner::IsBlockEntry()
	{
100
		return Exp::BlockEntry.Matches(INPUT);
Jesse Beder's avatar
Jesse Beder committed
101
102
103
104
105
	}

	// IsKey
	bool Scanner::IsKey()
	{
106
		if(m_flowLevel > 0)
107
108
			return Exp::KeyInFlow.Matches(INPUT);
		return Exp::Key.Matches(INPUT);
Jesse Beder's avatar
Jesse Beder committed
109
110
111
112
113
	}

	// IsValue
	bool Scanner::IsValue()
	{
114
		if(m_flowLevel > 0)
115
116
			return Exp::ValueInFlow.Matches(INPUT);
		return Exp::Value.Matches(INPUT);
Jesse Beder's avatar
Jesse Beder committed
117
118
119
120
121
	}

	// IsPlainScalar
	bool Scanner::IsPlainScalar()
	{
122
		if(m_flowLevel > 0)
123
124
			return Exp::PlainScalarInFlow.Matches(INPUT);
		return Exp::PlainScalar.Matches(INPUT);
Jesse Beder's avatar
Jesse Beder committed
125
126
	}

Jesse Beder's avatar
Jesse Beder committed
127
128
129
	///////////////////////////////////////////////////////////////////////
	// Specialization for scanning specific tokens

Jesse Beder's avatar
Jesse Beder committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143
	// 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);
	}

Jesse Beder's avatar
Jesse Beder committed
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
	// StreamStartToken
	template <> StreamStartToken *Scanner::ScanToken(StreamStartToken *pToken)
	{
		m_startedStream = true;
		m_simpleKeyAllowed = true;
		m_indents.push(-1);

		return pToken;
	}

	// StreamEndToken
	template <> StreamEndToken *Scanner::ScanToken(StreamEndToken *pToken)
	{
		// force newline
		if(m_column > 0)
			m_column = 0;

Jesse Beder's avatar
Jesse Beder committed
161
		PopIndentTo(-1);
Jesse Beder's avatar
Jesse Beder committed
162
163
164
		// TODO: "reset simple keys"

		m_simpleKeyAllowed = false;
165
		m_endedStream = true;
Jesse Beder's avatar
Jesse Beder committed
166
167
168
169
170
171
172

		return pToken;
	}

	// DocumentStartToken
	template <> DocumentStartToken *Scanner::ScanToken(DocumentStartToken *pToken)
	{
Jesse Beder's avatar
Jesse Beder committed
173
174
		PopIndentTo(m_column);
		// TODO: "reset simple keys"
Jesse Beder's avatar
Jesse Beder committed
175
176
177

		m_simpleKeyAllowed = false;

Jesse Beder's avatar
Jesse Beder committed
178
179
		// eat
		Eat(3);
Jesse Beder's avatar
Jesse Beder committed
180
181
182
183
184
185
		return pToken;
	}

	// DocumentEndToken
	template <> DocumentEndToken *Scanner::ScanToken(DocumentEndToken *pToken)
	{
186
		PopIndentTo(-1);
Jesse Beder's avatar
Jesse Beder committed
187
		// TODO: "reset simple keys"
Jesse Beder's avatar
Jesse Beder committed
188
189
190

		m_simpleKeyAllowed = false;

Jesse Beder's avatar
Jesse Beder committed
191
192
		// eat
		Eat(3);
Jesse Beder's avatar
Jesse Beder committed
193
194
195
		return pToken;
	}

Jesse Beder's avatar
Jesse Beder committed
196
197
198
199
200
201
202
203
	// FlowSeqStartToken
	template <> FlowSeqStartToken *Scanner::ScanToken(FlowSeqStartToken *pToken)
	{
		// TODO: "save simple key"
		// TODO: increase flow level

		m_simpleKeyAllowed = true;

204
205
		// eat
		Eat(1);
Jesse Beder's avatar
Jesse Beder committed
206
207
208
209
210
211
212
213
214
215
216
		return pToken;
	}

	// FlowMapStartToken
	template <> FlowMapStartToken *Scanner::ScanToken(FlowMapStartToken *pToken)
	{
		// TODO: "save simple key"
		// TODO: increase flow level

		m_simpleKeyAllowed = true;

217
218
		// eat
		Eat(1);
Jesse Beder's avatar
Jesse Beder committed
219
220
221
222
223
224
225
226
227
228
229
		return pToken;
	}

	// FlowSeqEndToken
	template <> FlowSeqEndToken *Scanner::ScanToken(FlowSeqEndToken *pToken)
	{
		// TODO: "remove simple key"
		// TODO: decrease flow level

		m_simpleKeyAllowed = false;

230
231
		// eat
		Eat(1);
Jesse Beder's avatar
Jesse Beder committed
232
233
234
235
236
237
238
239
240
241
242
		return pToken;
	}

	// FlowMapEndToken
	template <> FlowMapEndToken *Scanner::ScanToken(FlowMapEndToken *pToken)
	{
		// TODO: "remove simple key"
		// TODO: decrease flow level

		m_simpleKeyAllowed = false;

243
244
		// eat
		Eat(1);
Jesse Beder's avatar
Jesse Beder committed
245
246
247
248
249
250
251
252
253
254
		return pToken;
	}

	// FlowEntryToken
	template <> FlowEntryToken *Scanner::ScanToken(FlowEntryToken *pToken)
	{
		// TODO: "remove simple key"

		m_simpleKeyAllowed = true;

255
256
		// eat
		Eat(1);
Jesse Beder's avatar
Jesse Beder committed
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
		return pToken;
	}

	// BlockEntryToken
	template <> BlockEntryToken *Scanner::ScanToken(BlockEntryToken *pToken)
	{
		// we better be in the block context!
		if(m_flowLevel == 0) {
			// can we put it here?
			if(!m_simpleKeyAllowed)
				throw IllegalBlockEntry();

			PushIndentTo(m_column, true);	// , -1
		} else {
			// TODO: throw?
		}

		// TODO: "remove simple key"

		m_simpleKeyAllowed = true;

		// eat
Jesse Beder's avatar
Jesse Beder committed
279
		Eat(1);
Jesse Beder's avatar
Jesse Beder committed
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
		return pToken;
	}

	// KeyToken
	template <> KeyToken *Scanner::ScanToken(KeyToken *pToken)
	{
		// are we in block context?
		if(m_flowLevel == 0) {
			if(!m_simpleKeyAllowed)
				throw IllegalMapKey();

			PushIndentTo(m_column, false);
		}

		// TODO: "remove simple key"

		// can only put a simple key here if we're in block context
		if(m_flowLevel == 0)
			m_simpleKeyAllowed = true;
		else
			m_simpleKeyAllowed = false;

		// eat
Jesse Beder's avatar
Jesse Beder committed
303
		Eat(1);
Jesse Beder's avatar
Jesse Beder committed
304
305
306
307
308
309
310
311
312
		return pToken;
	}

	// ValueToken
	template <> ValueToken *Scanner::ScanToken(ValueToken *pToken)
	{
		// TODO: Is it a simple key?
		if(false) {
		} else {
Jesse Beder's avatar
Jesse Beder committed
313
314
315
316
317
318
319
320
321
322
			// If not, ...
			// are we in block context?
			if(m_flowLevel == 0) {
				if(!m_simpleKeyAllowed)
					throw IllegalMapValue();

				PushIndentTo(m_column, false);
			}
		}

Jesse Beder's avatar
Jesse Beder committed
323
324
325
326
		// can only put a simple key here if we're in block context
		if(m_flowLevel == 0)
			m_simpleKeyAllowed = true;
		else
Jesse Beder's avatar
Jesse Beder committed
327
328
329
330
			m_simpleKeyAllowed = false;

		// eat
		Eat(1);
Jesse Beder's avatar
Jesse Beder committed
331
332
333
334
335
		return pToken;
	}

	// PlainScalarToken
	template <> PlainScalarToken *Scanner::ScanToken(PlainScalarToken *pToken)
Jesse Beder's avatar
Jesse Beder committed
336
337
338
339
340
341
	{
		// TODO: "save simple key"

		m_simpleKeyAllowed = false;

		// now eat and store the scalar
342
343
		std::string scalar, whitespace, leadingBreaks, trailingBreaks;
		bool leadingBlanks = false;
Jesse Beder's avatar
Jesse Beder committed
344
345
346
347
348
349
350

		while(INPUT) {
			// doc start/end tokens
			if(IsDocumentStart() || IsDocumentEnd())
				break;

			// comment
351
			if(Exp::Comment.Matches(INPUT))
Jesse Beder's avatar
Jesse Beder committed
352
353
354
				break;

			// first eat non-blanks
355
			while(INPUT && !Exp::BlankOrBreak.Matches(INPUT)) {
Jesse Beder's avatar
Jesse Beder committed
356
				// illegal colon in flow context
357
				if(m_flowLevel > 0 && Exp::IllegalColonInScalar.Matches(INPUT))
358
					throw IllegalScalar();
Jesse Beder's avatar
Jesse Beder committed
359
360

				// characters that might end the scalar
361
				if(m_flowLevel > 0 && Exp::EndScalarInFlow.Matches(INPUT))
Jesse Beder's avatar
Jesse Beder committed
362
					break;
363
				if(m_flowLevel == 0 && Exp::EndScalar.Matches(INPUT))
Jesse Beder's avatar
Jesse Beder committed
364
365
					break;

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
				if(leadingBlanks) {
					if(!leadingBreaks.empty() && leadingBreaks[0] == '\n') {
						// fold line break?
						if(trailingBreaks.empty())
							scalar += ' ';
						else {
							scalar += trailingBreaks;
							trailingBreaks = "";
						}
					} else {
						scalar += leadingBreaks + trailingBreaks;
						leadingBreaks = "";
						trailingBreaks = "";
					}
				} else if(!whitespace.empty()) {
					scalar += whitespace;
					whitespace = "";
				}

				// finally, read the character!
Jesse Beder's avatar
Jesse Beder committed
386
387
388
				scalar += GetChar();
			}

389
			// did we hit a non-blank character that ended us?
390
			if(!Exp::BlankOrBreak.Matches(INPUT))
391
392
				break;

Jesse Beder's avatar
Jesse Beder committed
393
			// now eat blanks
394
395
			while(INPUT && Exp::BlankOrBreak.Matches(INPUT)) {
				if(Exp::Blank.Matches(INPUT)) {
Jesse Beder's avatar
Jesse Beder committed
396
397
398
					if(leadingBlanks && m_column <= m_indents.top())
						throw IllegalTabInScalar();

399
400
401
402
403
					// maybe store this character
					if(!leadingBlanks)
						whitespace += GetChar();
					else
						Eat(1);
Jesse Beder's avatar
Jesse Beder committed
404
				} else {
405
406
407
408
409
410
411
					// where to store this character?
					if(!leadingBlanks) {
						leadingBlanks = true;
						whitespace = "";
						leadingBreaks += GetChar();
					} else
						trailingBreaks += GetChar();
Jesse Beder's avatar
Jesse Beder committed
412
413
414
415
416
417
418
419
420
				}
			}

			// and finally break if we're below the indentation level
			if(m_flowLevel == 0 && m_column <= m_indents.top())
				break;
		}

		// now modify our token
421
		pToken->SetValue(scalar);
Jesse Beder's avatar
Jesse Beder committed
422
423
424
		if(leadingBlanks)
			m_simpleKeyAllowed = true;

Jesse Beder's avatar
Jesse Beder committed
425
426
427
		return pToken;
	}

Jesse Beder's avatar
Jesse Beder committed
428
429
430
	///////////////////////////////////////////////////////////////////////
	// The main scanning function

Jesse Beder's avatar
Jesse Beder committed
431
	void Scanner::ScanNextToken()
Jesse Beder's avatar
Jesse Beder committed
432
	{
433
434
435
		if(m_endedStream)
			return;

Jesse Beder's avatar
Jesse Beder committed
436
		if(!m_startedStream)
Jesse Beder's avatar
Jesse Beder committed
437
			return ScanAndEnqueue(new StreamStartToken);
Jesse Beder's avatar
Jesse Beder committed
438
439
440

		ScanToNextToken();
		// TODO: remove "obsolete potential simple keys"
Jesse Beder's avatar
Jesse Beder committed
441
		PopIndentTo(m_column);
Jesse Beder's avatar
Jesse Beder committed
442
443

		if(INPUT.peek() == EOF)
Jesse Beder's avatar
Jesse Beder committed
444
			return ScanAndEnqueue(new StreamEndToken);
Jesse Beder's avatar
Jesse Beder committed
445

Jesse Beder's avatar
Jesse Beder committed
446
		// are we at a document token?
Jesse Beder's avatar
Jesse Beder committed
447
		if(IsDocumentStart())
Jesse Beder's avatar
Jesse Beder committed
448
			return ScanAndEnqueue(new DocumentStartToken);
Jesse Beder's avatar
Jesse Beder committed
449
450

		if(IsDocumentEnd())
Jesse Beder's avatar
Jesse Beder committed
451
			return ScanAndEnqueue(new DocumentEndToken);
Jesse Beder's avatar
Jesse Beder committed
452

Jesse Beder's avatar
Jesse Beder committed
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
		// are we at a flow start/end/entry?
		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);

		// block/map stuff?
		if(IsBlockEntry())
			return ScanAndEnqueue(new BlockEntryToken);

		if(IsKey())
			return ScanAndEnqueue(new KeyToken);

		if(IsValue())
			return ScanAndEnqueue(new ValueToken);

		// TODO: alias/anchor/tag

		// TODO: special scalars
		if(INPUT.peek() == Keys::LiteralScalar && m_flowLevel == 0)
			return;

		if(INPUT.peek() == Keys::FoldedScalar && m_flowLevel == 0)
			return;

		if(INPUT.peek() == '\'')
			return;

		if(INPUT.peek() == '\"')
			return;

		// plain scalars
		if(IsPlainScalar())
			return ScanAndEnqueue(new PlainScalarToken);

		// don't know what it is!
		throw UnknownToken();
Jesse Beder's avatar
Jesse Beder committed
500
501
502
503
504
505
506
507
	}

	// ScanToNextToken
	// . Eats input until we reach the next token-like thing.
	void Scanner::ScanToNextToken()
	{
		while(1) {
			// first eat whitespace
Jesse Beder's avatar
Jesse Beder committed
508
509
			while(IsWhitespaceToBeEaten(INPUT.peek()))
				Eat(1);
Jesse Beder's avatar
Jesse Beder committed
510
511

			// then eat a comment
512
			if(Exp::Comment.Matches(INPUT.peek())) {
Jesse Beder's avatar
Jesse Beder committed
513
				// eat until line break
514
				while(INPUT && !Exp::Break.Matches(INPUT.peek()))
Jesse Beder's avatar
Jesse Beder committed
515
					Eat(1);
Jesse Beder's avatar
Jesse Beder committed
516
517
518
			}

			// if it's NOT a line break, then we're done!
519
			if(!Exp::Break.Matches(INPUT.peek()))
Jesse Beder's avatar
Jesse Beder committed
520
521
522
523
524
525
526
527
528
529
530
				break;

			// otherwise, let's eat the line break and keep going
			EatLineBreak();

			// new line - we may be able to accept a simple key now
			if(m_flowLevel == 0)
				m_simpleKeyAllowed = true;
        }
	}

Jesse Beder's avatar
Jesse Beder committed
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
	// PushIndentTo
	// . Pushes an indentation onto the stack, and enqueues the
	//   proper token (sequence start or mapping start).
	void Scanner::PushIndentTo(int column, bool sequence)
	{
		// are we in flow?
		if(m_flowLevel > 0)
			return;

		// is this actually an indentation?
		if(column <= m_indents.top())
			return;

		// now push
		m_indents.push(column);
		if(sequence)
			m_tokens.push(new BlockSeqStartToken);
		else
			m_tokens.push(new BlockMapStartToken);
	}

	// 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);
		}
	}

Jesse Beder's avatar
Jesse Beder committed
568
569
570
	// temporary function for testing
	void Scanner::Scan()
	{
571
		while(1) {
Jesse Beder's avatar
Jesse Beder committed
572
			ScanNextToken();
573
574
			if(m_tokens.empty())
				break;
Jesse Beder's avatar
Jesse Beder committed
575
576
577
578
579
580
581
582

			while(!m_tokens.empty()) {
				Token *pToken = m_tokens.front();
				m_tokens.pop();
				std::cout << typeid(*pToken).name() << std::endl;
				delete pToken;
			}
		}
Jesse Beder's avatar
Jesse Beder committed
583
584
	}
}