2010-09-29 17 views
6

मैं यह समझने की कोशिश कर रहा हूं कि इस प्रारूप में स्ट्रिंग को मनमाने ढंग से गहराई की डेटा संरचना जैसे पेड़ में कैसे पार्स करना है।एक पेड़ संरचना में पार्स स्ट्रिंग?

"{{Hello big|Hi|Hey} {world|earth}|{Goodbye|farewell} {planet|rock|globe{.|!}}}" 

[[["Hello big" "Hi" "Hey"] 
    ["world" "earth"]] 
[["Goodbye" "farewell"] 
    ["planet" "rock" "globe" ["." 
          "!"]]]] 

मैं कुछ नियमित इस के लिए अभिव्यक्ति के साथ खेल की कोशिश की है (# जैसा "{([^ {}] *)}"), लेकिन सब कुछ मैं कोशिश की है में पेड़ "समतल" लगता है सूचियों की एक बड़ी सूची। मैं गलत कोण से यह आ रहा था, या शायद एक regex सिर्फ नौकरी के लिए सही उपकरण नहीं है।

आपकी मदद के लिए धन्यवाद!

उत्तर

9

इस कार्य के लिए नियमित अभिव्यक्तियों का उपयोग न करें। एक व्याकरण (बीएनएफ या ईबीएनएफ) के साथ अपनी स्ट्रिंग का वर्णन करने के लिए एक आसान तरीका होगा और फिर व्याकरण के अनुसार स्ट्रिंग को पार्स करने के लिए एक पार्सर लिखें। आप अपने ईबीएनएफ और बीएनएफ से एक पार्स-पेड़ उत्पन्न कर सकते हैं और इसलिए आप स्वाभाविक रूप से पेड़ की संरचना के साथ समाप्त हो जाते हैं।

आप कुछ इस तरह के साथ शुरू कर सकते हैं:

element  ::= element-type, { ["|"], element-type } 
element-type ::= primitive | "{", element, "}" 
primitive ::= symbol | word 
symbol  ::= "." | "!" 
word   ::= character { character } 
character ::= "a" | "b" | ... | "z" 

नोट: मैं इस जल्दी में लिखा है, और इसलिए यह पूरी तरह से सही नहीं हो सकता। लेकिन यह आपको एक विचार देना चाहिए।

+1

तो व्याकरण होने के बाद, इस व्याकरण के आधार पर पार्सर उत्पन्न करने के लिए एक पार्सर जनरेटर का उपयोग करना आवश्यक है, है ना? इसके अलावा, पार्सर को एक वाक्य के साथ खिलाया जाना चाहिए और फिर पेड़ पैदा किया जा सकता है, नहीं? – bikashg

+1

@ बिकैश - हां और नहीं। * यदि आप चाहें तो एक पार्सर जनरेटर (जैसे yacc या bison) का उपयोग कर सकते हैं, या आप अपना खुद का रिकर्सिव-वंश पार्सर लिख सकते हैं (यह उल्लेखनीय सरल है)। यदि आप yacc या bison का उपयोग करते हैं, तो आपको उन कार्यों को लिखने की आवश्यकता है जो वास्तव में पेड़ का निर्माण करेंगे। मुझे नहीं लगता कि yacc/bison आपको स्वयं पेड़ देता है। वे बस व्याकरण को पहचानते हैं। –

3

आप एक त्वरित हैक चाहते हैं:

  • {साथ वर्ण [
  • की जगह} की जगह
  • की जगह के साथ वर्ण] | रिक्त स्थान के साथ वर्ण
  • आशा है कि आप रिक्त स्थान के साथ इनपुट प्राप्त न करें।

read इसमें यह घोंसला वाले सरणी के रूप में आता है।

ps: मैं मानता हूं कि एक reg-ex यह नहीं कर सकता है।

पीएसएस: सेट * पढ़ने के लिए eval * गलत पर

+0

उनके उदाहरण स्ट्रिंग में वास्तव में सेगमेंट में से एक में एक स्थान शामिल है। – Rayne

+0

@ रेयने: इसे संपादित किया गया था। ओपी में परिणामी पत्ती के तारों में से कोई भी स्थान शामिल नहीं था। – aschepler

+0

ओह। जब तक मैंने अंतरिक्ष देखा, तब तक मैं इस समाधान पर भी विचार कर रहा था। तब मैंने खुद को सोने के लिए रोया। – Rayne

4

आप बहुत दूर पाने के लिए नहीं जा रहा है एक भी नियमित अभिव्यक्ति के साथ पूरी बात मिलान करने के लिए कोशिश कर रहा है (यदि आप यह है चल स्वयं इनपुट नहीं करना चाहती) , चूंकि मेलिंग सबस्ट्रिंग पोजिशन की अधिकांश सूची में नियमित अभिव्यक्ति आउटपुट, पेड़ की तरह कुछ नहीं। आप एक लेक्सर या व्याकरण चाहते हैं जो इस तरह कुछ करता है:

टोकन में इनपुट को विभाजित करें - '{', '|', और 'world' जैसे परमाणु टुकड़े, फिर क्रम में उन टोकन को संसाधित करें। एक रूट नोड के साथ एक खाली पेड़ के साथ शुरू करें।

हर बार जब आप { पाते हैं, तो बच्चे नोड बनाएं और जाएं।

हर बार जब आप | पाते हैं, तो एक भाई नोड बनाएं और जाएं।

हर बार जब आप } पाते हैं, तो पैरेंट नोड तक जाएं।

हर बार जब आप कोई शब्द पाते हैं, तो उस शब्द को वर्तमान पत्ता नोड में रखें।

+2

यह मामला '{{text} {text}}' कैसे संबोधित करता है? मुझे लगता है कि उसकी स्ट्रिंग अस्पष्ट है ... सभी भाई नोड्स को शायद "|" के साथ सीमित किया जाना चाहिए –

+0

हां, उदाहरण में कुछ भ्रमित बिंदु हैं। ऐसा लगता है कि हे और दुनिया के बीच '} {' और {} | {'पृथ्वी और अलविदा के बीच पेड़ में विभिन्न गहराइयों पर भाई-जैसे रिश्तों का कारण बनता है। मैं केवल अनुमान लगा सकता हूं कि यह क्यों है। (एक और समस्या मैंने अपने स्वयं के एल्गोरिदम के साथ नोट किया: क्या होगा यदि {शब्द 'के बाद सही है, जैसे' ग्लोब '?) तो यह एक पूर्ण समाधान नहीं है, लेकिन "कुछ ऐसा" है जिसे इस प्रकार के हल करने के लिए अनुकूल होना चाहिए मुसीबत। – aschepler

+0

यूप समझ में आता है :) –

