मैं एक मार्कअप भाषा के लिए एक पार्सर लिख रहा हूं जिसे मैंने बनाया है (अजगर में लेखन, लेकिन यह वास्तव में इस प्रश्न के लिए प्रासंगिक नहीं है - वास्तव में अगर यह एक बुरे विचार की तरह लगता है, तो मुझे बेहतर रास्ते के लिए एक सुझाव पसंद आएगा) ।
मैं यहां पार्सर्स के बारे में पढ़ रहा हूं: http://www.ferg.org/parsing/index.html , और मैं लेक्सर लिखने पर काम कर रहा हूं, जिसे अगर मुझे सही तरीके से समझ में आता है, तो सामग्री को टोकन में विभाजित करें। मुझे यह समझने में परेशानी हो रही है कि मुझे किस प्रकार के टोकन का उपयोग करना चाहिए या उन्हें कैसे बनाना चाहिए। उदाहरण के लिए, मेरे द्वारा लिंक किए गए उदाहरण में टोकन प्रकार हैं:
- STRING
- IDENTIFIER
- संख्या
- खाली स्थान के
- टिप्पणी
- EOF
- कई प्रतीक जैसे {और (अपने स्वयं के टोकन प्रकार के रूप में गिना जाता है
मुझे जो समस्या हो रही है, वह यह है कि अधिक सामान्य टोकन मेरे लिए थोड़े अनियंत्रित लगते हैं। उदाहरण के लिए, STRING का अपना अलग टोकन प्रकार बनाम IDENTIFIER क्यों है। एक स्ट्रिंग को STRING_START + (IDENTIFIER | WHITESPACE) + STRING_START के रूप में दर्शाया जा सकता है।
यह मेरी भाषा की कठिनाइयों के साथ भी हो सकता है। उदाहरण के लिए, परिवर्तनशील घोषणाएँ लिखी जाती हैं {var-name var value}
और उनके साथ तैनात की जाती हैं {var-name}
। ऐसा लगता है '{'
और '}'
उनके स्वयं के टोकन होने चाहिए, लेकिन क्या VAR_NAME और VAR_VALUE टोकन प्रकार हैं, या ये दोनों IDENTIFIER के अंतर्गत आएंगे? क्या अधिक है कि VAR_VALUE में वास्तव में व्हॉट्सएप हो सकता है। के बाद व्हाट्सएप var-name
का उपयोग घोषणा में मूल्य की शुरुआत को इंगित करने के लिए किया जाता है .. किसी अन्य व्हाट्सएप का मूल्य का हिस्सा है। क्या यह व्हॉट्सएप अपना टोकन बन गया है? इस संदर्भ में व्हॉट्सएप का केवल वही अर्थ है। इसके अलावा, {
एक चर घोषणा की शुरुआत नहीं हो सकती है .. यह संदर्भ पर निर्भर करता है (फिर से वह शब्द है!)। {:
एक नाम घोषणा शुरू करता है, और{
कुछ मूल्य के हिस्से के रूप में भी इस्तेमाल किया जा सकता है।
मेरी भाषा पायथन के समान है, जिसमें ब्लॉक इंडेंटेशन के साथ बनाए गए हैं। मैं पढ़ रहा था कि कैसे अजगर इंडेंट और डेडेंट टोकन बनाने के लिए लेसर का उपयोग करता है (जो कि कम या ज्यादा के रूप में सेवा करता है {
और }
बहुत सारी अन्य भाषाओं में क्या करेगा)। पायथन संदर्भ-मुक्त होने का दावा करता है, जिसका अर्थ है कि कम से कम लेक्सर को इस बात की परवाह नहीं करनी चाहिए कि टोकन बनाते समय यह धारा में कहाँ है। पायथन के लेक्सर को कैसे पता चलता है कि यह पिछले वर्णों के बारे में जाने बिना एक विशिष्ट लंबाई का एक इंडेंट टोकन बना रहा है (जैसे कि पिछली पंक्ति एक नई रेखा थी, इसलिए INDENT के लिए रिक्त स्थान बनाना शुरू करें)? मैं पूछता हूं क्योंकि मुझे यह जानना भी आवश्यक है।
मेरा अंतिम प्रश्न सबसे बेवकूफ़ है: क्यों एक लेक्सर भी आवश्यक है? यह मुझे लगता है कि पार्सर चरित्र-दर-चरित्र जा सकता है और यह पता लगा सकता है कि यह कहां है और यह क्या उम्मीद करता है। क्या लेक्सर सादगी का लाभ जोड़ता है?