(यह मेरे इच्छित से अधिक लंबा है; कृपया मेरे साथ सहन करें।)
अधिकांश भाषाएं कुछ "सिंटैक्स" से बनी होती हैं: भाषा कई अच्छी तरह से परिभाषित कीवर्ड से युक्त होती है, और उस भाषा में आपके द्वारा बनाई जा सकने वाली अभिव्यक्तियों की पूरी श्रृंखला उस सिंटैक्स से निर्मित होती है।
उदाहरण के लिए, मान लें कि आपके पास एक साधारण चार-फ़ंक्शन अंकगणित "भाषा" है, जो इनपुट के रूप में केवल एकल-अंक पूर्णांक लेता है और संचालन के आदेश को पूरी तरह से अनदेखा करता है (मैंने आपको बताया कि यह एक सरल भाषा थी)। उस भाषा को वाक्य रचना द्वारा परिभाषित किया जा सकता है:
// The | means "or" and the := represents definition
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /
इन तीन नियमों से, आप किसी भी संख्या में एकल-अंक-इनपुट अंकगणितीय अभिव्यक्तियों का निर्माण कर सकते हैं। इसके बाद आप इस वाक्य रचना के लिए एक पार्सर लिख सकते हैं कि उसके घटक प्रकार में किसी भी मान्य इनपुट (नीचे टूट जाता है $expression
, $number
या $operator
परिणाम के साथ) और संबंधित है। उदाहरण के लिए, अभिव्यक्ति 3 + 4 * 5
को निम्नानुसार तोड़ा जा सकता है:
// Parentheses used for ease of explanation; they have no true syntactical meaning
$expression = 3 + 4 * 5
= $expression $operator (4 * 5) // Expand into $exp $op $exp
= $number $operator $expression // Rewrite: $exp -> $num
= $number $operator $expression $operator $expression // Expand again
= $number $operator $number $operator $number // Rewrite again
अब हमारे पास मूल अभिव्यक्ति के लिए, हमारी परिभाषित भाषा में एक पूरी तरह से व्यवस्थित वाक्य रचना है। एक बार जब हमारे पास यह हो जाता है, तो हम एक संयोजन के माध्यम से जा सकते हैं और सभी संयोजनों के परिणामों को खोजने के लिए एक परिणाम लिख सकते हैं $number $operator $number
, और एक परिणाम $number
छोड़ सकते हैं जब हमारे पास केवल एक ही होता है ।
ध्यान दें कि $expression
हमारी मूल अभिव्यक्ति के अंतिम पार्स संस्करण में कोई निर्माण नहीं बचा है। ऐसा इसलिए है क्योंकि $expression
हमेशा हमारी भाषा में अन्य चीजों के संयोजन को कम किया जा सकता है।
PHP बहुत समान है: भाषा निर्माण हमारे $number
या के बराबर के रूप में पहचाने जाते हैं $operator
। उन्हें अन्य भाषा निर्माणों में कम नहीं किया जा सकता है ; इसके बजाय, वे आधार इकाइयाँ हैं जिनसे भाषा निर्मित होती है। फ़ंक्शंस और भाषा निर्माणों के बीच महत्वपूर्ण अंतर यह है: पार्सर सीधे भाषा निर्माणों से संबंधित है। यह भाषा निर्माण में कार्यों को सरल बनाता है।
कारण यह है कि भाषा का निर्माण कोष्ठकों की आवश्यकता हो सकती है या नहीं हो सकती है और कुछ का रिटर्न मान है जबकि अन्य पूरी तरह से PHP पार्सर कार्यान्वयन के विशिष्ट तकनीकी विवरण पर निर्भर नहीं करते हैं। मैं उस अच्छी तरह से वाकिफ नहीं हूं कि पार्सर कैसे काम करता है, इसलिए मैं इन सवालों को विशेष रूप से संबोधित नहीं कर सकता, लेकिन एक दूसरी भाषा के लिए कल्पना करें जो इस पर शुरू होती है:
$expression := ($expression) | ...
प्रभावी रूप से, यह भाषा किसी भी भाव को लेने और आसपास के कोष्ठकों से छुटकारा पाने के लिए स्वतंत्र है। PHP (और यहां मैं शुद्ध अनुमान लगा रहा हूं) अपनी भाषा के निर्माण के लिए कुछ समान काम कर सकता है: पार्स print("Hello")
करने print "Hello"
से पहले नीचे कम हो सकता है, या इसके विपरीत (भाषा की परिभाषाएं कोष्ठक जोड़ने के साथ-साथ उनसे छुटकारा भी पा सकती हैं)।
यह इस बात की जड़ है कि आप भाषा निर्माण को फिर से परिभाषित क्यों नहीं कर सकते हैं echo
या print
: वे प्रभावी रूप से पार्सर में हार्डकोड किए जाते हैं, जबकि फ़ंक्शन भाषा निर्माणों के एक सेट पर मैप किए जाते हैं और पार्सर आपको संकलन या रनटाइम पर उस मैपिंग को बदलने की अनुमति देता है भाषा निर्माण या अभिव्यक्ति के अपने सेट को स्थानापन्न करें।
दिन के अंत में, निर्माण और अभिव्यक्तियों के बीच आंतरिक अंतर यह है: भाषा निर्माणों को समझा जाता है और पार्सर द्वारा निपटा जाता है। बिल्ट-इन फ़ंक्शंस, जबकि भाषा द्वारा प्रदान किए गए हैं, मैप किए जाते हैं और पार्स करने से पहले भाषा के निर्माण के एक सेट के लिए सरलीकृत किया जाता है।
और जानकारी:
- बैकस-नौर रूप , औपचारिक भाषाओं को परिभाषित करने के लिए प्रयुक्त वाक्यविन्यास (yacc इस रूप का उपयोग करता है)
संपादित करें: कुछ अन्य उत्तरों के माध्यम से पढ़ना, लोग अच्छे अंक बनाते हैं। उनमें से:
- एक भाषा बिलियन एक फ़ंक्शन की तुलना में कॉल करने के लिए तेज़ है। यह सच है, अगर केवल मामूली रूप से, क्योंकि PHP दुभाषिया को पार्स करने से पहले उस फ़ंक्शन को उसके भाषा-निर्मित समकक्षों में मैप करने की आवश्यकता नहीं है। एक आधुनिक मशीन पर, हालांकि, यह अंतर काफी नगण्य है।
- एक भाषा अंतर्निहित त्रुटि-जाँच को बायपास करती है। प्रत्येक बिलिन के लिए PHP के आंतरिक कार्यान्वयन के आधार पर यह सच हो सकता है या नहीं भी हो सकता है। यह निश्चित रूप से सच है कि अधिक बार नहीं, फ़ंक्शंस में अधिक उन्नत त्रुटि-जांच और अन्य कार्यक्षमता होगी जो बिल्डिन नहीं करते हैं।
- भाषा निर्माण का उपयोग फ़ंक्शन कॉलबैक के रूप में नहीं किया जा सकता है। यह सच है, क्योंकि एक निर्माण एक फ़ंक्शन नहीं है । वे अलग संस्थाएँ हैं। जब आप एक बिलिन को कोड करते हैं, तो आप एक फ़ंक्शन को कोड नहीं कर रहे हैं जो तर्क लेता है - बिलिन के सिंटैक्स को सीधे पार्सर द्वारा संभाला जाता है, और फ़ंक्शन के बजाय एक बेसिन के रूप में पहचाना जाता है। (यह समझना आसान हो सकता है यदि आप प्रथम श्रेणी के कार्यों के साथ भाषाओं पर विचार करते हैं: प्रभावी रूप से, आप ऑब्जेक्ट के रूप में कार्यों को पास कर सकते हैं। आप बिलिंस के साथ ऐसा नहीं कर सकते।)