internal SyntaxToken ScanXmlPIData(ScannerState state)
{
// // Scan the PI data after the white space
// // [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
// // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
Debug.Assert(state == ScannerState.StartProcessingInstruction || state == ScannerState.ProcessingInstruction);
var precedingTrivia = triviaListPool.Allocate<SyntaxNode>();
SyntaxToken result;
if (state == ScannerState.StartProcessingInstruction && CanGetChar())
{
var c = PeekChar();
switch (c)
{
case UCH_CR:
case UCH_LF:
case ' ':
case UCH_TAB:
var wsTrivia = ScanXmlTrivia(c);
precedingTrivia.AddRange(wsTrivia);
break;
}
}
var Here = 0;
while (CanGetCharAtOffset(Here))
{
char c = PeekAheadChar(Here);
switch (c)
{
case UCH_CR:
case UCH_LF:
result = XmlMakeProcessingInstructionToken(precedingTrivia.ToList(), Here + LengthOfLineBreak(c, Here));
goto CleanUp;
case '?':
if (CanGetCharAtOffset(Here + 1) && PeekAheadChar(Here + 1) == '>')
{
//// If valid characters found then return them.
if (Here != 0)
{
result = XmlMakeProcessingInstructionToken(precedingTrivia.ToList(), Here);
goto CleanUp;
}
// // Create token for the '?>' termination sequence
result = XmlMakeEndProcessingInstructionToken(precedingTrivia.ToList());
goto CleanUp;
}
goto default;
default:
var xmlCh = ScanXmlChar(Here);
if (xmlCh.Length > 0)
{
Here += xmlCh.Length;
continue;
}
// bad char
if (Here != 0)
{
result = XmlMakeProcessingInstructionToken(precedingTrivia.ToList(), Here);
goto CleanUp;
}
else
{
result = XmlMakeBadToken(precedingTrivia.ToList(), 1, ERRID.ERR_IllegalChar);
goto CleanUp;
}
}
}
// no more chars
if (Here > 0)
{
result = XmlMakeProcessingInstructionToken(precedingTrivia.ToList(), Here);
}
else
{
result = MakeEofToken(precedingTrivia.ToList());
}
CleanUp:
triviaListPool.Free(precedingTrivia);
return result;
}