2012-09-17 10 views
6

आगामी प्रोजेक्ट के हिस्से के रूप में, मैं इसे सेट अप करना चाहता हूं ताकि एक निश्चित डोमेन ऑब्जेक्ट टैग या टैग के संयोजन पर लागू हो सके। > लागू होता है -मानव-दर्ज लॉजिकल गुणों का विश्लेषण कैसे करें, उदा। यह और (वह या दूसरा)?

  • टैग-एक और (टैग-ख या टैग-ग):

    मैं उन एक मानव पठनीय रास्ते में इन संयोजनों, के समान प्रवेश करने में सक्षम होना चाहते हैं टैग-ए + टैग-बी या टैग-ए + टैग-सी

  • टैग-डी या (टैग-ई और टैग-एफ) -> टैग-डी या टैग-ई + टैग-एफ
  • पर लागू होता है

क्या टूल-सेट इस प्रकार के तर्क पार्सिंग को दर्ज टेक्स्ट की एक स्ट्रिंग से करने के लिए मौजूद है? मैं दृश्यों के पीछे टैग को एक निश्चित भेद ({}, [], आदि) के साथ परिभाषित कर सकता हूं ताकि उन्हें और आसानी से पार्स किया जा सके।

बस सोच रहा है कि प्रत्येक विशिष्ट संयोजन में प्रवेश किए बिना संयोजन के उन विशिष्ट सेटों में मानव-पठनीय पाठ को पार्स करने का सबसे अच्छा तरीका क्या है।

धन्यवाद! lexing और को पार्स (शाब्दिक विश्लेषण का संक्षिप्त रूप):

उत्तर

7

आमतौर पर यह दो चरण होते हैं।

पहले चरण में, इनपुट स्ट्रिंग को टोकन नामक लेक्सिकल आइटमों के अनुक्रम में परिवर्तित किया गया है। इस उद्देश्य के लिए, आप टोकन के विभिन्न प्रकार के लिए एक enum प्रकार की घोषणा हो सकती है जैसे:

public enum TokenType 
{ 
    OpenParenthesis, 
    CloseParenthesis, 
    And, 
    Or, 
    Tag 
} 

और टोकन के लिए एक वर्ग:

sealed class Token 
{ 
    public TokenType Type { get; private set; } 
    public string Item { get; private set; } 
    public Token(TokenType type, string item) { Type = type; Item = item; } 
} 

अब आप एक एल्गोरिथ्म है कि इनपुट स्ट्रिंग बदल जाता है लिखते हैं, जैसे , Token उदाहरणों के अनुक्रम में। आप विभिन्न वस्तुओं को पहचानने के लिए नियमित अभिव्यक्तियों का उपयोग कर सकते हैं, उदाहरण के लिए @"\s*\(\s*" खुले-कोष्ठक को पहचानने के लिए नियमित अभिव्यक्ति होगी। समाप्त अनुक्रम तो कुछ इस तरह दिखेगा:

  • new Token(TokenType.Tag, "tag-a")
  • new Token(TokenType.And, null)
  • new Token(TokenType.OpenParenthesis, null)
  • new Token(TokenType.Tag, "tag-b")
  • new Token(TokenType.Or, null)
  • new Token(TokenType.Tag, "tag-c")
  • new Token(TokenType.CloseParenthesis, null)

एक बार आपके पास यह अनुक्रम होने के बाद, आपको पार्सर चलाने की आवश्यकता है। इन तरह अभिव्यक्तियों को पार्स करने के लिए कई रणनीतियां हैं; शुरुआत के लिए, मैं आपको recursive descent parser की सलाह देता हूं।

आप, ज़ाहिर है, कुछ वर्गों की आवश्यकता होगी पार्स पेड़ को रोकने के लिए:

abstract class Node { } 
enum BooleanOperator { And, Or } 
sealed class BooleanNode : Node 
{ 
    public BooleanOperator Operator { get; private set; } 
    public Node Left { get; private set; } 
    public Node Right { get; private set; } 
    public BooleanNode(BooleanOperator op, Node left, Node right) 
    { 
     Operator = op; 
     Left = left; 
     Right = right; 
    } 
} 
sealed class TagNode : Node 
{ 
    public string Tag { get; private set; } 
    public TagNode(string tag) { Tag = tag; } 
} 

और फिर एक पुनरावर्ती वंश पार्सर कुछ इस तरह दिख सकता है:

public static Node ParseExpression(Token[] tok) 
{ 
    int i = 0; 
    return parseExpressionBoolOr(tok, ref i); 
} 
private static Node parseExpressionBoolOr(Token[] tok, ref int i) 
{ 
    var left = parseExpressionBoolAnd(tok, ref i); 
    while (tok[i].Type == TokenType.Or) 
    { 
     i++; 
     var right = parseExpressionBoolAnd(tok, ref i); 
     left = new BooleanNode(BooleanOperator.Or, left, right); 
    } 
    return left; 
} 
private static Node parseExpressionBoolAnd(Token[] tok, ref int i) 
{ 
    var left = parseExpressionPrimary(tok, ref i); 
    while (tok[i].Type == TokenType.And) 
    { 
     i++; 
     var right = parseExpressionPrimary(tok, ref i); 
     left = new BooleanNode(BooleanOperator.And, left, right); 
    } 
    return left; 
} 
private static Node parseExpressionPrimary(Token[] tok, ref int i) 
{ 
    if (tok[i].Type == TokenType.OpenParenthesis) 
    { 
     i++; 
     var node = parseExpressionBoolOr(tok, ref i); 
     if (tok[i].Type != TokenType.CloseParenthesis) 
      throw new InvalidOperationException(); // or customised parse exception 
     return node; 
    } 
    else if (tok[i].Type == TokenType.Tag) 
    { 
     var node = new TagNode(tok[i].Item); 
     i++; 
     return node; 
    } 
    else 
     throw new InvalidOperationException(); // or customised parse exception 
} 

ध्यान दें कि यह है एक बहुत ही सरल उदाहरण। हालांकि, यह अधिकतम लचीला है: आप इस एल्गोरिदम को पूरी तरह से किसी भी भाषा को पार्स करने के लिए बढ़ा सकते हैं।

+0

यह एक शानदार और विस्तृत उदाहरण है, और मुझे अवधारणाओं और कोड दोनों के साथ कई अलग-अलग तरीकों से एक बड़ा सौदा सिखाया। इस मणि के लिए धन्यवाद! – SeanKilleen

+0

[खुशी:)] (http://meta.stackexchange.com/questions/700) – Timwi

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