वन-पास कंपाइलर: Difference between revisions
(Created page with "{{Original research|date=January 2017}} कंप्यूटर प्रोग्रामिंग में, वन-पास संकलक एक कंपा...") |
No edit summary |
||
Line 1: | Line 1: | ||
[[कंप्यूटर प्रोग्रामिंग]] में, वन-पास [[ संकलक |संकलक]] एक कंपाइलर होता है जो प्रत्येक [[संकलन इकाई]] के हिस्सों से केवल एक बार गुजरता है, तुरंत प्रत्येक भाग को उसके अंतिम मशीन कोड में अनुवादित करता है। यह एक [[मल्टी-पास कंपाइलर]] के विपरीत है जो प्रोग्राम को स्रोत कोड और मशीन कोड के बीच चरणों में एक या अधिक [[मध्यवर्ती भाषा]]ओं में परिवर्तित करता है, और जो प्रत्येक अनुक्रमिक पास में संपूर्ण संकलन इकाई को पुन: संसाधित करता है। | |||
[[कंप्यूटर प्रोग्रामिंग]] में, वन-पास [[ संकलक ]] एक कंपाइलर होता है जो प्रत्येक [[संकलन इकाई]] के हिस्सों से केवल एक बार गुजरता है, तुरंत प्रत्येक भाग को उसके अंतिम मशीन कोड में अनुवादित करता है। यह एक [[मल्टी-पास कंपाइलर]] के विपरीत है जो प्रोग्राम को स्रोत कोड और मशीन कोड के बीच चरणों में एक या अधिक [[मध्यवर्ती भाषा]]ओं में परिवर्तित करता है, और जो प्रत्येक अनुक्रमिक पास में संपूर्ण संकलन इकाई को पुन: संसाधित करता है। | |||
यह कंपाइलर की तार्किक कार्यप्रणाली को संदर्भित करता है, न कि केवल एक बार स्रोत फ़ाइल की वास्तविक रीडिंग को। उदाहरण के लिए, स्रोत फ़ाइल को एक बार अस्थायी भंडारण में पढ़ा जा सकता है लेकिन उस प्रतिलिपि को कई बार स्कैन किया जा सकता है। [[आईबीएम 1130]] [[फोरट्रान]] कंपाइलर ने स्रोत को मेमोरी में संग्रहीत किया और कई पासों का उपयोग किया; इसके विपरीत, डिस्क भंडारण इकाई की कमी वाले सिस्टम पर असेंबलर के लिए आवश्यक है कि कार्ड के स्रोत डेक को कार्ड रीडर/पंच के सामने दो बार प्रस्तुत किया जाए। | यह कंपाइलर की तार्किक कार्यप्रणाली को संदर्भित करता है, न कि केवल एक बार स्रोत फ़ाइल की वास्तविक रीडिंग को। उदाहरण के लिए, स्रोत फ़ाइल को एक बार अस्थायी भंडारण में पढ़ा जा सकता है लेकिन उस प्रतिलिपि को कई बार स्कैन किया जा सकता है। [[आईबीएम 1130]] [[फोरट्रान]] कंपाइलर ने स्रोत को मेमोरी में संग्रहीत किया और कई पासों का उपयोग किया; इसके विपरीत, डिस्क भंडारण इकाई की कमी वाले सिस्टम पर असेंबलर के लिए आवश्यक है कि कार्ड के स्रोत डेक को कार्ड रीडर/पंच के सामने दो बार प्रस्तुत किया जाए। | ||
==गुण== | ==गुण== | ||
एक-पास कंपाइलर मल्टी-पास कंपाइलर की तुलना में छोटे और तेज़ होते हैं।<ref>{{Cite web |date=2019-03-13 |title=सिंगल पास, टू पास और मल्टी पास कंपाइलर|url=https://www.geeksforgeeks.org/single-pass-two-pass-and-multi-pass-compilers/ |access-date=2023-05-15 |website=GeeksforGeeks |language=en-us}}</ref> | एक-पास कंपाइलर मल्टी-पास कंपाइलर की तुलना में छोटे और तेज़ होते हैं।<ref>{{Cite web |date=2019-03-13 |title=सिंगल पास, टू पास और मल्टी पास कंपाइलर|url=https://www.geeksforgeeks.org/single-pass-two-pass-and-multi-pass-compilers/ |access-date=2023-05-15 |website=GeeksforGeeks |language=en-us}}</ref> | ||
उपलब्ध जानकारी के सीमित दायरे के कारण वन-पास कंपाइलर मल्टी-पास कंपाइलर के समान कुशल प्रोग्राम उत्पन्न करने में असमर्थ हैं। कई प्रभावी कंपाइलर अनुकूलन के लिए मूल ब्लॉक, लूप (विशेष रूप से नेस्टेड लूप), सबरूटीन, या संपूर्ण मॉड्यूल पर एकाधिक पास की आवश्यकता होती है। कुछ को संपूर्ण कार्यक्रम के लिए पास की आवश्यकता होती है। कुछ [[प्रोग्रामिंग भाषा]]ओं को उनके डिज़ाइन के परिणामस्वरूप, एक बार में संकलित नहीं किया जा सकता है। उदाहरण के लिए पीएल/आई डेटा घोषणाओं को प्रोग्राम के भीतर कहीं भी रखने की अनुमति देता है, विशेष रूप से, अभी तक घोषित नहीं किए गए आइटम के कुछ संदर्भों के बाद, इसलिए जब तक पूरा प्रोग्राम स्कैन नहीं हो जाता तब तक कोई कोड उत्पन्न नहीं किया जा सकता है। भाषा की परिभाषा में प्री-प्रोसेसर स्टेटमेंट भी शामिल हैं जो संकलित करने के लिए स्रोत कोड उत्पन्न करते हैं: एकाधिक पास निश्चित हैं। इसके विपरीत, कई प्रोग्रामिंग भाषाओं को विशेष रूप से एक-पास कंपाइलरों के साथ संकलित करने के लिए डिज़ाइन किया गया है, और इसमें एक-पास संकलन की अनुमति देने के लिए विशेष प्रोग्रामिंग संरचनाएं शामिल हैं। | उपलब्ध जानकारी के सीमित दायरे के कारण वन-पास कंपाइलर मल्टी-पास कंपाइलर के समान कुशल प्रोग्राम उत्पन्न करने में असमर्थ हैं। कई प्रभावी कंपाइलर अनुकूलन के लिए मूल ब्लॉक, लूप (विशेष रूप से नेस्टेड लूप), सबरूटीन, या संपूर्ण मॉड्यूल पर एकाधिक पास की आवश्यकता होती है। कुछ को संपूर्ण कार्यक्रम के लिए पास की आवश्यकता होती है। कुछ [[प्रोग्रामिंग भाषा]]ओं को उनके डिज़ाइन के परिणामस्वरूप, एक बार में संकलित नहीं किया जा सकता है। उदाहरण के लिए पीएल/आई डेटा घोषणाओं को प्रोग्राम के भीतर कहीं भी रखने की अनुमति देता है, विशेष रूप से, अभी तक घोषित नहीं किए गए आइटम के कुछ संदर्भों के बाद, इसलिए जब तक पूरा प्रोग्राम स्कैन नहीं हो जाता तब तक कोई कोड उत्पन्न नहीं किया जा सकता है। भाषा की परिभाषा में प्री-प्रोसेसर स्टेटमेंट भी शामिल हैं जो संकलित करने के लिए स्रोत कोड उत्पन्न करते हैं: एकाधिक पास निश्चित हैं। इसके विपरीत, कई प्रोग्रामिंग भाषाओं को विशेष रूप से एक-पास कंपाइलरों के साथ संकलित करने के लिए डिज़ाइन किया गया है, और इसमें एक-पास संकलन की अनुमति देने के लिए विशेष प्रोग्रामिंग संरचनाएं शामिल हैं। |
Revision as of 01:32, 4 August 2023
कंप्यूटर प्रोग्रामिंग में, वन-पास संकलक एक कंपाइलर होता है जो प्रत्येक संकलन इकाई के हिस्सों से केवल एक बार गुजरता है, तुरंत प्रत्येक भाग को उसके अंतिम मशीन कोड में अनुवादित करता है। यह एक मल्टी-पास कंपाइलर के विपरीत है जो प्रोग्राम को स्रोत कोड और मशीन कोड के बीच चरणों में एक या अधिक मध्यवर्ती भाषाओं में परिवर्तित करता है, और जो प्रत्येक अनुक्रमिक पास में संपूर्ण संकलन इकाई को पुन: संसाधित करता है।
यह कंपाइलर की तार्किक कार्यप्रणाली को संदर्भित करता है, न कि केवल एक बार स्रोत फ़ाइल की वास्तविक रीडिंग को। उदाहरण के लिए, स्रोत फ़ाइल को एक बार अस्थायी भंडारण में पढ़ा जा सकता है लेकिन उस प्रतिलिपि को कई बार स्कैन किया जा सकता है। आईबीएम 1130 फोरट्रान कंपाइलर ने स्रोत को मेमोरी में संग्रहीत किया और कई पासों का उपयोग किया; इसके विपरीत, डिस्क भंडारण इकाई की कमी वाले सिस्टम पर असेंबलर के लिए आवश्यक है कि कार्ड के स्रोत डेक को कार्ड रीडर/पंच के सामने दो बार प्रस्तुत किया जाए।
गुण
एक-पास कंपाइलर मल्टी-पास कंपाइलर की तुलना में छोटे और तेज़ होते हैं।[1] उपलब्ध जानकारी के सीमित दायरे के कारण वन-पास कंपाइलर मल्टी-पास कंपाइलर के समान कुशल प्रोग्राम उत्पन्न करने में असमर्थ हैं। कई प्रभावी कंपाइलर अनुकूलन के लिए मूल ब्लॉक, लूप (विशेष रूप से नेस्टेड लूप), सबरूटीन, या संपूर्ण मॉड्यूल पर एकाधिक पास की आवश्यकता होती है। कुछ को संपूर्ण कार्यक्रम के लिए पास की आवश्यकता होती है। कुछ प्रोग्रामिंग भाषाओं को उनके डिज़ाइन के परिणामस्वरूप, एक बार में संकलित नहीं किया जा सकता है। उदाहरण के लिए पीएल/आई डेटा घोषणाओं को प्रोग्राम के भीतर कहीं भी रखने की अनुमति देता है, विशेष रूप से, अभी तक घोषित नहीं किए गए आइटम के कुछ संदर्भों के बाद, इसलिए जब तक पूरा प्रोग्राम स्कैन नहीं हो जाता तब तक कोई कोड उत्पन्न नहीं किया जा सकता है। भाषा की परिभाषा में प्री-प्रोसेसर स्टेटमेंट भी शामिल हैं जो संकलित करने के लिए स्रोत कोड उत्पन्न करते हैं: एकाधिक पास निश्चित हैं। इसके विपरीत, कई प्रोग्रामिंग भाषाओं को विशेष रूप से एक-पास कंपाइलरों के साथ संकलित करने के लिए डिज़ाइन किया गया है, और इसमें एक-पास संकलन की अनुमति देने के लिए विशेष प्रोग्रामिंग संरचनाएं शामिल हैं।
कठिनाइयाँ
मूल समस्या आगे के सन्दर्भों की है। स्रोत फ़ाइल में किसी बिंदु पर किसी प्रतीक की सही व्याख्या स्रोत फ़ाइल में आगे अन्य प्रतीकों की उपस्थिति या अनुपस्थिति पर निर्भर हो सकती है और जब तक उनका सामना नहीं किया जाता है, तब तक वर्तमान प्रतीक के लिए सही कोड उत्पन्न नहीं किया जा सकता है। यह संदर्भ निर्भरता की समस्या है, और विस्तार आसन्न प्रतीकों से लेकर मनमाने ढंग से बड़ी मात्रा में स्रोत पाठ तक कहीं भी हो सकता है।
स्थानीय संदर्भ
मान लीजिए कि प्रतीक < को तुलना से कम के रूप में पहचाना जाता है, उदाहरण के लिए इससे अधिक के विपरीत। कैरेक्टर कोडिंग सीमाओं के कारण, ग्लिफ़ ≤ मानक एन्कोडिंग में उपलब्ध नहीं हो सकता है, इसलिए एक मिश्रित प्रतिनिधित्व की अनुमति दी जानी चाहिए, <=। भले ही यह संदर्भ अगले प्रतीक द्वारा निर्धारित किया जाता है, यह अज्ञात है जब < का सामना होता है। इसी तरह, प्रतीक = का मतलब हमेशा = नहीं होता है, क्योंकि जब यह किसी मिश्रित प्रतीक का हिस्सा होता है। अन्य मिश्रित प्रतीकों में .lt शामिल हो सकता है। उस स्थिति के लिए जब विशेष वर्ण < अनुपलब्ध हो। फिर भी एक और संभावना जहां ग्लिफ़ ¬ (नहीं) के लिए एक वर्ण कोड अनुपलब्ध है, <> ¬= के लिए है या बराबर नहीं है - कुछ सिस्टम ~ या ! का उपयोग करते हैं। ¬ के लिए अभी भी और भिन्नता है। एक तरीका यह है कि < के बाद स्कैन को आगे बढ़ाया जाए और = का सामना करने पर, पीछे चला जाए। निःसंदेह इसका मतलब यह है कि पाठ के उस हिस्से पर दो बार गुजरना होगा, जिससे बचना होगा। उस मामले के लिए, स्रोत फ़ाइल किसी ऐसे उपकरण से आ सकती है जो कार्ड रीडर जैसे गो-बैक-एंड-रीरीड ऑपरेशन का समर्थन नहीं करता है। प्रारंभिक निर्णय लेने के बजाय, जिसे बाद में पूर्ववत करना पड़ सकता है, लेक्सिकल विश्लेषक क्वांटम सुपरपोजिशन की धारणा की तरह कई व्याख्याओं को बनाए रख सकता है, जो बाद में निर्धारण प्रतीक को देखने पर ही एक विशिष्ट विकल्प में बदल जाता है। विशेष रूप से, COBOL कंपाइलर दशमलव स्थिरांक में दिखाई देने वाले पूर्ण विराम और कथनों के अंत में दिखाई देने वाले पूर्ण विराम के बीच अंतर करने के लिए एक पास समर्पित करते हैं। ऐसी योजना एकल-पास कंपाइलर के लिए उपलब्ध नहीं है।
इसी प्रकार वस्तुओं के नाम के साथ भी। कुछ भाषाएँ स्वयं को एकल-वर्ण नामों तक ही सीमित रखती हैं, इसलिए एकल-वर्ण नाम के रूप में वर्ण x, पाठ जैसे नाम के भीतर वर्ण x से काफी भिन्न होता है - अब संदर्भ तत्काल आसन्न वर्णों से आगे बढ़ जाता है। अनुक्रमिक स्रोत धारा की वस्तुओं को भाषा के टोकन में अलग करना शाब्दिक विश्लेषक का कार्य है। सिर्फ शब्द ही नहीं, क्योंकि < और <= टोकन भी हैं। नाम आम तौर पर एक अक्षर से शुरू होते हैं और अक्षरों और अंकों के साथ जारी रहते हैं, और शायद कुछ अतिरिक्त प्रतीक जैसे _। संख्याओं को निर्दिष्ट करने के लिए अनुमत वाक्यविन्यास आश्चर्यजनक रूप से जटिल है, उदाहरण के लिए +3.14159E+0 मान्य हो सकता है। टोकन के बीच अंतरिक्ष वर्णों की एक मनमानी संख्या की अनुमति देना सामान्य है, और फोरट्रान स्पष्ट टोकन के भीतर रिक्त स्थान की अनुमति देने (और अनदेखा करने) में भी असामान्य है ताकि GO TO और GOTO समान हों जैसे कि <= और < =। हालाँकि, कुछ प्रणालियों को कुछ टोकन को सीमित करने के लिए रिक्त स्थान की आवश्यकता हो सकती है, और अन्य, जैसे कि पायथन, प्रोग्राम ब्लॉक के दायरे को इंगित करने के लिए अग्रणी रिक्त स्थान का उपयोग करते हैं जो अन्यथा प्रारंभ ... अंत या समान मार्करों द्वारा इंगित किया जा सकता है।
अभिव्यक्ति के भीतर संदर्भ
जो भाषाएँ अंकगणितीय अभिव्यक्तियों की अनुमति देती हैं वे आम तौर पर प्राथमिकता नियमों के साथ इन्फ़िक्स नोटेशन के वाक्यविन्यास का पालन करती हैं। इसका मतलब यह है कि किसी अभिव्यक्ति के मूल्यांकन के लिए कोड का निर्माण सुचारू रूप से नहीं होता है क्योंकि अभिव्यक्ति के टोकन स्रोत पाठ से प्राप्त होते हैं। उदाहरण के लिए, अभिव्यक्ति x + y*(u - v) लोड x के समतुल्य की ओर नहीं ले जाती है, y जोड़ें, क्योंकि x को y में नहीं जोड़ा गया है। यदि अंकगणित के लिए स्टैक स्कीम का उपयोग किया जाता है, तो कोड लोड एक्स से शुरू हो सकता है, लेकिन निम्नलिखित + टोकन से संबंधित कोड का पालन नहीं होता है। इसके बजाय, (u - v) के लिए कोड तैयार किया जाता है, उसके बाद y से गुणा किया जाता है और उसके बाद ही x जोड़ा जाता है। अंकगणितीय अभिव्यक्तियों का पार्सर अपने विश्लेषण के दौरान स्रोत के साथ आगे और पीछे नहीं चलता है, यह प्राथमिकता नियमों द्वारा संचालित स्थगित संचालन के स्थानीय स्टैक को नियोजित करता है। अंकगणितीय अभिव्यक्तियों को रिवर्स पोलिश नोटेशन या इसी तरह प्रस्तुत करने की आवश्यकता से इस नृत्य से बचा जा सकता है; उपरोक्त उदाहरण के लिए u v - y * x + जैसा कुछ और जिसे सख्ती से बाएं से दाएं स्कैन किया जाएगा।
एक अनुकूलन संकलक पुनरावृत्ति को पहचानने और हटाने या अन्य संभावित सुधार करने के लिए अंकगणितीय अभिव्यक्ति के रूप का विश्लेषण कर सकता है। विचार करना
a*sin(x) + b*sin(x)
कुछ भाषाएँ, जैसे अल्गोल, अंकगणितीय अभिव्यक्ति के भीतर असाइनमेंट की अनुमति देती हैं, इसलिए प्रोग्रामर कुछ इस तरह लिख सकता था
a*(t:=sin(x)) + b*t
लेकिन ऐसा करने के लिए आवश्यक परिश्रम के अलावा, परिणामी कथन का रूप गड़बड़ है और अब इसे कोडित किए जा रहे गणितीय अभिव्यक्ति से आसानी से तुलना नहीं की जा सकेगी। गलतियाँ आसानी से हो जायेंगी. इसके बजाय, कंपाइलर संपूर्ण अभिव्यक्ति के रूप का प्रतिनिधित्व कर सकता है (आमतौर पर एक पेड़ संरचना का उपयोग करके), उस संरचना का विश्लेषण और संशोधन कर सकता है, और फिर बेहतर फॉर्म के लिए कोड उत्सर्जित कर सकता है। क्रमिक असाइनमेंट स्टेटमेंट के ब्लॉक में एक स्पष्ट विस्तार होगा। इसमें स्रोत पाठ के माध्यम से दोबारा गुजरना शामिल नहीं है।
मध्यम श्रेणी संदर्भ
यद्यपि शाब्दिक विश्लेषक ने इनपुट स्ट्रीम को टोकन की एक स्ट्रीम में विभाजित कर दिया है (और किसी भी टिप्पणी को खारिज कर दिया है), भाषा के वाक्यविन्यास के अनुसार इन टोकन की व्याख्या अभी भी संदर्भ पर निर्भर हो सकती है। फोरट्रान छद्म कोड में निम्नलिखित कथनों पर विचार करें:
यदि (अभिव्यक्ति) = आदि। यदि (अभिव्यक्ति) लेबल1,लेबल2,लेबल3 यदि (अभिव्यक्ति) तो
पहला, if नामक एक-आयामी सरणी के एक तत्व के लिए कुछ अंकगणितीय अभिव्यक्ति (आदि) के मान का असाइनमेंट है। फोरट्रान इस मायने में असामान्य है कि इसमें कोई आरक्षित शब्द नहीं हैं, इसलिए एक सांकेतिक लेखन का मतलब यह नहीं है कि कोई लेखन-कथन प्रगति पर है। अन्य कथन वास्तव में यदि-कथन हैं - दूसरा एक अंकगणित है-यदि जो अभिव्यक्ति के परिणाम के संकेत की जांच करता है और इसके नकारात्मक, शून्य, या सकारात्मक होने के आधार पर 1, 2, या 3 लेबल पर कूदता है; तीसरा एक तार्किक-यदि है, और इसके लिए आवश्यक है कि इसकी अभिव्यक्ति का परिणाम बूलियन हो - इस प्रकार, लेक्सिकल विश्लेषक से निकलने वाले टोकन की सही व्याख्या तब तक नहीं की जा सकती जब तक कि अभिव्यक्ति को स्कैन नहीं किया जाता है और समापन ब्रैकेट के बाद वहां दिखाई नहीं देता है या तो एक बराबर चिह्न, एक अंक (लेबल 1 का पाठ होने के नाते: फोरट्रान लेबल के रूप में केवल पूर्णांक का उपयोग करता है, हालांकि यदि अक्षरों को अनुमति दी जाती है तो स्कैन को अल्पविराम खोजने पर निर्भर रहना होगा) या एक अक्षर से शुरू होने वाली कोई चीज़ (वह तब होनी चाहिए), और तो अब, संदर्भ स्रोत पाठ की एक मनमानी मात्रा तक फैला हुआ है क्योंकि अभिव्यक्ति मनमानी है। हालाँकि, तीनों मामलों में कंपाइलर स्कैन के आगे बढ़ने पर अभिव्यक्ति के मूल्यांकन के लिए कोड उत्पन्न कर सकता है। इस प्रकार, शाब्दिक विश्लेषण हमेशा स्वीकार्य वाक्यविन्यास की अनियमितताओं के कारण पहचाने गए टोकन के अर्थ को निर्धारित नहीं कर सकता है, और इसलिए यदि बैकट्रैकिंग से बचना है तो वाक्यविन्यास विश्लेषण को संभावित राज्यों का एक सुपरपोजिशन बनाए रखना होगा।
सुपरपोज़्ड अवस्थाओं के कोहरे में वाक्यविन्यास विश्लेषण के भटकने के साथ, यदि कोई त्रुटि सामने आती है (अर्थात, एक टोकन पाया जाता है जिसे किसी भी वैध वाक्यविन्यास फ्रेम में फिट नहीं किया जा सकता है) तो एक सहायक संदेश का उत्पादन मुश्किल हो सकता है। उदाहरण के लिए, बी6700 अल्गोल कंपाइलर त्रुटि संदेशों के लिए कुख्यात था, जैसे कि स्रोत लाइन की सूची के साथ-साथ परेशानी का स्थान दिखाने वाला एक मार्कर - अक्सर अर्धविराम को चिह्नित करने के साथ अपेक्षित अर्धविराम। अर्धविराम की अनुपस्थिति में, यदि किसी को वास्तव में संकेत के अनुसार रखा गया था, तो पुनर्संकलन पर इसके लिए एक अप्रत्याशित अर्धविराम संदेश उत्पन्न हो सकता है। अक्सर, कंपाइलर से केवल पहला त्रुटि संदेश ही ध्यान देने योग्य होगा, क्योंकि बाद के संदेश गड़बड़ा गए थे। स्रोत फ़ाइल में त्रुटि होने पर वर्तमान व्याख्या को रद्द करना और फिर अगले कथन की शुरुआत में स्कैन को फिर से शुरू करना मुश्किल होता है, और इसलिए बाद के संदेश अनुपयोगी होते हैं। आगे का कोड उत्पादन निश्चित रूप से छोड़ दिया गया है।
इस समस्या को आरक्षित शब्दों के उपयोग के माध्यम से कम किया जा सकता है, उदाहरण के लिए यदि, तब, और अन्य हमेशा एक इफ-स्टेटमेंट के हिस्से होते हैं और चर के नाम नहीं हो सकते हैं, लेकिन आश्चर्यजनक रूप से बड़ी संख्या में उपयोगी शब्द अनुपलब्ध हो सकते हैं। एक और तरीका है स्ट्रॉपिंग, जिसके तहत आरक्षित शब्दों को चिह्नित किया जाता है, जैसे कि उन्हें पूर्ण विराम, या एपोस्ट्रोफ जैसे विशेष वर्णों के बीच रखकर, जैसा कि अल्गोल के कुछ संस्करणों में होता है। इस का मतलब है कि 'if'
और if
अलग-अलग टोकन हैं, बाद वाला एक सामान्य नाम है, लेकिन उन सभी एपोस्ट्रोफ की आपूर्ति जल्द ही परेशान करने वाली हो जाती है। कई भाषाओं के लिए, रिक्ति पर्याप्त जानकारी प्रदान करती है, हालांकि यह जटिल हो सकती है। अक्सर यह केवल एक स्थान (या टैब, आदि) नहीं होता है, बल्कि एक अक्षर या अंक के अलावा एक वर्ण होता है जो संभावित टोकन के पाठ को समाप्त करता है। उपरोक्त उदाहरण में, यदि-कथन की अभिव्यक्ति कोष्ठक के भीतर होनी चाहिए ताकि (निश्चित रूप से यदि की पहचान समाप्त हो जाए और इसी तरह,) तब की पहचान को सक्षम कर सके; इसके अलावा, किसी कंपाउंड के अन्य भाग if-स्टेटमेंट को नई लाइनों पर प्रदर्शित होना चाहिए: else और End if (या Endif ) और else if । इसके विपरीत, अल्गोल और अन्य के साथ कोष्ठक की आवश्यकता नहीं होती है और इफ-स्टेटमेंट के सभी भाग एक पंक्ति में हो सकते हैं। पास्कल के साथ, 'यदि' ए 'या' बी 'तब' आदि मान्य है, लेकिन यदि ए और बी अभिव्यक्ति हैं, तो उन्हें कोष्ठक में संलग्न किया जाना चाहिए।
संकलक द्वारा निर्मित स्रोत फ़ाइल सूची को उसके द्वारा पहचाने जाने वाले आरक्षित शब्दों को रेखांकित या 'बोल्ड' या इटैलिक में प्रस्तुत करके पढ़ना आसान बनाया जा सकता है, लेकिन आलोचना हुई है: अल्गोल एकमात्र ऐसी भाषा है जो इटैलिक और सामान्य पूर्ण विराम के बीच अंतर करती है। दरअसल ये कोई मज़ाक की बात नहीं है. फोरट्रान में, एक डू-स्टेटमेंट की शुरुआत जैसे होती है DO 12 I = 1,15
से अलग है DO 12 I = 1.15
(एक वैरिएबल के लिए मान 1.15 का एक असाइनमेंट कहा जाता है DO12I
; याद रखें कि रिक्त स्थान अप्रासंगिक हैं) केवल अल्पविराम और पूर्ण विराम के बीच के अंतर से, और एक मुद्रित सूची के ग्लिफ़ अच्छी तरह से नहीं बने हो सकते हैं।
किसी भाषा के डिज़ाइन पर सावधानीपूर्वक ध्यान देने से एक विश्वसनीय संकलक बनाने की दृष्टि से अभिव्यक्ति की स्पष्टता और सरलता को बढ़ावा मिल सकता है जिसका व्यवहार आसानी से समझ में आता है। फिर भी ख़राब विकल्प आम हैं। उदाहरण के लिए, मैटलैब ए' के रूप में एपोस्ट्रोफ का उपयोग करके मैट्रिक्स ट्रांसपोज़िशन को दर्शाता है जो कि अपवाद नहीं है और गणितीय उपयोग का बारीकी से पालन करता है। ठीक है और अच्छा है, लेकिन टेक्स्ट स्ट्रिंग के सीमांकक के लिए मैटलैब किसी भी उद्देश्य के लिए दोहरे उद्धरण चिह्न द्वारा प्रस्तुत अवसर को अनदेखा करता है और इसके लिए एपोस्ट्रोफ का भी उपयोग करता है। हालाँकि ऑक्टेव टेक्स्ट स्ट्रिंग्स के लिए दोहरे उद्धरण चिह्नों का उपयोग करता है, यह मैटलैब कथनों को भी स्वीकार करने का प्रयास करता है और इसलिए समस्या दूसरे सिस्टम तक फैल जाती है।
प्री-प्रोसेसर विस्तार
यह इस स्तर पर है कि प्री-प्रोसेसर विकल्पों का प्रयोग किया जाता है, तथाकथित क्योंकि इन्हें कंपाइलर द्वारा आने वाले स्रोत को उचित रूप से संसाधित करने से पहले प्रयोग किया जाता है। वे असेंबलर सिस्टम के मैक्रो विस्तार विकल्पों को प्रतिध्वनित करते हैं, उम्मीद है कि अधिक दयालु वाक्यविन्यास के साथ। सबसे आम व्यवस्था पर एक भिन्नता है
यदि स्थिति तो यह स्रोत अन्यथा अन्य स्रोत फाई
अक्सर प्री-प्रोसेसर सोर्स स्टेटमेंट को सामान्य सोर्स स्टेटमेंट से अलग करने की कुछ व्यवस्था के साथ, जैसे कि pl/i, या # इत्यादि में % प्रतीक से शुरू होने वाला स्टेटमेंट। एक और सरल विकल्प एक भिन्नता है
यह = वह परिभाषित करें
लेकिन सावधानी की जरूरत है, जैसे कि
SumXY = (x + y) को परिभाषित करें योग:=3*SumXY;
चूँकि कोष्ठक के बिना, परिणाम sum:=3*x + y; इसी तरह, प्रतिस्थापन पाठ की सीमा निर्धारित करने और परिणामी पाठ को कैसे स्कैन किया जाएगा, यह निर्धारित करने में सावधानी बरतने की आवश्यकता है। विचार करना
#तीन परिभाषित करें = 3; #बिंदु परिभाषित करें = .; #एक को परिभाषित करें = 1; x:=तीन दशमलव एक;
यहां परिभाषित कथन को अर्धविराम द्वारा समाप्त किया जाता है, और अर्धविराम स्वयं प्रतिस्थापन का हिस्सा नहीं है। आह्वान नहीं हो सकता x:=threepointone;
क्योंकि वह एक अलग नाम है, लेकिन three point one
होगा 3 . 1
और बाद का स्कैन उसे एकल टोकन के रूप में मानने में सक्षम हो भी सकता है और नहीं भी।
कुछ प्रणालियाँ प्री-प्रोसेसर प्रक्रियाओं की परिभाषा की अनुमति देती हैं जिनका आउटपुट स्रोत पाठ को संकलित करने के लिए होता है, और ऐसे स्रोत को और भी प्री-प्रोसेसर आइटम को परिभाषित करने की अनुमति भी दे सकते हैं। ऐसे विकल्पों के कुशल उपयोग से स्थिरांकों को व्याख्यात्मक नाम दिए जाने, विवरण को आसान निमोनिक्स द्वारा प्रतिस्थापित करने, नए कथन प्रपत्रों की उपस्थिति और सामान्य प्रक्रिया के विशिष्ट उपयोगों के लिए इन-लाइन कोड उत्पन्न करने (जैसे सॉर्टिंग) की अनुमति मिलती है। , बजाय वास्तविक प्रक्रियाओं को तैयार करने के। मापदंडों और पैरामीटर प्रकारों के प्रसार के साथ, आवश्यक संयोजनों की संख्या तेजी से बढ़ती है।
इसके अलावा, एक ही प्री-प्रोसेसर सिंटैक्स का उपयोग कई अलग-अलग भाषाओं, यहां तक कि प्राकृतिक भाषाओं के लिए भी किया जा सकता है, जैसे किसी व्यक्ति के नाम, उपनाम, पालतू कुत्ते का नाम आदि का उपयोग करके कहानी टेम्पलेट से कहानी तैयार करना और प्रलोभन होगा एक प्री-प्रोसेसर प्रोग्राम तैयार करें जो स्रोत फ़ाइल को स्वीकार करेगा, प्री-प्रोसेसर क्रियाएं करेगा और अगले चरण, संकलन के लिए तैयार परिणाम को आउटपुट करेगा। लेकिन यह स्पष्ट रूप से स्रोत के माध्यम से कम से कम एक अतिरिक्त पास का गठन करता है और इसलिए ऐसा समाधान एकल-पास कंपाइलर के लिए अनुपलब्ध होगा। इस प्रकार, वास्तविक इनपुट स्रोत फ़ाइल के माध्यम से प्रगति फिट और स्टार्ट में अच्छी तरह से आगे बढ़ सकती है, लेकिन यह अभी भी यूनिडायरेक्शनल है।
लंबी दूरी का संदर्भ
कंपाइलर द्वारा कोड जेनरेशन (कंपाइलर) को फॉरवर्ड रेफरेंस की समस्या का भी सामना करना पड़ता है, सबसे सीधे तौर पर लेबल पर जाएं जैसे जहां गंतव्य लेबल स्रोत फ़ाइल में आगे एक अज्ञात दूरी है, और इस प्रकार जंप निर्देश उस लेबल के स्थान तक पहुंचने के लिए अभी तक उत्पन्न होने वाले कोड में एक अज्ञात दूरी शामिल है। कुछ भाषा डिज़ाइन, संभवतः Consulted_harmful| से प्रभावित हैं हानिकारक माने जाने वाले GOTO में GOTO कथन नहीं होता है, लेकिन इससे समस्या नहीं सुलझती क्योंकि एक कार्यक्रम में कई अंतर्निहित GOTO समकक्ष होते हैं। विचार करना
यदि स्थिति है तो कोड सही है अन्यथा कोड गलत है
जैसा कि पहले उल्लेख किया गया है, स्थिति का मूल्यांकन करने के लिए कोड तुरंत उत्पन्न किया जा सकता है। लेकिन जब तत्कालीन टोकन का सामना होता है, तो एक जम्पफाल्स ऑपरेशन कोड रखा जाना चाहिए जिसका गंतव्य पता कोड गलत कथनों के लिए कोड की शुरुआत है, और इसी तरह, जब अन्य टोकन का सामना होता है, तो उसके लिए अभी-अभी पूरा किया गया कोड कोड ट्रू स्टेटमेंट के बाद एक GOTO-स्टाइल जंप ऑपरेशन होना चाहिए जिसका गंतव्य वह कोड है जो if-स्टेटमेंट के अंत के बाद आता है, यहां फाई टोकन द्वारा चिह्नित किया गया है। इन गंतव्यों को केवल तब ही जाना जा सकता है जब अभी तक स्कैन न किए गए स्रोत के लिए मनमानी मात्रा में कोड उत्पन्न हो जाए। इसी तरह की समस्याएँ किसी भी कथन के लिए उत्पन्न होती हैं जिनके हिस्से स्रोत की मनमानी मात्रा तक फैले होते हैं, जैसे कि केस स्टेटमेंट।
एक रिकर्सिव-डिसेंट कंपाइलर प्रत्येक प्रकार के स्टेटमेंट के लिए एक प्रक्रिया को सक्रिय करेगा, जैसे कि इफ-स्टेटमेंट, जिसके बदले में कोड ट्रू और कोड गलत के स्टेटमेंट के लिए कोड उत्पन्न करने के लिए उचित प्रक्रियाओं को लागू किया जाएगा। इसके कथन के कुछ हिस्सों और इसी प्रकार अन्य कथनों के लिए उनके वाक्य-विन्यास के अनुसार। अपने स्थानीय भंडारण में यह अपने अपूर्ण जंपफाल्स ऑपरेशन के पता फ़ील्ड के स्थान का ट्रैक रखेगा, और इसके तत्कालीन टोकन का सामना करने पर, अब ज्ञात पते को रखेगा, और इसी तरह 'के बाद आवश्यक जंप के लिए फाई टोकन का सामना करने पर 'कोड सत्य कोड। GoTo स्टेटमेंट इस मायने में भिन्न है कि जिस कोड पर जम्प किया जाना है वह उसके स्टेटमेंट फॉर्म के अंदर नहीं है, इसलिए फिक्सअप की एक सहायक तालिका में एक प्रविष्टि की आवश्यकता होती है जिसका उपयोग अंततः उसके लेबल के सामने आने पर किया जाएगा। इस धारणा को बढ़ाया जा सकता है. सभी अज्ञात-गंतव्य जंप एक जंप टेबल में एक प्रविष्टि के माध्यम से किए जा सकते हैं (जिनके पते बाद में गंतव्यों के सामने आने पर भर दिए जाते हैं), हालांकि इस तालिका का आवश्यक आकार संकलन के अंत तक अज्ञात है।
इसका एक समाधान कंपाइलर के लिए असेंबलर स्रोत को उत्सर्जित करना है (जंप आदि के लिए गंतव्य के रूप में कंपाइलर-जनरेटेड लेबल के साथ), और असेंबलर वास्तविक पते निर्धारित करेगा। लेकिन इसके लिए स्पष्ट रूप से स्रोत फ़ाइल के एक अतिरिक्त पास (एक संस्करण) की आवश्यकता होती है और इसलिए एकल-पास कंपाइलरों के लिए इसकी अनुमति नहीं है।
दुर्भाग्यपूर्ण निर्णय
हालाँकि ऊपर दिए गए विवरण में इस धारणा को नियोजित किया गया है कि कोड को बाद में तय किए जाने के लिए छोड़े गए कुछ फ़ील्ड के साथ उत्पन्न किया जा सकता है, एक अंतर्निहित धारणा थी कि ऐसे कोड अनुक्रमों का आकार स्थिर था। यह मामला नहीं हो सकता है। कई कंप्यूटरों में अलग-अलग मात्रा में स्टोरेज लेने वाले संचालन के लिए प्रावधान होता है, विशेष रूप से सापेक्ष एड्रेसिंग, जिसके तहत यदि गंतव्य -128 या +127 एड्रेसिंग चरणों के भीतर है, तो आठ-बिट एड्रेस फ़ील्ड का उपयोग किया जा सकता है, अन्यथा पहुंचने के लिए बहुत बड़े एड्रेस फ़ील्ड की आवश्यकता होती है। . इस प्रकार यदि कोड एक आशाजनक संक्षिप्त पता फ़ील्ड के साथ उत्पन्न किया गया था, तो बाद में वापस जाना और लंबे फ़ील्ड का उपयोग करने के लिए कोड को समायोजित करना आवश्यक हो सकता है, जिसके परिणामस्वरूप परिवर्तन के बाद पहले कोड संदर्भित स्थानों को भी समायोजित करना होगा। इसी तरह, परिवर्तन के दौरान पीछे की ओर जाने वाले बाद के संदर्भों को भी ठीक करना होगा, यहां तक कि वे भी जो ज्ञात पतों पर थे। और साथ ही, फिक्सअप जानकारी को स्वयं ही सही ढंग से ठीक करना होगा। दूसरी ओर, लंबे पते का उपयोग उन सभी मामलों के लिए किया जा सकता है जब निकटता निश्चित नहीं है, लेकिन परिणामी कोड अब आदर्श नहीं होगा।
एक-पास अनुक्रमिक इनपुट, अनियमित अनुक्रम आउटपुट
एक ही कथन में अनुकूलन की कुछ संभावनाओं का उल्लेख पहले ही किया जा चुका है। एकाधिक कथनों में अनुकूलन के लिए आवश्यक होगा कि ऐसे कथनों की सामग्री को किसी प्रकार की डेटा संरचना में रखा जाए जिसका कोड उत्सर्जित होने से पहले विश्लेषण और हेरफेर किया जा सके। ऐसे मामले में, फिक्सअप की अनुमति के साथ भी अनंतिम कोड का उत्पादन एक बाधा होगी। सीमा में इसका मतलब है कि कंपाइलर पूरे प्रोग्राम को आंतरिक रूप में प्रस्तुत करने वाली एक डेटा संरचना तैयार करेगा, लेकिन एक स्ट्रॉ को पकड़ा जा सकता है और दावा किया जा सकता है कि शुरू से अंत तक स्रोत फ़ाइल का कोई वास्तविक दूसरा पास नहीं है। संभवतः पीआर दस्तावेज़ में कंपाइलर का विज्ञापन किया गया है।
विशेष रूप से इसलिए, एक कंपाइलर अपने कोड को एक निरंतर-अग्रेषित अनुक्रम में उत्पन्न नहीं कर सकता है, स्रोत के प्रत्येक भाग को पढ़ने के तुरंत बाद भी नहीं। आउटपुट को अभी भी क्रमिक रूप से लिखा जा सकता है, लेकिन केवल तभी जब किसी सेक्शन का आउटपुट तब तक के लिए स्थगित कर दिया जाता है जब तक कि उस सेक्शन के लिए सभी लंबित फिक्सअप नहीं हो जाते।
उपयोग से पहले घोषणा
विभिन्न अभिव्यक्तियों के लिए कोड बनाते समय, कंपाइलर को ऑपरेंड की प्रकृति जानने की आवश्यकता होती है। उदाहरण के लिए, एक कथन जैसे A:=B; ए और बी पूर्णांक हैं या फ़्लोटिंग-पॉइंट वैरिएबल (और कौन सा आकार: एकल, डबल या चौगुनी परिशुद्धता) या जटिल संख्या, सरणी, स्ट्रिंग, प्रोग्रामर-परिभाषित प्रकार इत्यादि के आधार पर अलग-अलग कोड उत्पन्न कर सकते हैं। इस मामले में, एक सरल दृष्टिकोण भंडारण के शब्दों की उचित संख्या को स्थानांतरित करना होगा, लेकिन, स्ट्रिंग्स के लिए यह अनुपयुक्त हो सकता है क्योंकि प्राप्तकर्ता आपूर्तिकर्ता से छोटा हो सकता है और किसी भी मामले में, स्ट्रिंग का केवल एक हिस्सा उपयोग किया जा सकता है - शायद इसमें एक हजार अक्षरों के लिए जगह है, लेकिन वर्तमान में इसमें दस शामिल हैं। फिर अधिक जटिल निर्माण भी हैं, जैसे कि COBOL और pl/i द्वारा प्रस्तावित A:=B by name;
इस मामले में, ए और बी समुच्चय (या संरचनाएं) हैं, उदाहरण के लिए ए में कुछ हिस्से हैं A.x
, A.y
और A.other
जबकि बी के हिस्से हैं B.y
, B.c
और B.x
, और उसी क्रम में. नाम सुविधा का अर्थ इसके समकक्ष है A.y:=B.y; A.x:=B.x;
लेकिन क्योंकि B.c
ए, और में कोई समकक्ष नहीं है A.other
बी में कोई समकक्ष नहीं है, वे शामिल नहीं हैं।
यह सब इस आवश्यकता से नियंत्रित किया जा सकता है कि वस्तुओं को उपयोग से पहले घोषित किया जाए। कुछ भाषाओं में स्पष्ट घोषणाओं की आवश्यकता नहीं होती है, पहली बार किसी नए नाम का सामना करने पर एक अंतर्निहित घोषणा उत्पन्न होती है। क्या फोरट्रान कंपाइलर को पहले से अज्ञात नाम का सामना करना पड़ता है जिसका पहला अक्षर I, J,...,N में से एक है, तो चर एक पूर्णांक होगा, अन्यथा एक फ़्लोटिंग-पॉइंट वैरिएबल होगा। इस प्रकार एक नाम DO12I
एक फ़्लोटिंग-पॉइंट वैरिएबल होगा। यह एक सुविधा है, लेकिन गलत टाइप किए गए नामों के साथ कुछ अनुभवों के बाद, अधिकांश प्रोग्रामर इस बात से सहमत हैं कि किसी भी अंतर्निहित कंपाइलर विकल्प का उपयोग नहीं किया जाना चाहिए।
अन्य प्रणालियाँ प्रकार तय करने के लिए पहली मुठभेड़ की प्रकृति का उपयोग करती हैं, जैसे कि एक स्ट्रिंग, या एक सरणी, इत्यादि। व्याख्या की गई भाषाएँ विशेष रूप से लचीली हो सकती हैं, निर्णय रन टाइम पर लिया जा सकता है, कुछ इस प्रकार
यदि स्थिति तो pi:= 3.14 अन्यथा pi:=3.14 fi; पाई प्रिंट करें;
क्या ऐसी भाषा के लिए कोई कंपाइलर होना चाहिए, उसे वेरिएबल पाई का प्रतिनिधित्व करने के लिए एक जटिल इकाई बनानी होगी, जिसमें यह संकेत होगा कि इसका वर्तमान प्रकार क्या है और ऐसे प्रकार का प्रतिनिधित्व करने के लिए संबंधित भंडारण होगा। यह निश्चित रूप से लचीला है, लेकिन गहन गणना के लिए सहायक नहीं हो सकता है जैसे कि A.x = b को हल करने में जहां A सौ क्रम का एक मैट्रिक्स है, और अचानक, इसका कोई भी तत्व एक अलग प्रकार का हो सकता है।
प्रक्रियाएँ और कार्य
उपयोग से पहले घोषणा भी प्रक्रियाओं और कार्यों के लिए एक आसान आवश्यकता है, और यह प्रक्रियाओं के भीतर प्रक्रियाओं के घोंसले पर भी लागू होती है। ALGOL, पास्कल, PL/I और कई अन्य की तरह, MATLAB और (1995 से) फोरट्रान एक फ़ंक्शन (या प्रक्रिया) को किसी अन्य फ़ंक्शन (या प्रक्रिया) की परिभाषा को शामिल करने की अनुमति देते हैं, जो केवल युक्त फ़ंक्शन के भीतर दिखाई देता है, लेकिन इन प्रणालियों के लिए आवश्यक है कि उन्हें युक्त प्रक्रिया के अंत के बाद परिभाषित किया जाए।
लेकिन जब पुनरावृत्ति की अनुमति दी जाती है, तो एक समस्या उत्पन्न होती है। दो प्रक्रियाएँ, जिनमें से प्रत्येक एक दूसरे का आह्वान करती हैं, दोनों को उपयोग से पहले घोषित नहीं किया जा सकता है। स्रोत फ़ाइल में सबसे पहले होना चाहिए। इससे कोई फर्क नहीं पड़ता, जैसा कि एक अज्ञात चर के साथ मुठभेड़ पर, मुठभेड़ से पर्याप्त निष्कर्ष निकाला जा सकता है कि कंपाइलर अज्ञात प्रक्रिया के आह्वान के लिए उपयुक्त कोड उत्पन्न कर सकता है, निश्चित रूप से वापस आने और भरने के लिए फिक्सअप उपकरण के साथ जब प्रक्रिया की परिभाषा सामने आती है तो गंतव्य के लिए सही पते पर। उदाहरण के लिए, बिना किसी पैरामीटर वाली प्रक्रिया के लिए यही स्थिति होगी। किसी फ़ंक्शन मंगलाचरण से लौटाया गया परिणाम मंगलाचरण से पहचाने जाने योग्य प्रकार का हो सकता है, लेकिन यह हमेशा सही नहीं हो सकता है: एक फ़ंक्शन एक फ़्लोटिंग-पॉइंट परिणाम लौटा सकता है लेकिन इसका मान एक पूर्णांक को सौंपा जा सकता है।
पास्कल पूर्वघोषणा की आवश्यकता के द्वारा इस समस्या का समाधान करता है। प्रक्रिया या फ़ंक्शन घोषणाओं में से एक पहले दी जानी चाहिए, लेकिन, प्रक्रिया या फ़ंक्शन के मुख्य भाग के बजाय, कीवर्ड 'फ़ॉरवर्ड' दिया गया है। फिर अन्य प्रक्रिया या कार्य को घोषित किया जा सकता है और उसके मुख्य भाग को परिभाषित किया जा सकता है। किसी बिंदु पर आगे की प्रक्रिया या फ़ंक्शन को फ़ंक्शन के मुख्य भाग के साथ पुनः घोषित किया जाता है।
मापदंडों के साथ एक प्रक्रिया (या फ़ंक्शन) के आह्वान के लिए, उनके प्रकार को जाना जाएगा (उन्हें उपयोग से पहले घोषित किया जाएगा) लेकिन प्रक्रिया के आह्वान में उनका उपयोग नहीं किया जा सकता है। उदाहरण के लिए, फोरट्रान सभी मापदंडों को संदर्भ द्वारा (यानी पते द्वारा) पारित करता है, इसलिए कोड उत्पन्न करने में कोई तत्काल कठिनाई नहीं होती है (हमेशा की तरह, वास्तविक पते बाद में तय किए जाएंगे), लेकिन पास्कल और अन्य भाषाएं विभिन्न तरीकों से मापदंडों को पारित करने की अनुमति देती हैं प्रोग्रामर की पसंद पर (मूल्यांकन रणनीति#संदर्भ द्वारा कॉल करें, या मूल्यांकन रणनीति#मूल्य द्वारा कॉल करें, या शायद मूल्यांकन रणनीति#नाम से कॉल करें|नाम से) और यह केवल प्रक्रिया की परिभाषा में दर्शाया गया है, जो इससे पहले अज्ञात है परिभाषा का सामना करना पड़ा है. विशेष रूप से पास्कल के लिए, मापदंडों के विनिर्देश में एक उपसर्ग वार दर्शाता है कि इसे संदर्भ द्वारा प्राप्त किया जाना चाहिए, इसकी अनुपस्थिति मूल्य से दर्शाती है। पहले मामले में कंपाइलर को कोड उत्पन्न करना होगा जो पैरामीटर के पते को पास करता है, जबकि दूसरे में उसे अलग कोड उत्पन्न करना होगा जो मान की एक प्रति को आमतौर पर स्टैक के माध्यम से पास करता है। हमेशा की तरह, इससे निपटने के लिए एक फिक्सअप तंत्र लागू किया जा सकता है, लेकिन यह बहुत गड़बड़ होगा। मल्टी-पास कंपाइलर निश्चित रूप से सभी आवश्यक जानकारी को एकत्रित कर सकते हैं क्योंकि वे आगे और पीछे शटल करते हैं, लेकिन सिंगल-पास कंपाइलर ऐसा नहीं कर सकते हैं। स्कैन के आगे बढ़ने पर कोड जनरेशन को रोका जा सकता है (और इसके परिणाम आंतरिक भंडारण में रखे जाएंगे) जब तक कि आवश्यक इकाई का सामना न हो जाए, और इसे स्रोत के माध्यम से दूसरी बार पास होने के परिणामस्वरूप नहीं माना जा सकता है क्योंकि कोड जनरेशन चरण होगा जल्द ही पकड़ लो, यह केवल थोड़ी देर के लिए रुक रहा था। लेकिन यह जटिल होगा. इसके बजाय एक विशेष निर्माण शुरू किया गया है, जिसके तहत पैरामीटर उपयोग की प्रक्रिया की परिभाषा को इसकी बाद की पूर्ण परिभाषा से पहले घोषित किया जाता है ताकि कंपाइलर इसे उपयोग से पहले जान सके, जैसा कि इसकी आवश्यकता है।
फर्स्ट फोरट्रान (1957) के बाद से, एक कार्यक्रम के हिस्सों का अलग-अलग संकलन संभव हो गया है, जो प्रक्रियाओं और कार्यों के पुस्तकालयों के निर्माण का समर्थन करता है। संकलित की जा रही स्रोत फ़ाइल में एक प्रक्रिया जो ऐसे बाहरी संग्रह से एक फ़ंक्शन को आमंत्रित करती है, उसे प्रकार जानना चाहिएअज्ञात फ़ंक्शन द्वारा लौटाए गए परिणाम का, यदि केवल कोड उत्पन्न करना है जो परिणाम ढूंढने के लिए सही जगह पर दिखता है। मूल रूप से, जब केवल पूर्णांक और फ़्लोटिंग-पॉइंट चर थे, तो विकल्प को अंतर्निहित घोषणा के नियमों पर छोड़ा जा सकता था, लेकिन आकार और प्रकारों के प्रसार के साथ आह्वान प्रक्रिया को फ़ंक्शन के लिए एक प्रकार की घोषणा की आवश्यकता होगी। यह कोई विशेष बात नहीं है, इसका स्वरूप प्रक्रिया के अंदर घोषित चर के समान ही है।
पूरी की जाने वाली आवश्यकता यह है कि एकल-पास संकलन में वर्तमान बिंदु पर, एक इकाई पर जानकारी की आवश्यकता होती है ताकि इसके लिए सही कोड अभी तैयार किया जा सके, यदि बाद में पता फिक्सअप के साथ। क्या आवश्यक जानकारी बाद में स्रोत फ़ाइल में मिलेगी या कुछ अलग से संकलित कोड फ़ाइल में मिलेगी, जानकारी यहां कुछ प्रोटोकॉल द्वारा प्रदान की गई है।
किसी प्रक्रिया (या फ़ंक्शन) के सभी आह्वानों की एक-दूसरे और उनकी परिभाषाओं के साथ अनुकूलता के लिए जाँच की जाती है या नहीं, यह एक अलग मामला है। अल्गोल-जैसी प्रेरणा से उत्पन्न भाषाओं में, यह जाँच आमतौर पर कठोर होती है, लेकिन अन्य प्रणालियाँ उदासीन हो सकती हैं। उन प्रणालियों को छोड़कर जो किसी प्रक्रिया को वैकल्पिक पैरामीटर रखने की अनुमति देते हैं, पैरामीटर की संख्या और प्रकार में गलतियाँ आम तौर पर प्रोग्राम के क्रैश होने का कारण बनेंगी। सिस्टम जो पूरे कार्यक्रम के हिस्सों के अलग-अलग संकलन की अनुमति देते हैं, जिन्हें बाद में एक साथ जोड़ा जाता है, उन्हें सही प्रकार और मापदंडों की संख्या और परिणामों की भी जांच करनी चाहिए क्योंकि गलतियाँ करना और भी आसान है, लेकिन अक्सर ऐसा नहीं होता है। कुछ भाषाओं (जैसे अल्गोल) में उन्नयन या विस्तार या पदोन्नति की औपचारिक धारणा होती है, जिसके तहत एक प्रक्रिया जो यह अपेक्षा करती है कि एक डबल-सटीक पैरामीटर को एकल परिशुद्धता चर के रूप में लागू किया जा सकता है, और इस मामले में कंपाइलर कोड उत्पन्न करता है जो एकल परिशुद्धता चर को एक अस्थायी डबल-परिशुद्धता चर में संग्रहीत करता है जो वास्तविक पैरामीटर बन जाता है। हालाँकि, यह पैरामीटर पासिंग तंत्र को मूल्यांकन रणनीति#कॉपी-रिस्टोर|कॉपी-इन, कॉपी-आउट द्वारा कॉल में बदल देता है जिससे व्यवहार में सूक्ष्म अंतर हो सकता है। जब कोई प्रक्रिया एक एकल परिशुद्धता चर का पता प्राप्त करती है, जब वह दोहरे परिशुद्धता पैरामीटर, या अन्य आकार भिन्नताओं की अपेक्षा करती है, तो परिणाम बहुत कम सूक्ष्म होते हैं। जब प्रक्रिया के भीतर पैरामीटर का मान पढ़ा जाता है, तो उसके दिए गए पैरामीटर की तुलना में अधिक संग्रहण पढ़ा जाएगा और परिणामी मान में सुधार होने की संभावना नहीं है। इससे भी बदतर स्थिति तब होती है जब प्रक्रिया अपने पैरामीटर का मान बदल देती है: कुछ न कुछ क्षतिग्रस्त होना निश्चित है। इन गलतियों को खोजने और सुधारने में बहुत धैर्य खर्च किया जा सकता है।
पास्कल उदाहरण
ऐसे निर्माण का एक उदाहरण पास्कल (प्रोग्रामिंग भाषा) में आगे की घोषणा है। पास्कल के लिए आवश्यक है कि उपयोग से पहले सबरूटीन को घोषित या पूर्ण रूप से परिभाषित किया जाए। यह एक-पास कंपाइलर को उसके प्रकार की जाँच करने में मदद करता है: ऐसी प्रक्रिया को कॉल करना जिसे कहीं भी घोषित नहीं किया गया है, एक स्पष्ट त्रुटि है। उपयोग से पहले घोषणा नियम के बावजूद, आगे की घोषणाएं आपसी रिकर्सन प्रक्रियाओं को एक-दूसरे को सीधे कॉल करने में मदद करती हैं:
function odd(n : integer) : boolean;
begin
if n = 0 then
odd := false
else if n < 0 then
odd := even(n + 1) { Compiler error: 'even' is not defined }
else
odd := even(n - 1)
end;
function even(n : integer) : boolean;
begin
if n = 0 then
even := true
else if n < 0 then
even := odd(n + 1)
else
even := odd(n - 1)
end;
फ़ंक्शन के लिए एक अग्रेषित घोषणा जोड़कर even
समारोह से पहले odd
, वन-पास कंपाइलर को बताया जाता है कि इसकी एक परिभाषा होगी even
बाद में कार्यक्रम में.
function even(n : integer) : boolean; forward;
function odd(n : integer) : boolean;
{ Et cetera }
जब फ़ंक्शन के मुख्य भाग की वास्तविक घोषणा की जाती है, तो या तो पैरामीटर हटा दिए जाते हैं या मूल फ़ॉरवर्ड घोषणा के बिल्कुल समान होने चाहिए, या एक त्रुटि चिह्नित की जाएगी।
प्री-प्रोसेसर रिकर्सन
जटिल डेटा समुच्चय की घोषणा करते समय, विषम और सम कार्यों का संभावित उपयोग उत्पन्न हो सकता है। शायद यदि किसी डेटा समुच्चय उपरोक्त के अनुसार ऑड और ईवन की समतुल्य घोषणाओं को देखते हुए, संभवतः आगे की घोषणा की आवश्यकता नहीं होगी क्योंकि पैरामीटर का उपयोग प्री-प्रोसेसर को ज्ञात है जो संदर्भ और मूल्य के बीच चयन करने के अवसर प्रदान करने की संभावना नहीं है। हालाँकि, उनकी वास्तविक परिभाषा के बाद तक स्रोत कोड (उनकी परिभाषाओं के बाहर) में इन कार्यों का कोई आह्वान नहीं हो सकता है, क्योंकि आह्वान के परिणाम को जानना आवश्यक है। जब तक कि प्री-प्रोसेसर अपनी स्रोत फ़ाइल के कई पासों में संलग्न न हो।
अग्रेषित घोषणाएँ हानिकारक मानी जाती हैं
जिस किसी ने भी एक बड़े कार्यक्रम में प्रक्रियाओं की घोषणाओं और उपयोगों और दिनचर्या के पुस्तकालयों के उपयोग के बीच सुसंगतता बनाए रखने का प्रयास किया है, विशेष रूप से परिवर्तन से गुजरने वाली प्रक्रियाओं के लिए आगे या इसी तरह की अतिरिक्त घोषणाओं के उपयोग पर संघर्ष किया होगा, लेकिन परिभाषित नहीं किया गया है वर्तमान संकलन. व्यापक रूप से अलग-अलग स्थानों, विशेष रूप से विभिन्न स्रोत फ़ाइलों के बीच तालमेल बनाए रखने के लिए परिश्रम की आवश्यकता होती है। आरक्षित शब्द का उपयोग करने वाली उन घोषणाओं को ढूंढना आसान है, लेकिन यदि सहायक घोषणाओं को सामान्य घोषणाओं से अलग नहीं किया जाता है, तो कार्य परेशानी भरा हो जाता है। कथित रूप से तेज़ संकलन का लाभ तब अपर्याप्त लग सकता है जब केवल एक-पास संकलन के लक्ष्य को छोड़ने से यह अधिरोपण दूर हो जाएगा।
यह भी देखें
- एल्गोल 68आर
- बड़े सिस्टम बरोज़#ALGOL
- नेलियाक
- एक्सपीएल
संदर्भ
- ↑ "सिंगल पास, टू पास और मल्टी पास कंपाइलर". GeeksforGeeks (in English). 2019-03-13. Retrieved 2023-05-15.