private static void ParseTypeSymbol(string id, ref int index, Compilation compilation, ISymbol typeParameterContext, List <ISymbol> results) { var ch = PeekNextChar(id, index); // context expression embedded in reference => <context-definition>:<type-parameter> // note: this is a deviation from the language spec if ((ch == 'M' || ch == 'T') && PeekNextChar(id, index + 1) == ':') { var contexts = s_symbolListPool.Allocate(); try { ParseDeclaredId(id, ref index, compilation, contexts); if (contexts.Count == 0) { // context cannot be bound, so abort return; } if (PeekNextChar(id, index) == ':') { index++; // try parsing following in all contexts var startIndex = index; foreach (var context in contexts) { index = startIndex; ParseTypeSymbol(id, ref index, compilation, context, results); } } else { // this was a definition where we expected a reference? results.AddRange(contexts.OfType <ITypeSymbol>()); } } finally { s_symbolListPool.ClearAndFree(contexts); } } else { if (ch == '`') { ParseTypeParameterSymbol(id, ref index, typeParameterContext, results); } else { ParseNamedTypeSymbol(id, ref index, compilation, typeParameterContext, results); } // apply any array or pointer constructions to results var startIndex = index; var endIndex = index; for (int i = 0; i < results.Count; i++) { index = startIndex; var typeSymbol = (ITypeSymbol)results[i]; while (true) { if (PeekNextChar(id, index) == '[') { var bounds = ParseArrayBounds(id, ref index); typeSymbol = compilation.CreateArrayTypeSymbol(typeSymbol, bounds); continue; } if (PeekNextChar(id, index) == '*') { index++; typeSymbol = compilation.CreatePointerTypeSymbol(typeSymbol); continue; } break; } results[i] = typeSymbol; endIndex = index; } index = endIndex; } }