2010-04-16 6 views
9

क्या यह कोड भी उच्च स्तर के अमूर्तकरण के लायक होने के लिए पर्याप्त जटिल है?मैं इसे अधिक प्रबंधनीय कोड में कैसे पुन: सक्रिय कर सकता हूं?

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; 
} 
+1

आप अपने स्वयं के JSON पार्सर क्यों लिखेंगे जब पहले से ही बहुत सारे अच्छे विकल्प हैं? –

+3

@Hightechrider - मैं अपने पीसी का निर्माण क्यों करूं जब मैं स्टोर में पूरी तरह से अच्छा खरीद सकता हूं? क्योंकि यह एक मजेदार और शैक्षणिक अनुभव है। – ChaosPandion

उत्तर

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

मैं एकल-विधि इंटरफेस के बजाय, इस मामले में प्रतिनिधियों को पसंद करता हूं। – Dykam

+0

@Dykam: हो सकता है लेकिन इंटरफेस और कक्षाओं के साथ आप अलग-अलग फ़ाइलों में कोड को अलग कर सकते हैं जो तार्किक रूप से अलग हैं। और ओपी को अन्य तरीकों की आवश्यकता हो सकती है, मैं केवल यह दिखाने के लिए एक उदाहरण दे रहा था कि मेरा क्या मतलब था। मुझे कल्पना है कि वास्तविक कार्यान्वयन में चीजों को बदलने की आवश्यकता हो सकती है ... –

+0

मैं अभी भी अन्य राय प्राप्त करने की उम्मीद कर रहा हूं लेकिन राज्य पैटर्न निश्चित रूप से एक सुरुचिपूर्ण विकल्प है। – ChaosPandion

2

'संकल्पनात्मक डिजाइन' इस मामले में उत्पादन नियम है। यदि आप स्वयं को जेसन डिजाइन करना चाहते थे, तो क्या आप सोचेंगे कि "एक जोड़ी एक कुंजी है जिसके बाद एक कोलन एक मूल्य के बाद होता है" या आप इस मामले में "कॉलन करेंगे 'ए' जैसे शब्दों में सोचेंगे 'ए' 'बी' के मामले में 'बी' करें और 'सी' के मामले में 'सी' करें? 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 
+0

कृपया बताएं कि * इस मामले में "डिजाइन 'उत्पादन नियम है।" * मतलब है। – ChaosPandion

+0

मैं बिल्कुल नहीं कहूंगा कि मेरे कोड में डिज़ाइन की कमी है। यह एक परिमित राज्य मशीन है। यह ओओ सिद्धांतों का पालन नहीं कर सकता है, लेकिन यदि आप राज्यों का पालन करते हैं तो आप पाएंगे कि यह वास्तव में बहुत अच्छा है। हालांकि मैं आपके विचार की तरह करता हूँ। – ChaosPandion

+0

हाँ, अच्छा विचार। –

संबंधित मुद्दे

 संबंधित मुद्दे