परिमित स्थिति ऑटोमेटा में बैकरेफर, लुकहेड और लुकबाइंड का अनुकरण कैसे करें?


26

मैंने नियमित अभिव्यक्ति लेने और इसके पार्स ट्री को उत्पन्न करने के लिए एक साधारण नियमित अभिव्यक्ति लेक्सर और पार्सर बनाया। इस पेरेस ट्री से एक गैर-नियतात्मक परिमित राज्य ऑटोमेटन बनाना बुनियादी नियमित अभिव्यक्तियों के लिए अपेक्षाकृत सरल है। हालाँकि मैं अपने सिर को चारों ओर लपेटने के लिए नहीं देख सकता कि कैसे बैकरेफरेंस, लुकहेड और लुकहाइंड को अनुकरण करना है।

बैंगनी ड्रैगन पुस्तक में मैंने जो कुछ भी पढ़ा, उससे मैं समझ गया कि एक लुकहेड का अनुकरण करने के लिए जहां नियमित अभिव्यक्ति r का मिलान किया जाता है, यदि और उसके बाद ही मैच को नियमित अभिव्यक्ति s के मिलान के बाद किया जाता है , तो आप एक गैर-नियतात्मक परिमित बनाते हैं जिसमें राज्य automaton / ने ले ली है ε । क्या यह एक निर्धारक परिमित राज्य ऑटोमेटन बनाना संभव है जो समान करता है?r/srs/ε

नकारात्मक लुकहैड और लुकहाइंड के अनुकरण के बारे में क्या? मैं वास्तव में इसकी सराहना करूंगा यदि आप मुझे एक संसाधन से जोड़ेंगे जो यह बताता है कि यह कैसे करना है।



जवाबों:


21

([ab]^*)\1{www{a,b}}

आगे-आगे देखने और देखने के लिए परिमित ऑटोमेटा की दुनिया में कुछ भी खास नहीं है क्योंकि हम यहां केवल पूरे इनपुट से मेल खाते हैं। इसलिए, "बस जाँच करें लेकिन उपभोग नहीं करते" का विशेष अर्थ व्यर्थ है; आप बस जाँच और / या अभिव्यक्ति की जाँच और अभिव्यक्ति का उपयोग और जिसके परिणामस्वरूप automata का उपयोग करें। विचार यह है कि जब आप इनपुट का "उपभोग" करते हैं और परिणाम को एक स्थिति में संग्रहीत करते हैं, तो लुक-फ़ॉर या लुक-बैक एक्सप्रेशंस की जाँच करें।

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

/(?=c)[ab]+/{a,b,c}{a,b,c}c{a,b}+{a,b,c}

यहाँ छवि विवरण दर्ज करें
[ स्रोत ]

और आपको करना होगा

  • iq2q2
  • i1q2

ध्यान दें कि ऑटोमेटन का बायां हिस्सा क्रमशः [abc]*और c(पुनरावृत्त) के लिए कैनोनिकल ऑटोमेटा के समानांतर ऑटोमेटन कैसे होता है।

ijij

ध्यान दें कि गैर-नियतात्मकता इस के लिए अंतर्निहित है: मुख्य और लुक-फॉरवर्ड / -बाइंड ऑटोमैटन ओवरलैप हो सकता है, इसलिए आपको बाद वाले या बैकट्रैक की रिपोर्ट करने के लिए उनके बीच सभी संक्रमणों को संग्रहीत करना होगा।


11

रेगेक्स इंजन को लागू करने के पीछे व्यावहारिक मुद्दों पर आधिकारिक संदर्भ, रस कॉक्स द्वारा तीन ब्लॉग पोस्ट की एक श्रृंखला है । जैसा कि वहां वर्णित है, चूंकि बैकरेफ्रेंस आपकी भाषा को गैर-नियमित बनाते हैं, इसलिए उन्हें बैकट्रैकिंग का उपयोग करके लागू किया जाता है ।

रेगाक्स पैटर्न के कई फीचर्स जैसे लुकहेड्स और लुकबाइंड्स, मैचिंग इंजन के कई फीचर्स की तरह, यह तय करने के प्रतिमान में एकदम फिट नहीं बैठते हैं कि स्ट्रिंग एक भाषा का सदस्य है या नहीं। Regexes के बजाय हम आमतौर पर एक बड़े स्ट्रिंग के भीतर सबस्ट्रिंग की खोज कर रहे हैं। "माचिस" वे सबस्ट्रिंग हैं जो भाषा के सदस्य हैं, और वापसी मूल्य बड़े स्ट्रिंग के भीतर प्रतिस्थापन के शुरुआती और अंत बिंदु हैं।

लुकहैड्स और लुकबाइंड्स का बिंदु गैर-नियमित भाषाओं से मेल खाने की क्षमता का परिचय देने के लिए इतना नहीं है, बल्कि समायोजित करने के लिए जहां इंजन मिलान किए गए प्रतिस्थापन की शुरुआत और अंत बिंदुओं की रिपोर्ट करता है।

