स्केनरलेस पार्सिंग का "डेंग्लिंग एल्स प्रॉब्लम" से क्या लेना-देना है?


13

मुझे यह वाक्य विकिंग एंगल समस्या पर विकिपीडिया लेख से समझ में नहीं आता है :

[द डंग्लिंग एल्स प्रॉब्लम] एक ऐसी समस्या है जो अक्सर कंपाइलर कंस्ट्रक्शन में सामने आती है, खासकर स्कैनरलेस पार्सिंग में।

क्या कोई मुझे समझा सकता है कि कैसे स्कैनर रहित पार्सिंग तकनीक इस समस्या को बढ़ा सकती है? यह मुझे लगता है कि समस्या व्याकरण के साथ है - चूंकि यह अस्पष्ट है - पार्सिंग तकनीक के विकल्प के साथ नहीं। मुझे किसकी याद आ रही है?


2
केवल एक चीज जो मैं सोच सकता हूं, वह यह है कि स्कैनर-कम पार्सर को अधिक जटिल व्याकरण की आवश्यकता होती है, जिससे अस्पष्टता को हल करने के लिए आंकड़े प्रदान करना अधिक कठिन हो जाता है।
जियोर्जियो

3
@ रोबर्ट हार्वे: मुद्दा यह है कि इस धारणा को वाक्यविन्यास पेड़ से परिलक्षित होना चाहिए। यदि एक व्याकरण स्ट्रिंग के लिए दो अलग-अलग वाक्यविन्यास पेड़ों को प्राप्त करने की अनुमति देता है if a then if b then s1 else s2, तो व्याकरण अस्पष्ट है।
जियोर्जियो

1
@RobertHarvey भाषाओं को परिभाषित करने का एक सामान्य तरीका संदर्भ-मुक्त व्याकरण का उपयोग कर रहा है, साथ ही नियमों का एक गुच्छा जो व्याकरण की अवहेलना करता है, यदि आवश्यक हो।

2
सभी स्कैनर रहित पार्सर समान नहीं बनाए गए। के लिए, कहते हैं, खूंटी या GLR, एक लटकाने वाला व्यवहार हमेशा पूर्वानुमान योग्य होता है।
SK- तर्क

1
[द डंग्लिंग एल्स प्रॉब्लम] का स्कैनरलेस पार्सिंग से कोई लेना-देना नहीं है। [डैंगलिंग एल्स समस्या] एलआर (नीचे ऊपर) पार्सर्स के शिफ्ट-कम संचालन से संबंधित है। AFAIK
ddur

जवाबों:


6

मेरा सबसे अच्छा अनुमान है कि विकिपीडिया लेख में वाक्य ई। विज़सर के काम की गलतफहमी के कारण है।

स्केनरलेस पर्सर्स के लिए व्याकरण (अर्थात किसी भाषा का वर्णन करने वाले व्याकरण वर्णों के अनुक्रमों के सेट के रूप में होते हैं, साथ ही टोकन के अनुक्रमों के समूह के रूप में अलग से वर्णित वर्णों के साथ टोकन होते हैं) में बहुत अधिक अस्पष्टता होती है। ई। विज़सर पेपर स्कैनररहित सामान्यीकृत एलआर पार्सर्स (*) के लिए विखंडन फ़िल्टर , अस्पष्टता को हल करने के लिए कई तंत्र प्रस्तावित करता है, जिनमें से एक झूलने वाली समस्या को हल करने के लिए उपयोगी है। लेकिन कागज यह नहीं बताता है कि "लटकती हुई समस्या" नाम की सटीक अस्पष्टता स्केनरलेस पार्सर्स से संबंधित है (न ही यह भी कि तंत्र विशेष रूप से स्केनरलेस पार्सर्स के लिए उपयोगी है)।

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


(*) जो शायद स्कैनर रहित पार्सर्स पर विकिपीडिया लेख के आधार के रूप में सेवारत है, भले ही वे एक दूसरे का संदर्भ देते हों, ई। विसेर , स्कैनररहित सामान्यीकृत-एलआर पार्सिंग द्वारा भी ।


13