1

आप amotoen का उपयोग व्याकरण का निर्माण कर सकते हैं और इस पार्स:

(ns pegg.core 
    (:gen-class) 
    (:use 
    (com.lithinos.amotoen 
    core string-wrapper)) 
    (:use clojure.contrib.pprint)) 

(def input "{{Hello big|Hi|Hey} {world|earth}|{Goodbye|farewell} {planet|rock|globe{.|!}}}") 

(def grammar 
    { 
     :Start :List 
     :ws #"^[ \n\r\t]*" 
     :Sep "|" 
     :String #"^[A-Za-z !.]+" 
     :Item '(| :String :List) 
     :Items [:Item '(+ [:Sep :Item])] 
     :List [:ws "{" '(* (| :Items :Item)) "}" :ws] 
     }) 

(def parser (create-parser grammar)) 

(defn parse 
    [^String input] 
    (validate grammar) 
    (pprint (parser (wrap-string input)))) 

परिणाम:

pegg.core> (parse input) 
{:List [{:ws ""} "{" ({:Item {:List [{:ws ""} "{" ({:Items [{:Item {:String "Hello big"}} ([{:Sep "|"} {:Item {:String "Hi"}}] [{:Sep "|"} {:Item {:String "Hey"}}])]}) "}" {:ws " "}]}} {:Items [{:Item {:List [{:ws ""} "{" ({:Items [{:Item {:String "world"}} ([{:Sep "|"} {:Item {:String "earth"}}])]}) "}" {:ws ""}]}} ([{:Sep "|"} {:Item {:List [{:ws ""} "{" ({:Items [{:Item {:String "Goodbye"}} ([{:Sep "|"} {:Item {:String "farewell"}}])]}) "}" {:ws " "}]}}])]} {:Item {:List [{:ws ""} "{" ({:Items [{:Item {:String "planet"}} ([{:Sep "|"} {:Item {:String "rock"}}] [{:Sep "|"} {:Item {:String "globe"}}])]} {:Item {:List [{:ws ""} "{" ({:Items [{:Item {:String "."}} ([{:Sep "|"} {:Item {:String "!"}}])]}) "}" {:ws ""}]}}) "}" {:ws ""}]}}) "}" {:ws ""}]} 

पी.एस. यह मेरा पहला पेग व्याकरण है और यह बेहतर हो सकता है। यह भी देखें http://en.wikipedia.org/wiki/Parsing_expression_grammar

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