How could I refactor this into more manageable methods?
- by ChaosPandion
private static JsonStructure Parse(string jsonText, bool throwException)
{
var result = default(JsonStructure);
var structureStack = new Stack<JsonStructure>();
var keyStack = new Stack<string>();
var current = default(JsonStructure);
var currentState = ParserState.Begin;
var invalidToken = false;
var key = default(string);
var value = default(object);
foreach (var token in Lexer.Tokenize(jsonText))
{
switch (currentState)
{
case ParserState.Begin:
switch (token.Type)
{
case TokenType.OpenBrace:
currentState = ParserState.ObjectKey;
current = result = new JsonObject();
break;
case TokenType.OpenBracket:
currentState = ParserState.ArrayValue;
current = result = new JsonArray();
break;
default:
invalidToken = true;
break;
}
break;
case ParserState.ObjectKey:
switch (token.Type)
{
case TokenType.StringLiteral:
currentState = ParserState.ColonSeperator;
key = (string)token.Value;
break;
default:
invalidToken = true;
break;
}
break;
case ParserState.ColonSeperator:
switch (token.Type)
{
case TokenType.Colon:
currentState = ParserState.ObjectValue;
break;
default:
invalidToken = true;
break;
}
break;
case ParserState.ObjectValue:
case ParserState.ArrayValue:
switch (token.Type)
{
case TokenType.NumberLiteral:
case TokenType.StringLiteral:
case TokenType.BooleanLiteral:
case TokenType.NullLiteral:
currentState = ParserState.ItemEnd;
value = token.Value;
break;
case TokenType.OpenBrace:
structureStack.Push(current);
keyStack.Push(key);
currentState = ParserState.ObjectKey;
current = new JsonObject();
break;
case TokenType.OpenBracket:
structureStack.Push(current);
currentState = ParserState.ArrayValue;
current = new JsonArray();
break;
default:
invalidToken = true;
break;
}
break;
case ParserState.ItemEnd:
var jsonObject = (current as JsonObject);
if (jsonObject != null)
{
jsonObject.Add(key, value);
currentState = ParserState.ObjectKey;
}
var jsonArray = (current as JsonArray);
if (jsonArray != null)
{
jsonArray.Add(value);
currentState = ParserState.ArrayValue;
}
switch (token.Type)
{
case TokenType.CloseBrace:
case TokenType.CloseBracket:
currentState = ParserState.End;
break;
case TokenType.Comma:
break;
default:
invalidToken = true;
break;
}
break;
case ParserState.End:
switch (token.Type)
{
case TokenType.CloseBrace:
case TokenType.CloseBracket:
case TokenType.Comma:
var previous = structureStack.Pop();
var previousJsonObject = (previous as JsonObject);
if (previousJsonObject != null)
{
currentState = ParserState.ObjectKey;
previousJsonObject.Add(keyStack.Pop(), current);
}
var previousJsonArray = (previous as JsonArray);
if (previousJsonArray != null)
{
currentState = ParserState.ArrayValue;
previousJsonArray.Add(current);
}
current = previous;
if (token.Type != TokenType.Comma)
{
currentState = ParserState.End;
}
break;
default:
invalidToken = true;
break;
}
break;
default:
break;
}
if (invalidToken)
{
if (throwException)
{
throw new JsonException(token);
}
return null;
}
}
return result;
}