बस समस्या को बताने के लिए, डेंग्लिंग एल्स प्रॉब्लम कोड सिंटैक्स स्पेसिफिकेशन में एक अस्पष्टता है जहां यह अगले इफ़्स और इलसेस के मामलों में अस्पष्ट हो सकता है, जो अन्य के अंतर्गत आता है।

सबसे सरल और क्लासिक उदाहरण:

if(conditionA)
if(conditionB)
   doFoo();
else
   doBar();

यह जो लोग जो दिल से भाषा विनिर्देश, की बारीकियों पता नहीं है करने के लिए स्पष्ट नहीं है, ifहो जाता है else(और इस विशेष कोड का टुकड़ा आधा दर्जन भाषाओं में मान्य है, लेकिन प्रत्येक में अलग ढंग से प्रदर्शन कर सकते हैं)।

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

विराम चिह्न के पहले या बाद में नई कहानियों और व्हाट्सएप को निरर्थक मान लेना (जैसा कि वे अधिकांश सी-शैली भाषाओं में हैं), यह कथन संकलक के रूप में प्रकट होगा:

if(conditionA)if(conditionB)doFoo();else doBar;

पूरी तरह से एक कंप्यूटर के लिए सक्षम है, तो चलो देखते हैं। मेरे पास एक समय में एक ही चरित्र मिलता है:

if(conditionA)

