这段代码是否足够复杂,值得更高级别的抽象?
public static JsonStructure Parse(string jsonText)
{
var result = default(JsonStructure);
var structureStack = new Stack<JsonStructure>();
var keyStack = new Stack<string>();
var current = default(JsonStructure);
var currentState = ParserState.Begin;
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.BeginObject:
currentState = ParserState.Name;
current = result = new JsonObject();
break;
case TokenType.BeginArray:
currentState = ParserState.Value;
current = result = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Name:
switch (token.Type)
{
case TokenType.String:
currentState = ParserState.NameSeparator;
key = (string)token.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.NameSeparator:
switch (token.Type)
{
case TokenType.NameSeparator:
currentState = ParserState.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Value:
switch (token.Type)
{
case TokenType.Number:
case TokenType.String:
case TokenType.True:
case TokenType.False:
case TokenType.Null:
currentState = ParserState.ValueSeparator;
value = token.Value;
break;
case TokenType.BeginObject:
structureStack.Push(current);
keyStack.Push(key);
currentState = ParserState.Name;
current = new JsonObject();
break;
case TokenType.BeginArray:
structureStack.Push(current);
currentState = ParserState.Value;
current = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.ValueSeparator:
var jsonObject = (current as JsonObject);
var jsonArray = (current as JsonArray);
if (jsonObject != null)
{
jsonObject.Add(key, value);
currentState = ParserState.Name;
}
if (jsonArray != null)
{
jsonArray.Add(value);
currentState = ParserState.Value;
}
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
currentState = ParserState.End;
break;
case TokenType.ValueSeparator:
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.End:
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
case TokenType.ValueSeparator:
var previous = structureStack.Pop();
var previousJsonObject = (previous as JsonObject);
var previousJsonArray = (previous as JsonArray);
if (previousJsonObject != null)
{
previousJsonObject.Add(keyStack.Pop(), current);
currentState = ParserState.Name;
}
if (previousJsonArray != null)
{
previousJsonArray.Add(current);
currentState = ParserState.Value;
}
if (token.Type != TokenType.ValueSeparator)
{
currentState = ParserState.End;
}
current = previous;
break;
default:
throw new JsonException(token, currentState);
}
break;
default:
break;
}
}
return result;
}
答案 0 :(得分:10)
在没有详细查看的情况下,当您基于状态进行解析时,是否可以使用state pattern将其拆分并根据状态解析单独类中的每个位?
这样的事情可能是一个开始,虽然这只是伪代码......
public interface IParserState
{
IParserState ParseToken (IToken token);
}
public class BeginState : IParserState
{
private readonly Stack<JsonStructure> m_structureStack;
private readonly Stack<String> m_keyStack;
public BeginState (Stack<JsonStructure> structureStack, Stack<String> keyStack)
{
m_structureStack = structureStack;
m_keyStack = keyStack;
}
public IParserState ParseToken(IToken token)
{
switch (token.Type)
{
case TokenType.OpenBrace:
return new ObjectKeyParserState(m_structureStack,m_keyStack);
case TokenType.OpenBracket:
return new ArrayValueParserState(m_structureStack, m_keyStack);
default:
throw new JsonException (token);
}
}
}
public class ObjectKeyParserState : IParserState
{
private readonly Stack<JsonStructure> m_structureStack;
private readonly Stack<String> m_keyStack;
private readonly JsonObject m_current;
public ObjectKeyParserState (Stack<JsonStructure> structureStack, Stack<String> keyStack)
{
m_current = new JsonObject();
}
public IParserState ParseToken (IToken token)
{
switch (token.Type)
{
case TokenType.StringLiteral:
key = (string)token.Value;
return new ColonSeperatorParserState(m_structureStack, m_keyStack, m_current,key);
default:
throw new JsonException(token);
}
}
答案 1 :(得分:2)
在这种情况下,“概念设计”是生产规则。如果你自己设计json,你会想到“一对是一个关键后跟一个冒号然后是一个值”或者你会想像“Colons会做'a'在这种情况下'A'和在'B'的情况下做'b',在'C'的情况下做'c'“?看看http://www.json.org/。您将看到根据生产规则陈述的“概念设计”。
由于代码的“结构设计”不具有“概念设计”的形式,因此任何重构都不会有所帮助。稍微改变“概念设计”会导致难以编码且难以测试的代码更改。您需要根据“概念设计”重写代码。
// object
// "{" "}"
// "{" members "}"
private static JsonObject ProduceJsonObject(Tokens tokens)
{
var result = new JsonObject();
tokens.Accept( TokenType.OpenBrace );
result.members = ProduceJsonMembers(tokens);
tokens.Accept( TokenType.CloseBrace );
return result;
}
// members
// pair
// pair { "," pair }
private static JsonMembers ProduceJsonMembers(Tokens tokens)
{
var result = new JsonMembers();
result.Add( ProduceJsonPair(tokens) );
while (tokens.LookAhead == TokenTag.Comma)
{
tokens.Accept( TokenType.Comma );
result.Add( ProduceJsonPair(tokens) );
}
return result;
}
//pair
// string ":" value
private static JsonPair ProduceJsonPair(Tokens tokens)
{
var result = new JsonPair();
result.String = tokens.Accept( TokenType.ID );
tokens.Accept( TokenType.Colon );
result.Value = ProduceJsonValue( tokens );
return result;
}
// and so forth