in Sources/Visualization/Microsoft.Psi.Visualization.Windows/Views/Visuals2D/DiagnosticsVisualization/TypeSpec.cs [143:220]
private static TypeSpec Parse(Token[] tokens)
{
StringBuilder name = new StringBuilder();
StringBuilder modifier = new StringBuilder();
for (var i = 0; i < tokens.Length; i++)
{
var t = tokens[i];
switch (t.Kind)
{
case TokenKind.Name:
name.Clear();
name.Append(t.Value);
break;
case TokenKind.Open:
modifier.Append('['); // before ` braces represent arrays
break;
case TokenKind.Close:
modifier.Append(']'); // before ` braces represent arrays
break;
case TokenKind.Separator:
switch (t.Value)
{
case ",":
return new TypeSpec(name.ToString(), modifier.ToString()); // e.g. [Foo.Bar[], ... -> Bar []
case "`":
// generic type specification
var spec = new TypeSpec(name.ToString(), modifier.ToString());
if (i + 3 >= tokens.Length || tokens[i + 2].Kind != TokenKind.Open || tokens[i + 3].Kind != TokenKind.Open)
{
return spec; // some types appear to be generic, but are _not_ followed by type params
}
// parse type params in the form [[...<param0>...],[...<param1>...],...] by matching braces and recursing
int match = 0;
for (var j = i + 3; j < tokens.Length; j++)
{
switch (tokens[j].Kind)
{
case TokenKind.Open:
match++;
break;
case TokenKind.Close:
match--;
break;
}
// sub [...<param>...] part
if (match == 0 && i + 4 < tokens.Length)
{
var len = j - i - 5;
var childTokens = new Token[len];
Array.Copy(tokens, i + 4, childTokens, 0, len);
spec.TypeParams.Add(Parse(childTokens)); // recurse
if (j + 1 < tokens.Length && tokens[j + 1].Kind == TokenKind.Close)
{
return spec; // final
}
else
{
j++;
i = j;
if (j + 1 >= tokens.Length || tokens[j].Kind != TokenKind.Separator || tokens[j].Value != "," || tokens[j + 1].Kind != TokenKind.Open)
{
throw new ArgumentException("Malformed generic syntax. Expected \"Foo`123[[...],[...\"");
}
}
}
}
break;
}
break;
}
}
return new TypeSpec(name.ToString(), modifier.ToString()); // undelimited single type
}