Token ScanTag()
{
var start = cursor.Mark();
// Check if the tag is in the canonical form.
string handle;
string suffix;
if (analyzer.Check('<', 1))
{
// Set the handle to ''
handle = string.Empty;
// Eat '!<'
Skip();
Skip();
// Consume the tag value.
suffix = ScanTagUri(null, start);
// Check for '>' and eat it.
if (!analyzer.Check('>'))
{
throw new SyntaxErrorException(start, cursor.Mark(), "While scanning a tag, did not find the expected '>'.");
}
Skip();
}
else
{
// The tag has either the '!suffix' or the '!handle!suffix' form.
// First, try to scan a handle.
var firstPart = ScanTagHandle(false, start);
// Check if it is, indeed, handle.
if (firstPart.Length > 1 && firstPart[0] == '!' && firstPart[firstPart.Length - 1] == '!')
{
handle = firstPart;
// Scan the suffix now.
suffix = ScanTagUri(null, start);
}
else
{
// It wasn't a handle after all. Scan the rest of the tag.
suffix = ScanTagUri(firstPart, start);
// Set the handle to '!'.
handle = "!";
// A special case: the '!' tag. Set the handle to '' and the
// suffix to '!'.
if (suffix.Length == 0)
{
suffix = handle;
handle = string.Empty;
}
}
}
// Check the character which ends the tag.
if (!analyzer.IsWhiteBreakOrZero())
{
throw new SyntaxErrorException(start, cursor.Mark(), "While scanning a tag, did not find expected whitespace or line break.");
}
// Create a token.
return new Tag(handle, suffix, start, cursor.Mark());
}