शंटिंग-यार्ड एल्गोरिथ्म में फ़ंक्शन की प्राथमिकता


10

मैं शंटिंग-यार्ड एल्गोरिथ्म के माध्यम से काम कर रहा हूं , जैसा कि विकिपीडिया द्वारा वर्णित है।

ऑपरेटरों के साथ काम करते समय एल्गोरिथ्म का वर्णन निम्नानुसार है:

यदि टोकन एक ऑपरेटर है, ओ 1, तो:

जबकि ऑपरेटर स्टैक के शीर्ष पर एक ऑपरेटर टोकन, ओ 2 है, और या तो

o1 is left-associative and its precedence is less than or equal to
that of o2, or

o1 is right associative, and has precedence less than that of o2,

फिर आउटपुट कतार पर ऑपरेटर स्टैक से पॉप ओ 2;

ऑपरेटर स्टैक पर o1 पुश करें।

हालाँकि, वे निम्नलिखित उदाहरण देते हैं:

इनपुट: sin max 2 3 / 3 * 3.1415

जब एल्गोरिथ्म /टोकन को हिट करता है , तो जो होना चाहिए उसका विवरण निम्नानुसार है:

Token |        Action       |   Output (in RPN) |   Operator Stack
...
/     | Pop token to output | 2 3 max           | / sin 
...

वे फंक्शन टोकन को maxबंद कर रहे हैं stackऔर अंदर डाल रहे हैं queue। उनके एल्गोरिथ्म के अनुसार, इसका मतलब यह होगा कि फ़ंक्शन टोकन दोनों एक ऑपरेटर है, और ऑपरेटर की तुलना में एक पूर्वता कम है /

यह मामला है या नहीं, इस बारे में कोई स्पष्टीकरण नहीं है। तो, Shunting-yardएल्गोरिथ्म के लिए, एक कार्य की पूर्वता क्या है? क्या फ़ंक्शन सही या बाएं साहचर्य हैं? या विकिपीडिया सिर्फ अधूरा / गलत है?

जवाबों:


5

मेरा मानना ​​है कि प्रत्यक्ष उत्तर बस यह है कि फ़ंक्शन ऑपरेटर नहीं हैं। आपके द्वारा जुड़े पृष्ठ से:

यदि टोकन एक फ़ंक्शन टोकन है, तो इसे स्टैक पर धक्का दें।

यह सब कहने की जरूरत है, क्योंकि फ़ंक्शन केस (उपसर्ग के बाद के उपसर्ग) ऑपरेटर के मामले (इन्फिक्स से पोस्टफिक्स) की तुलना में बहुत सरल है।

अनुवर्ती प्रश्नों के लिए: पूर्वता और सहानुभूति की धारणाओं की आवश्यकता केवल इसलिए होती है क्योंकि कई infix ऑपरेटरों के साथ किसी भी अभिव्यक्ति में विरासत अस्पष्टता के कारण होती है। फ़ंक्शन टोकन पहले से ही उपसर्ग संकेतन का उपयोग कर रहे हैं, इसलिए वे बस उस समस्या नहीं है। आपको यह जानने की जरूरत नहीं है कि पहले मूल्यांकन करने की आवश्यकता है sinया maxनहीं "उच्च पूर्वता" max; यह टोकन के आदेश से पहले से ही स्पष्ट है। यही कारण है कि कंप्यूटर के साथ शुरू करने के लिए पूर्व / पोस्टफ़िक्स संकेतन पसंद करते हैं, और हमारे पास इस इंफ़िक्स को प्री / पोस्टफ़िक्स में कनवर्ट करने के लिए क्यों है।

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


उनका एल्गोरिथ्म सही है, फिर; यह उनका उदाहरण है जो गलत है। इनफिक्स नोटेशन में फ़ंक्शंस को लपेटते हुए कोष्ठक शामिल होना चाहिए:sin( max( 2 3) / 3 * 3.1415)
मिररफेड

मुझे यकीन नहीं है कि मैं इसे गलत कहूंगा, लेकिन यह उन भाषाओं के पक्ष में एक मजबूत तर्क है, जिन्हें सभी फ़ंक्शन कॉल के लिए कोष्ठक और अल्पविराम की आवश्यकता होती है।
Ixrec

मुझे लगता है कि यह गलत है क्योंकि एल्गोरिथ्म का उपयोग करके इन्फिक्स को पार्स करना असंभव है क्योंकि वे इसका वर्णन करते हैं।
मिररफाइंड

@Ixrec मैं लाइन नहीं देखता "यदि टोकन एक फ़ंक्शन टोकन है, तो इसे स्टैक पर धक्का दें।" विकिपीडिया पृष्ठ पर। अब तक इसका संपादन किया जा सकता है। लेकिन क्या आपका मतलब है कि मैं एल्गोरिथ्म में एक संख्या के रूप में एक फ़ंक्शन का इलाज कर सकता हूं?
अभिनव

मेरा मानना ​​है, विकिपीडिया लेख (आज तक) में एल्गोरिथम विवरण में एक त्रुटि है। वाक्यांश के बाद if there is a left parenthesis at the top of the operator stack, then: pop the operator from the operator stack and discard it, एक और पंक्ति को जोड़ा जाना चाहिए: यदि स्टैक के शीर्ष पर एक फ़ंक्शन नाम है, तो इसे स्टैक से पॉप करें और आउटपुट पर पुश करें । दूसरे शब्दों में, बाएं '(' को हमेशा फ़ंक्शन नाम के साथ पॉप किया जाना चाहिए, अगर उन्हें फ़ंक्शन सिंटैक्स के रूप में एक साथ रखा गया है: " name("।
स्टेन

