private static List<SyntaxToken> ReplaceParameters(
List<MacroArgumentSyntax> originalArguments,
List<List<SyntaxToken>> expandedArguments,
FunctionLikeDefineDirectiveParameterListSyntax parameterList,
List<SyntaxToken> macroBody)
{
var parameters = parameterList.Parameters;
var result = new List<SyntaxToken>();
for (var i = 0; i < macroBody.Count; i++)
{
var token = macroBody[i];
// Do token pasting (##).
if (i < macroBody.Count - 2
&& macroBody[i + 1].Kind == SyntaxKind.HashHashToken
&& macroBody[i + 2].Kind != SyntaxKind.EndOfFileToken
&& macroBody[i + 2].Kind != SyntaxKind.HashHashToken)
{
var parameterIndexLeft = FindParameterIndex(parameters, token);
var pastedText = (parameterIndexLeft != -1) ? originalArguments[parameterIndexLeft].ToString(true) : token.Text;
while (i < macroBody.Count - 2
&& macroBody[i + 1].Kind == SyntaxKind.HashHashToken
&& macroBody[i + 2].Kind != SyntaxKind.EndOfFileToken
&& macroBody[i + 2].Kind != SyntaxKind.HashHashToken)
{
var parameterIndexRight = FindParameterIndex(parameters, macroBody[i + 2]);
var textRight = (parameterIndexRight != -1) ? originalArguments[parameterIndexRight].ToString(true) : macroBody[i + 2].Text;
pastedText += textRight;
i += 2;
}
result.AddRange(SyntaxFactory.ParseAllTokens(new StringText(pastedText)).TakeWhile(t => t.Kind != SyntaxKind.EndOfFileToken));
continue;
}
switch (token.Kind)
{
// Potentially stringify.
case SyntaxKind.HashToken:
{
if (i < macroBody.Count - 1 && macroBody[i + 1].Kind.IsIdentifierOrKeyword())
{
var parameterIndex = FindParameterIndex(parameters, macroBody[i + 1]);
if (parameterIndex != -1)
{
var stringifiedText = "\"" + originalArguments[parameterIndex].ToString(true) + "\"";
result.Add(SyntaxFactory.ParseToken(stringifiedText));
i++;
break;
}
}
goto default;
}
// Potentially replacement parameter with argument tokens.
case SyntaxKind.IdentifierToken:
{
var parameterIndex = FindParameterIndex(parameters, token);
if (parameterIndex != -1)
result.AddRange(expandedArguments[parameterIndex]);
else
result.Add(token);
break;
}
default:
{
if (token.Kind.IsKeyword())
goto case SyntaxKind.IdentifierToken;
result.Add(token);
break;
}
}
}
return result;
}