private Token ScanPlainScalar()
{
var value = new StringBuilder();
var whitespaces = new StringBuilder();
var leadingBreak = new StringBuilder();
var trailingBreaks = new StringBuilder();
bool hasLeadingBlanks = false;
int currentIndent = indent + 1;
var start = cursor.Mark();
var end = start;
// Consume the content of the plain scalar.
for (;;)
{
// Check for a document indicator.
if (IsDocumentIndicator())
{
break;
}
// Check for a comment.
if (analyzer.Check('#'))
{
break;
}
// Consume non-blank characters.
while (!analyzer.IsWhiteBreakOrZero())
{
// Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13".
if (flowLevel > 0 && analyzer.Check(':') && !analyzer.IsWhiteBreakOrZero(1))
{
throw new SyntaxErrorException(start, cursor.Mark(), "While scanning a plain scalar, find unexpected ':'.");
}
// Check for indicators that may end a plain scalar.
if ((analyzer.Check(':') && analyzer.IsWhiteBreakOrZero(1)) || (flowLevel > 0 && analyzer.Check(",:?[]{}")))
{
break;
}
// Check if we need to join whitespaces and breaks.
if (hasLeadingBlanks || whitespaces.Length > 0)
{
if (hasLeadingBlanks)
{
// Do we need to fold line breaks?
if (StartsWith(leadingBreak, '\n'))
{
if (trailingBreaks.Length == 0)
{
value.Append(' ');
}
else
{
value.Append(trailingBreaks);
}
}
else
{
value.Append(leadingBreak);
value.Append(trailingBreaks);
}
leadingBreak.Length = 0;
trailingBreaks.Length = 0;
hasLeadingBlanks = false;
}
else
{
value.Append(whitespaces);
whitespaces.Length = 0;
}
}
// Copy the character.
value.Append(ReadCurrentCharacter());
end = cursor.Mark();
}
// Is it the end?
if (!(analyzer.IsWhite() || analyzer.IsBreak()))
{
break;
}
// Consume blank characters.
while (analyzer.IsWhite() || analyzer.IsBreak())
{
if (analyzer.IsWhite())
{
// Check for tab character that abuse intendation.
if (hasLeadingBlanks && cursor.LineOffset < currentIndent && analyzer.IsTab())
{
throw new SyntaxErrorException(start, cursor.Mark(), "While scanning a plain scalar, find a tab character that violate intendation.");
}
// Consume a space or a tab character.
if (!hasLeadingBlanks)
{
whitespaces.Append(ReadCurrentCharacter());
}
else
{
Skip();
}
}
else
{
// Check if it is a first line break.
if (!hasLeadingBlanks)
{
whitespaces.Length = 0;
leadingBreak.Append(ReadLine());
hasLeadingBlanks = true;
}
else
{
trailingBreaks.Append(ReadLine());
}
}
}
// Check intendation level.
if (flowLevel == 0 && cursor.LineOffset < currentIndent)
{
break;
}
}
// Note that we change the 'simple_key_allowed' flag.
if (hasLeadingBlanks)
{
simpleKeyAllowed = true;
}
// Create a token.
return new Scalar(value.ToString(), ScalarStyle.Plain, start, end);
}