मैं http://www . अनियमित-expressions.info/lookaround.html पर विवरण पर भरोसा कर रहा हूं । रेगेक्स इंजन जो इस सुविधा का समर्थन करते हैं (पर्ल, टीसीएल, पायथन, रूबी, ...) सभी बैकट्रैकिंग पर आधारित प्रतीत होते हैं (यानी, वे केवल नियमित भाषाओं की तुलना में भाषाओं के बहुत बड़े सेट का समर्थन करते हैं)। वे इस विशेषता को कार्य करने के लिए वास्तविक परिमित ऑटोमेटा के निर्माण की कोशिश करने के बजाय, बैकट्रैकिंग के एक अपेक्षाकृत "सरल" विस्तार के रूप में लागू कर रहे हैं।

पॉजिटिव लुकहेड

वाक्य विन्यास को सकारात्मक अग्रदर्शी है (?=regex) । इसलिए उदाहरण के लिए केवल तभी q(?=u)मिलान qकिया जाता है u, जब उसका अनुसरण किया जाता है , लेकिन मेल नहीं खाता u। मुझे लगता है कि वे इसे बैकग्राउंडिंग में बदलाव के साथ लागू करते हैं। सकारात्मक लुकहेड से पहले अभिव्यक्ति के लिए एक एफएसएम बनाएं। जब यह मैच याद आता है कि यह कहां समाप्त हुआ और एक नया FSM शुरू किया जो सकारात्मक रूपांतर के अंदर अभिव्यक्ति का प्रतिनिधित्व करता है। यदि वह मैच तब आपके पास "मैच" है, लेकिन पॉजिटिव लुकहेड मैच शुरू होने से ठीक पहले मैच "समाप्त" होता है।

इसका केवल एक ही हिस्सा है जो बिना बैकग्रांउड के कठिन होगा, आपको इनपुट में उस बिंदु को याद रखने की आवश्यकता है, जहाँ लुकहेड शुरू होता है और मैच के बाद आपके इनपुट टेप को वापस इस स्थिति में ले जाता है।

नकारात्मक लुकहेड

वाक्य विन्यास को नकारात्मक अग्रदर्शी है (?!regex) । उदाहरण के लिए केवल तभी q(?!u)मेल खाता है qजब तक कि उसका पालन न किया जाए u। यह या तो qकिसी अन्य चरित्र द्वारा पीछा किया जा सकता है , या qस्ट्रिंग के बहुत अंत में हो सकता है। मुझे लगता है कि यह लुकहेड अभिव्यक्ति के लिए एक एनएफए बनाकर लागू किया गया है, फिर केवल तभी सफल होगा जब एनएफए बाद के स्ट्रिंग से मेल न खाए।

यदि आप इसे बैकट्रैकिंग पर भरोसा किए बिना करना चाहते हैं तो आप लुकहेड अभिव्यक्ति के एनएफए को नकार सकते हैं, तो इसे उसी तरह से व्यवहार करें जैसे आप सकारात्मक लुकहेड का इलाज करते हैं।

सकारात्मक नजरिया

(?<=)(?=q)uuqqnnn

आप देख रेख ऑपरेटर से पहले आता है कि रेगेक्स के कुछ हिस्से के साथ "स्ट्रिंग जो regex के साथ समाप्त होता है" का चौराहा लेने के बिना इसे लागू करने में सक्षम हो सकता है । यह मुश्किल है, हालांकि हो सकता है क्योंकि lookbehind जा रहा है regex इनपुट की वर्तमान शुरुआत से आगे वापस देखने की जरूरत हो सकती है।

नकारात्मक लग रहा है

वाक्य विन्यास को नकारात्मक lookbehind है (?<!regex) । इसलिए, उदाहरण के लिए, (?<!q)uमेल खाता है u, लेकिन केवल अगर यह पहले से नहीं है q। तो यह मेल खाएंगे uमें umbrellaऔर uमें doubt, लेकिन नहीं uमें quick। फिर से, यह regex की लंबाई की गणना करके किया गया लगता है , जो कि कई पात्रों का समर्थन करता है, regex के साथ मैच के लिए परीक्षण कर रहा है , लेकिन अब पूरा मैच विफल हो जाता है यदि लुकअप मैच होता है।

आप का निषेध लेने से उलटे पांव लौटने के बिना इस लागू करने के लिए सक्षम हो सकता है regex और फिर उसी कर के रूप में आप सकारात्मक lookbehind के लिए करना होगा।


5

कम से कम बैकरेफरेंस के लिए, यह संभव नहीं है। उदाहरण के लिए, रेगेक्स (.*)\1एक ऐसी भाषा का प्रतिनिधित्व करता है जो नियमित नहीं है। इसका मतलब यह है कि एक परिमित ऑटोमोटन (निर्धारक या नहीं) बनाना असंभव है जो इस भाषा को पहचान सके। यदि आप इसे औपचारिक रूप से सिद्ध करना चाहते हैं, तो आप पंपिंग लेम्मा का उपयोग कर सकते हैं ।


4

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

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

Backreferences हैं, जैसा कि दूसरों ने उल्लेख किया है, नियमित नहीं है, इसलिए उन्हें एक परिमित ऑटोमेटन द्वारा लागू नहीं किया जा सकता है। वास्तव में, वे एनपी-पूर्ण हैं। जिस कार्यान्वयन में मैं काम कर रहा हूं, त्वरित हाँ / नहीं मिलान सर्वोपरि है, इसलिए मैंने बैकरेफ़रेंस को बिल्कुल लागू नहीं करने के लिए चुना।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.