private HybridDictionary RecursiveBuildDictionary(char[] contents, int fromIndex, IInternalContextAdapter context,
out int lastIndex)
{
lastIndex = 0;
HybridDictionary hash = new HybridDictionary(true);
bool inKey, valueStarted, expectSingleCommaAtEnd, inTransition, inEvaluationContext;
inKey = false;
inTransition = true;
valueStarted = expectSingleCommaAtEnd = inEvaluationContext = false;
StringBuilder sbKeyBuilder = new StringBuilder();
StringBuilder sbValBuilder = new StringBuilder();
for(int i = fromIndex; i < contents.Length; i++)
{
char c = contents[i];
if (inTransition)
{
// Eat all insignificant chars
if (c == ',' || c == ' ')
{
continue;
}
else if (c == '}') // Time to stop
{
lastIndex = i;
break;
}
else
{
inTransition = false;
inKey = true;
}
}
if (c == '=' && inKey)
{
inKey = false;
valueStarted = true;
continue;
}
if (inKey)
{
sbKeyBuilder.Append(c);
}
else
{
if (valueStarted && c == ' ') continue;
if (valueStarted)
{
valueStarted = false;
if (c == '\'')
{
expectSingleCommaAtEnd = true;
continue;
}
else if (c == '{')
{
object nestedHash = RecursiveBuildDictionary(contents, i + 1, context, out i);
ProcessDictEntry(hash, sbKeyBuilder, nestedHash, context);
inKey = false;
valueStarted = false;
inTransition = true;
continue;
}
}
if (c == '\\')
{
char ahead = contents[i + 1];
// Within escape
switch(ahead)
{
case 'r':
i++;
sbValBuilder.Append('\r');
continue;
case '\'':
i++;
sbValBuilder.Append('\'');
continue;
case '"':
i++;
sbValBuilder.Append('"');
continue;
case 'n':
i++;
sbValBuilder.Append('\n');
continue;
}
}
if ((c == '\'' && expectSingleCommaAtEnd) ||
(!expectSingleCommaAtEnd && c == ',') ||
(!inEvaluationContext && c == '}'))
{
ProcessDictEntry(hash, sbKeyBuilder, sbValBuilder, expectSingleCommaAtEnd, context);
inKey = false;
valueStarted = false;
inTransition = true;
if (!inEvaluationContext && c == '}')
{
lastIndex = i;
break;
}
}
else
{
if (!inEvaluationContext && c == '{')
{
inEvaluationContext = true;
}
else if (inEvaluationContext && c == '}')
{
inEvaluationContext = false;
}
sbValBuilder.Append(c);
}
}
if (i == contents.Length - 1)
{
if (sbKeyBuilder.ToString().Trim() == String.Empty)
{
break;
}
lastIndex = i;
ProcessDictEntry(hash, sbKeyBuilder, sbValBuilder, expectSingleCommaAtEnd, context);
inKey = false;
valueStarted = false;
inTransition = true;
}
}
return hash;
}