प्रोग्रामिंग भाषा के लिए बुनियादी, सामान्य व्याख्याता
मैं पिछले कुछ दिनों से एक प्रोग्रामिंग भाषा के सामान्य लेक्सर पर काम कर रहा हूं। मुझे नहीं पता कि मैंने जो कोड लिखा है वह बहुत जटिल है, क्या कोड को टोकन में पार्स करने का कोई बेहतर तरीका है या क्या मेरे कोड को लाइब्रेरी के साथ आसान बनाया जा सकता है।
कोड:
कई स्थानों पर आपके पास समान कोड है:
आप एक सूची बना रहे हैं जिसके तत्व प्रिंट फ़ंक्शन को कॉल करने से रिटर्न मान होंगे। और आप इस सूची के साथ क्या कर रहे हैं? निःसंदेह, कुछ भी नहीं। तो फिर सूची क्यों बनाएं? कोडिंग की यह शैली गैर-पायथनिक है (अक्षम होने का उल्लेख नहीं है)। बस यह करें:
आपके कोड में कई प्रिंट कॉल हैं जो डिबगिंग उद्देश्यों के लिए प्रतीत होती हैं। उदाहरण के लिए:
यदि ऐसा है, तो लॉगिंग एपीआई का उपयोग करना बेहतर होगा। उदाहरण के लिए:
आपके पास:
एक शाब्दिक विश्लेषक के बीच एक बड़ा अंतर है, जो आम तौर पर उन टोकन को पहचानता है जिन्हें एक नियमित भाषा (या समकक्ष, एक नियमित अभिव्यक्ति) का उपयोग करके परिभाषित किया जा सकता है और पार्सर जो उन टोकन को पार्स करने के लिए उन टोकन का उपयोग करता है, उदाहरण के लिए, व्याकरण पर आधारित एक अमूर्त वाक्यविन्यास वृक्ष, जो सामान्य तौर पर नियमित नहीं होता है। लंबी कहानी को संक्षिप्त करने के लिए, लेक्सर उदाहरण के लिए एक बेहतर नाम लेक्सर होगा। इसी तरह, मैं विधि पार्स का नाम बदलकर लेक्स (पार्स के अलावा कुछ और) करने का सुझाव देता हूं।
आपके पास है:
हमें वास्तव में शामिल होने के लिए एक सूची बनाने की आवश्यकता नहीं है:
< br>ध्यान दें कि मैंने वेरिएबल i का नाम बदलकर अधिक सार्थक टोकन (और पार्सर से लेक्सर) कर दिया है। आपकी भाषा जो होगी आपके पार्सर द्वारा पार्स किया गया। मान लीजिए कि हमारा पार्सर एलएएलआर (1) व्याकरण पर आधारित होगा। एक एलएएलआर (1) पार्सर "वर्तमान स्थिति संख्या" और "वर्तमान लेक्सिकल टोकन" द्वारा अनुक्रमित दो आयामी तालिका द्वारा संचालित होता है। जिनमें से पूर्णांक हैं। टोकन की आपकी परिभाषा (आंशिक रूप से) है:
जहां आप दावा करते हैं कि प्रकार विशेषता एक पूर्णांक है, लेकिन जब आप टोकन को इंस्टेंट करते हैं, तो आप कोड करते हैं है:
लेकिन टोकनटाइप्स enum.Enum का एक उपवर्ग है:
परिणामस्वरूप टोकनटाइप.NUMBER कोई बड़ी बात नहीं है, वैसे भी, यह कुछ ऐसा है जिसे मैंने पकड़ लिया है। आप अभिव्यक्ति टोकनटाइप.NUMBER.वैल्यू के साथ एक पूर्णांक मान प्राप्त कर सकते हैं, जो कि महत्वपूर्ण है और इसलिए टोकनटाइप की यह परिभाषा बिल्कुल ठीक है। लेकिन आमतौर पर कोई व्याकरण से शुरुआत करता है, जिससे टोकन प्राप्त किए जा सकते हैं। व्याकरण को कोड करने वाला व्यक्ति और लेक्सर को कोड करने वाला व्यक्ति एक ही व्यक्ति नहीं हो सकते हैं। तो पार्सर जनरेटर चलाने से निकलने वाले आउटपुट में से एक आमतौर पर एक मॉड्यूल होता है जिसे टोकन को परिभाषित करते हुए आयात किया जा सकता है। आमतौर पर, यह इस तरह दिखने वाली एक फ़ाइल हो सकती है:
तो वास्तविक जीवन में आपकी टोकन परिभाषाएँ संभवतः आपके द्वारा आयात किए गए मॉड्यूल के भीतर होंगी।
पार्सर आम तौर पर एक ही बार में सभी टोकन का अनुरोध नहीं करता है बल्कि अगला टोकन प्राप्त करने के लिए lexer.next_token() जैसी विधि को कॉल करता है। यदि आप यह उपलब्ध कराते तो अच्छा होता. इसे बस इस प्रकार कार्यान्वित किया जा सकता है:
आपको एक अतिरिक्त टोकन भी परिभाषित करना चाहिए, जिसे हम ईओएफ कह सकते हैं, जो इनपुट के अंत का प्रतिनिधित्व करता है:
तो अब हमारी अगली_टोकन विधि होगी:
इसका उद्देश्य यह सुनिश्चित करना है कि टोकन की एक धारा के बाद कोई बाहरी टोकन न हो जिसे व्याकरण के वाक्य में पार्स किया जा सके। उदाहरण के लिए, यदि हमारे पास व्याकरण होता:
मान्य इनपुट हो सकता है: "1 + 3" लेकिन "1 + 3 + 4" नहीं। सिर्फ इसलिए कि हम एक अभिव्यक्ति में टोकन "1", "+" और "3" को कम करने में सक्षम थे, इसका मतलब यह नहीं है कि इनपुट वैध था। इसलिए हम आम तौर पर एक "संवर्धित" व्याकरण का उपयोग करते हैं:
अब हमारे पास एक नया लक्ष्य प्रतीक, अभिव्यक्ति_प्राइम है, जो "1 + 3 + 4 ईओएफ" को अस्वीकार कर देगा लेकिन "1 + 3 ईओएफ" को स्वीकार कर लेगा।
br>क्या होगा यदि अपने शाब्दिक विश्लेषण करते समय आप एक गलत गठित टोकन (उदाहरण के लिए एक स्ट्रिंग जो ठीक से समाप्त नहीं हुई है) पर आते हैं? लेक्सर और पार्सर के पास ERROR नामक एक अतिरिक्त टोकन प्रकार होना चाहिए, जिसे अवैध टोकन मिलने पर लेक्सर वापस कर देता है। व्याकरण में आम तौर पर लेक्सर या पार्सर द्वारा खोजी गई त्रुटियों को संभालने के लिए विशेष उत्पादन शामिल होंगे