3

आपकी भाषा सिंटैक्स के आधार पर, विचार करने के लिए दो अलग-अलग मामले हैं। यदि आपकी भाषा फ़ंक्शन एप्लिकेशन (जैसे f(2+1)) को इंगित करने के लिए कोष्ठक का उपयोग करती है तो पूर्वता अप्रासंगिक है। फ़ंक्शन को स्टैक पर धकेल दिया जाना चाहिए और इसके बाद पॉप आउट किया जाना चाहिए (उदाहरण के लिए ऊपर, परिणाम है 2 1 + f)। वैकल्पिक रूप से आप फ़ंक्शन को एक मान के रूप में मान सकते हैं और इसे तुरंत आउटपुट कर सकते हैं, और नजदीकी कोष्ठक (जो अन्यथा किसी अन्य कोष्ठक के समान माना जाना चाहिए) के बाद एक फ़ंक्शन मंगलाचरण का उत्पादन करता है, उदाहरण के लिए f 2 1 + $, जहां $फ़ंक्शन मंगलाचरण ऑपरेशन है।

यदि आपकी भाषा, हालांकि फ़ंक्शन इन्वोकेशन को इंगित करने के लिए कोष्ठक का उपयोग नहीं करती है, लेकिन इसके बजाय फ़ंक्शन को सीधे किसी विशेष विराम चिह्न (जैसे f 2 + 1) के बिना तर्क देता है , जैसा कि स्पष्ट रूप से विकिपीडिया के उदाहरण के लिए मामला है, तो चीजें थोड़ी अधिक जटिल हैं। ध्यान दें कि अभिव्यक्ति मैं बस दी, जैसा कि एक उदाहरण अस्पष्ट है: है 2 के लिए आवेदन किया और 1 परिणाम को जोड़ा गया है, या हम 2 और 1 एक साथ जोड़ने और फिर फोन कर परिणाम के साथ?

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

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

केवल एक चीज जिसे आपको तय करने की आवश्यकता है, वह है फ़ंक्शन फ़ंक्शन की पूर्वता। चुनाव आप पर निर्भर है, लेकिन मैंने जिस भाषा का इस्तेमाल किया है, वह इस तरह से काम करती है, यह भाषा में सबसे मजबूती से चलने वाला ऑपरेटर है, और सही सहयोगी रहा है। (हास्केल होने का एकमात्र दिलचस्प भिन्नता है, साथ ही साथ दृढ़ता से बाध्यकारी संस्करण का वर्णन करने के लिए, इसके प्रतीक का एक पर्याय भी है $जो भाषा में सबसे कमजोर बंधन ऑपरेटर है, अभिव्यक्ति f 2 + 1को 2 f $ 2 + 1से लागू करने और लागू करने की अनुमति देता है। बाकी सारी अभिव्यक्ति के लिए यह)


3

मैंने दीजकस्ट्रा की मूल सोच (पेज ६१० में अल्जोल ६० कंपाइलर पेपर, https://ir.cwi.nl/pub/9251 ) को पढ़ने के बाद "कार्यों को शंटिंग यार्ड" में लागू करने के लिए कहा , और मुझे एक मजबूत समाधान की आवश्यकता है, निम्नलिखित कार्य किया:

पार्स:

  • फ़ंक्शन डिस्क्रिप्टर को पुश करें
  • एक स्टार्ट-ऑफ-आर्ग्स लेफ्ट ब्रैकेट को पुश करें "" जैसे कि सब-डेफ़िशिएंसी कोष्ठक की शुरुआत।
  • इनपुट से एक "(" से ")" संतुलित तर्क सूची अनुक्रम पढ़ें
  • इसे आउटपुट टोकन स्ट्रीम पर पुश करें
  • "एंड-ऑफ-आर्ग्स राइट ब्रैकेट" को पुश करें "" जैसे उसका "क्षतिपूर्ति समापन ब्रैकेट"

Infix-to-postfix (शंटिंग यार्ड):

  • ऑपरेटर स्टैक की तरह, एक और स्टैक, फ़ंक्शन स्टैक जोड़ें
  • किसी फ़ंक्शन नाम को स्कैन करते समय, फ़ंक्शन जानकारी को फ़ंक्शन स्टैक पर धक्का दें
  • जब एंड-ऑफ-आर्ग्स दायां ब्रैकेट देखा जाता है, तो फ़ंक्शन स्टैक को आउटपुट में पॉप करें

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

उदाहरण "sqrt (3 ^ 2 + 4 ^ 2)" जैसे दिखते हैं, जो "3 2 ^ 4 2 ^ + sqrt" और अंततः "5" हो जाते हैं, जो कि प्रोग्राम को लगता है कि तर्क है। यह बिग्नम है, इसलिए "" द्विपद (64, 32) / जीसीडी (द्विपद (64, 32), द्विपद (63, 31)) "==> बड़ी चीजें ==>" 2 "मददगार है।" 123x6 ^ 789 " 40,173 अंक है और मेरे मैकबुकप्रो पर टाइमिंग "मूल्यांकन = 0.000390 सेकंड" दिखाता है, इतनी जल्दी।

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

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