private void FetchNextToken()
{
// Check if we just started scanning. Fetch STREAM-START then.
if (!streamStartProduced)
{
FetchStreamStart();
return;
}
// Eat whitespaces and comments until we reach the next token.
ScanToNextToken();
// Remove obsolete potential simple keys.
StaleSimpleKeys();
// Check the indentation level against the current column.
UnrollIndent(cursor.LineOffset);
// Ensure that the buffer contains at least 4 characters. 4 is the length
// of the longest indicators ('--- ' and '... ').
analyzer.Buffer.Cache(4);
// Is it the end of the stream?
if (analyzer.Buffer.EndOfInput)
{
FetchStreamEnd();
return;
}
// Is it a directive?
if (cursor.LineOffset == 0 && analyzer.Check('%'))
{
FetchDirective();
return;
}
// Is it the document start indicator?
bool isDocumentStart =
cursor.LineOffset == 0 &&
analyzer.Check('-', 0) &&
analyzer.Check('-', 1) &&
analyzer.Check('-', 2) &&
analyzer.IsWhiteBreakOrZero(3);
if (isDocumentStart)
{
FetchDocumentIndicator(true);
return;
}
// Is it the document end indicator?
bool isDocumentEnd =
cursor.LineOffset == 0 &&
analyzer.Check('.', 0) &&
analyzer.Check('.', 1) &&
analyzer.Check('.', 2) &&
analyzer.IsWhiteBreakOrZero(3);
if (isDocumentEnd)
{
FetchDocumentIndicator(false);
return;
}
// Is it the flow sequence start indicator?
if (analyzer.Check('['))
{
FetchFlowCollectionStart(true);
return;
}
// Is it the flow mapping start indicator?
if (analyzer.Check('{'))
{
FetchFlowCollectionStart(false);
return;
}
// Is it the flow sequence end indicator?
if (analyzer.Check(']'))
{
FetchFlowCollectionEnd(true);
return;
}
// Is it the flow mapping end indicator?
if (analyzer.Check('}'))
{
FetchFlowCollectionEnd(false);
return;
}
// Is it the flow entry indicator?
if (analyzer.Check(','))
{
FetchFlowEntry();
return;
}
// Is it the block entry indicator?
if (analyzer.Check('-') && analyzer.IsWhiteBreakOrZero(1))
{
FetchBlockEntry();
return;
}
// Is it the key indicator?
if (analyzer.Check('?') && (flowLevel > 0 || analyzer.IsWhiteBreakOrZero(1)))
{
FetchKey();
return;
}
// Is it the value indicator?
if (analyzer.Check(':') && (flowLevel > 0 || analyzer.IsWhiteBreakOrZero(1)))
{
FetchValue();
return;
}
// Is it an alias?
if (analyzer.Check('*'))
{
FetchAnchor(true);
return;
}
// Is it an anchor?
if (analyzer.Check('&'))
{
FetchAnchor(false);
return;
}
// Is it a tag?
if (analyzer.Check('!'))
{
FetchTag();
return;
}
// Is it a literal scalar?
if (analyzer.Check('|') && flowLevel == 0)
{
FetchBlockScalar(true);
return;
}
// Is it a folded scalar?
if (analyzer.Check('>') && flowLevel == 0)
{
FetchBlockScalar(false);
return;
}
// Is it a single-quoted scalar?
if (analyzer.Check('\''))
{
FetchFlowScalar(true);
return;
}
// Is it a double-quoted scalar?
if (analyzer.Check('"'))
{
FetchFlowScalar(false);
return;
}
// Is it a plain scalar?
// A plain scalar may start with any non-blank characters except
// '-', '?', ':', ',', '[', ']', '{', '}',
// '#', '&', '*', '!', '|', '>', '\'', '\"',
// '%', '@', '`'.
// In the block context (and, for the '-' indicator, in the flow context
// too), it may also start with the characters
// '-', '?', ':'
// if it is followed by a non-space character.
// The last rule is more restrictive than the specification requires.
bool isInvalidPlainScalarCharacter = analyzer.IsWhiteBreakOrZero() || analyzer.Check("-?:,[]{}#&*!|>'\"%@`");
bool isPlainScalar =
!isInvalidPlainScalarCharacter ||
(analyzer.Check('-') && !analyzer.IsWhite(1)) ||
(flowLevel == 0 && (analyzer.Check("?:")) && !analyzer.IsWhiteBreakOrZero(1));
if (isPlainScalar)
{
FetchPlainScalar();
return;
}
// If we don't determine the token type so far, it is an error.
var start = cursor.Mark();
Skip();
var end = cursor.Mark();
throw new SyntaxErrorException(start, end, "While scanning for the next token, find character that cannot start any token.");
}