ओह, मुझे पता है कि इसका क्या मतलब है (सी # में), इसका मतलब है " pusheval स्टैक पर कंडीशन और फिर brfalseअगले अर्धविराम के बाद बयान में कूदने के लिए कॉल करें यदि यह सच नहीं है"। अभी मुझे अर्धविराम नहीं दिखाई देता है, इसलिए अभी के लिए मैं इस निर्देश के बाद अपनी छलांग ऑफ़सेट अगले स्थान पर लगाऊंगा, और जब तक मैं एक अर्धविराम नहीं देखता तब तक मैं उतनी ही वृद्धि करूँगा जितना कि मैं और निर्देश डालता हूँ। जारी रखने के लिए ...

if(conditionB)

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

doFoo();

ठीक है, यह आसान है। वह " calldoFoo" है। और क्या वह अर्धविराम है जो मैं देख रहा हूं? खैर, यह बहुत अच्छा है, यह पंक्ति का अंत है। मैं इन दोनों आदेशों की लंबाई से अपने दोनों ब्लॉकों के कूदने की संख्या बढ़ाता हूँ और भूल जाता हूँ कि मैंने कभी परवाह की है। ठीक है, आगे बढ़ रहे हैं ...

else

... उह ओह। यह उतना सरल नहीं है जितना कि यह दिखता है। ठीक है, मैं भूल गया था कि मैं क्या कर रहा था, लेकिन elseइसका मतलब है कि कहीं न कहीं एक सशर्त विराम कथन है जो मैंने पहले ही देखा है, इसलिए मुझे वापस देखने दें ... हां, यह है brfalse, ठीक है, जब मैं कुछ "कंडीशनबी" पर धक्का देता हूं ढेर, जो कुछ भी था। ठीक है, अब मुझे breakअगले बयान के रूप में बिना शर्त की आवश्यकता है । उसके बाद जो बयान आएगा, वह निश्चित रूप से मेरे सशर्त विराम का लक्ष्य है, इसलिए मैं यह सुनिश्चित करूंगा कि मेरे पास यह सही है, और मैं बिना शर्त विराम को बढ़ाऊंगा जो मैं आगे बढ़ रहा हूं ...

doBar();

यह आसान है। " callदोबार"। और एक अर्धविराम है, और मैंने कभी कोई ब्रेसिज़ नहीं देखा। इसलिए, बिना शर्त breakअगले बयान पर कूदना चाहिए, चाहे वह कुछ भी हो, और मैं भूल सकता हूं कि मैंने कभी परवाह की।


तो, हमारे पास क्या है ... (ध्यान दें: यह 10:00 बजे है और मुझे ऐसा महसूस नहीं होता है कि बिट ऑफ़सेट को हेक्साडेसिमल में बदल दिया जाए या इन कमांड के साथ फंक्शन का पूरा IL शेल खोल दिया जाए, इसलिए यह सिर्फ छद्म आईएल है। लाइन नंबर का उपयोग करना जहां सामान्य रूप से बाइट ऑफ़सेट होंगे):

ldarg.1 //conditionA
brfalse <line 6> //jumps to "break"
ldarg.2 //conditionB
brfalse <line 7> //jumps to "call doBar"
call doFoo
break <line 8> //jumps beyond statement in scope
call doBar
<line 8 is here>

ठीक है, यह वास्तव में सही ढंग से निष्पादित करता है, यदि नियम (अधिकांश सी-शैली भाषाओं में) यह है कि elseनिकटतम के साथ जाता है if। निष्पादन घोंसले का पालन करने के लिए प्रेरित, यह इस तरह से निष्पादित करेगा, जहां अगर स्थिति झूठी है, तो स्निपेट का पूरा शेष छोड़ दिया जाता है:

if(conditionA)
    if(conditionB)
       doFoo();
    else
       doBar();

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

इसके अलावा, अगर भाषा के विनिर्देश ने कहा कि एक झूलना elseपहले का है if, और यदि शर्त झूठी है तो doBar निष्पादित किया जाता है, जबकि अगर conditiona सही है, लेकिन conditionB नहीं है, तो ऐसा कुछ भी नहीं होता है?

if(conditionA)
    if(conditionB)
       doFoo();
else
   doBar();

पार्सर पहले ifमौजूद अस्तित्व को भूल गया था, और इसलिए यह सरल पार्सर एल्गोरिदम सही कोड का उत्पादन नहीं करेगा, कुशल कोड के बारे में कुछ भी कहने के लिए नहीं।

अब, पार्सर उस समय को याद रखने के लिए काफी स्मार्ट हो सकता है ifऔर elseउसके पास अधिक समय के लिए है, लेकिन अगर भाषा की युक्ति पहले elseदो ifमैचों के बाद एक एकल कहती है if, तो इससे ifमेल खाने वाले elses के साथ दो s की समस्या होती है :

if(conditionA)
    if(conditionB)
       doFoo();
    else
       doBar();
else
    doBaz();

पार्सर पहले को देखेगा, पहले elseको मैच करेगा if, फिर दूसरे को देखेगा और घबराहट में जाएगा "मैं फिर से क्या कर रहा था" मोड। इस बिंदु पर पार्सर को एक उत्परिवर्ती राज्य में बहुत अधिक कोड मिला है, लेकिन यह बहुत पहले से ही आउटपुट फाइल करने के लिए बाहर धकेल दिया है।

इन सभी समस्याओं के समाधान और क्या-क्या हैं। लेकिन, या तो कोड की आवश्यकता है कि स्मार्ट पार्सर एल्गोरिथ्म की जटिलता को बढ़ाता है, या भाषा युक्ति पार्सर को इस गूंगा होने की अनुमति देता है, भाषा स्रोत कोड की वर्बोसिटी बढ़ाता है, जैसे कि समाप्त होने वाले बयानों की आवश्यकता होती है end if, या ब्रैकेट्स नेस्टेड का संकेत देते हैं। यदि ifकथन में ब्लॉक है else(दोनों जिनमें से आमतौर पर अन्य भाषा शैलियों में देखा जाता है)।

यह सिर्फ एक-दो का सरल उदाहरण है if, और उन सभी निर्णयों पर गौर करें जिन्हें कंपाइलर को करना था, और जहां यह बहुत आसानी से गड़बड़ कर सकता था। यह आपके प्रश्न में विकिपीडिया के उस सहज कथन के पीछे का विवरण है।


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

3
प्रतिक्रिया के लिए धन्यवाद, लेकिन यह वास्तव में ओपी को संबोधित नहीं करता है। मैं इस पोस्ट में मान्यताओं से सहमत नहीं हूं कि एक स्कैनर रहित पार्सर का लक्ष्य क्या है और इसे कैसे लागू किया जाता है। स्कैनर रहित पार्सर को लागू करने के कई तरीके हैं और यह पोस्ट केवल एक सीमित उपसमूह के साथ सौदा करती है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.