नीचे मेरा (वर्तमान) पसंदीदा प्रदर्शन है कि पार्सिंग सी ++ क्यों (शायद) ट्यूरिंग-पूर्ण है , क्योंकि यह एक प्रोग्राम दिखाता है जो सिंटैक्टिक रूप से सही है यदि और केवल यदि एक पूर्णांक अभाज्य है।
इसलिए मैं जोर देकर कहता हूं कि C ++ न तो संदर्भ-मुक्त है और न ही संदर्भ-संवेदनशील है ।
यदि आप किसी भी उत्पादन के दोनों किनारों पर मनमाने ढंग से प्रतीक अनुक्रम की अनुमति देते हैं, तो आप चॉम्स्की पदानुक्रम में एक टाइप -० व्याकरण ("अप्रतिबंधित") का उत्पादन करते हैं , जो संदर्भ-संवेदनशील व्याकरण की तुलना में अधिक शक्तिशाली है; अप्रतिबंधित व्याकरण ट्यूरिंग-पूर्ण है। एक संदर्भ-संवेदनशील (टाइप -1) व्याकरण एक उत्पादन के बाएं हाथ के संदर्भ के कई प्रतीकों की अनुमति देता है, लेकिन उसी संदर्भ को उत्पादन के दाहिने हाथ की ओर दिखाई देना चाहिए (इसलिए नाम "संदर्भ-संवेदनशील")। [१] प्रसंग-संवेदी व्याकरण रैखिक-बाउंड ट्यूरिंग मशीनों के बराबर हैं ।
उदाहरण कार्यक्रम में, अभिकलन-बद्ध ट्यूरिंग मशीन द्वारा अभिकलन किया जा सकता है, इसलिए यह ट्यूरिंग तुल्यता साबित नहीं करता है, लेकिन महत्वपूर्ण बात यह है कि क्रमिक विश्लेषण करने के लिए पार्सर को अभिकलन करने की आवश्यकता है। यह टेम्पलेट तात्कालिकता के रूप में व्यक्त की जाने वाली कोई संगणना हो सकती है और यह मानने का हर कारण है कि C ++ टेम्पलेट तात्कालिकता ट्यूरिंग-पूर्ण है। उदाहरण के लिए देखें, टोड एल। वेल्डहुइज़न का 2003 का पेपर ।
भले ही, C ++ को कंप्यूटर द्वारा पार्स किया जा सकता है, इसलिए यह निश्चित रूप से ट्यूरिंग मशीन द्वारा पार्स किया जा सकता है। नतीजतन, एक अप्रतिबंधित व्याकरण इसे पहचान सकता है। वास्तव में ऐसा व्याकरण लिखना अव्यावहारिक होगा, यही कारण है कि मानक ऐसा करने की कोशिश नहीं करता है। (निचे देखो।)
कुछ अभिव्यक्तियों की "अस्पष्टता" वाला मुद्दा ज्यादातर एक लाल हेरिंग है। शुरुआत करने के लिए, अस्पष्टता एक विशेष व्याकरण की एक विशेषता है, न कि एक भाषा। भले ही कोई भाषा किसी भी प्रकार के अस्पष्ट व्याकरण से सिद्ध नहीं की जा सकती है, अगर उसे संदर्भ-मुक्त व्याकरण द्वारा मान्यता दी जा सकती है, तो यह संदर्भ-मुक्त है। इसी तरह, अगर इसे संदर्भ-मुक्त व्याकरण द्वारा मान्यता नहीं दी जा सकती है, लेकिन इसे संदर्भ-संवेदनशील व्याकरण द्वारा मान्यता दी जा सकती है, तो यह संदर्भ-संवेदनशील है। अस्पष्टता प्रासंगिक नहीं है।
लेकिन किसी भी घटना में, जैसे auto b = foo<IsPrime<234799>>::typen<1>();
कि कार्यक्रम में लाइन 21 (यानी ), भाव बिल्कुल भी अस्पष्ट नहीं हैं; वे केवल संदर्भ के आधार पर अलग तरह से पार्स किए जाते हैं। समस्या की सरलतम अभिव्यक्ति में, कुछ विशिष्ट पहचानकर्ताओं की श्रेणीबद्धता इस बात पर निर्भर करती है कि उन्हें कैसे घोषित किया गया है (प्रकार और कार्य, उदाहरण के लिए), जिसका अर्थ है कि औपचारिक भाषा को इस तथ्य को पहचानना होगा कि दो मनमाना लंबाई समान कार्यक्रम समान हैं (घोषणा और उपयोग)। इसे "कॉपी" व्याकरण द्वारा मॉडल किया जा सकता है, जो कि व्याकरण है जो एक ही शब्द की दो लगातार सटीक प्रतियों को पहचानता है। पम्पिंग लेम्मा के साथ यह साबित करना आसान हैयह भाषा संदर्भ-मुक्त नहीं है। इस भाषा के लिए एक संवेदी-संवेदनशील व्याकरण संभव है, और इस प्रश्न के उत्तर में एक टाइप -० व्याकरण प्रदान किया गया है: /math/163830/context-sensitive-grammar-for-the-the- कॉपी-भाषा ।
यदि कोई सी ++ को पार्स करने के लिए एक संदर्भ-संवेदनशील (या अप्रतिबंधित) व्याकरण लिखने का प्रयास करता है, तो यह संभवतः ब्रह्मांड को स्क्रिबब्लिंग्स से भर देगा। C ++ को पार्स करने के लिए ट्यूरिंग मशीन लिखना एक समान रूप से असंभव उपक्रम होगा। यहां तक कि सी ++ प्रोग्राम लिखना भी मुश्किल है, और जहां तक मुझे पता है कि कोई भी सही साबित नहीं हुआ है। यही कारण है कि मानक एक पूर्ण औपचारिक व्याकरण प्रदान करने का प्रयास नहीं करता है, और यह तकनीकी अंग्रेजी में कुछ पार्सिंग नियमों को लिखने का विकल्प क्यों चुनता है।
सी ++ मानक में एक औपचारिक व्याकरण जैसा दिखता है, सी ++ भाषा के वाक्यविन्यास की पूरी औपचारिक परिभाषा नहीं है। यह प्रीप्रोसेसिंग के बाद भाषा की पूरी औपचारिक परिभाषा भी नहीं है, जिसे औपचारिक रूप देना आसान हो सकता है। (यह भाषा नहीं होगी, हालांकि: मानक द्वारा परिभाषित C ++ भाषा में प्रीप्रोसेसर शामिल है, और प्रीप्रोसेसर के संचालन को एल्गोरिदम के रूप में वर्णित किया गया है क्योंकि यह किसी भी व्याकरणिक औपचारिकता में वर्णन करना बहुत कठिन होगा। यह उस अनुभाग में है। मानक जहां लेक्सिकल अपघटन का वर्णन किया गया है, उन नियमों सहित जहां इसे एक से अधिक बार लागू किया जाना चाहिए।)
विभिन्न व्याकरण (लेक्सिकल विश्लेषण के लिए दो अतिव्यापी व्याकरण, एक जो प्रीप्रोसेसिंग से पहले होता है और दूसरा, यदि आवश्यक हो, बाद में, "सिंटैक्टिक" व्याकरण) को इस महत्वपूर्ण नोट के साथ परिशिष्ट ए में एकत्र किया जाता है (जोर जोड़ा):
C ++ सिंटैक्स का यह सारांश समझ में सहायता के लिए है। यह भाषा का सटीक विवरण नहीं है । विशेष रूप से, यहाँ वर्णित व्याकरण मान्य C ++ निर्माण के एक सुपरसेट को स्वीकार करता है । घोषणा से अभिव्यक्ति को अलग करने के लिए वितरण नियम (6.8, 7.1, 10.2) लागू होना चाहिए। इसके अलावा, अभिगम नियंत्रण, अस्पष्टता, और प्रकार के नियमों का उपयोग सिंटैक्टिक रूप से मान्य लेकिन अर्थहीन निर्माणों को हटाने के लिए किया जाना चाहिए।
अंत में, यहाँ वादा किया कार्यक्रम है। पंक्ति 21 वाक्यविन्यास रूप से सही है यदि और केवल यदि N IsPrime<N>
प्राइम है। अन्यथा, typen
एक पूर्णांक है, कोई टेम्पलेट नहीं है, इसलिए typen<1>()
इसे पार्स किया गया है, (typen<1)>()
जो कि वाक्यविन्यास रूप से गलत है क्योंकि ()
एक वाक्यात्मक रूप से मान्य अभिव्यक्ति नहीं है।
template<bool V> struct answer { answer(int) {} bool operator()(){return V;}};
template<bool no, bool yes, int f, int p> struct IsPrimeHelper
: IsPrimeHelper<p % f == 0, f * f >= p, f + 2, p> {};
template<bool yes, int f, int p> struct IsPrimeHelper<true, yes, f, p> { using type = answer<false>; };
template<int f, int p> struct IsPrimeHelper<false, true, f, p> { using type = answer<true>; };
template<int I> using IsPrime = typename IsPrimeHelper<!(I&1), false, 3, I>::type;
template<int I>
struct X { static const int i = I; int a[i]; };
template<typename A> struct foo;
template<>struct foo<answer<true>>{
template<int I> using typen = X<I>;
};
template<> struct foo<answer<false>>{
static const int typen = 0;
};
int main() {
auto b = foo<IsPrime<234799>>::typen<1>(); // Syntax error if not prime
return 0;
}
[१] इसे अधिक तकनीकी रूप से रखने के लिए, एक संदर्भ-संवेदनशील व्याकरण में प्रत्येक उत्पादन का रूप होना चाहिए:
αAβ → αγβ
जहां A
एक गैर टर्मिनल और है α
, β
संभवतः व्याकरण प्रतीकों में से खाली दृश्यों रहे हैं, और γ
एक गैर खाली अनुक्रम है। (व्याकरण के प्रतीक या तो टर्मिनल या गैर-टर्मिनल हो सकते हैं)।
इसे A → γ
केवल संदर्भ में पढ़ा जा सकता है [α, β]
। एक संदर्भ-मुक्त (टाइप 2) व्याकरण में, α
और β
खाली होना चाहिए।
यह पता चला है कि आप व्याकरण को "मोनोटोनिक" प्रतिबंध के साथ प्रतिबंधित कर सकते हैं, जहां हर उत्पादन फॉर्म का होना चाहिए:
α → β
जहां |α| ≥ |β| > 0
( |α|
मतलब "की लंबाई α
")
यह साबित करना संभव है कि मोनोटोनिक व्याकरण द्वारा मान्यता प्राप्त भाषाओं का सेट बिल्कुल वैसा ही है जैसा कि संदर्भ-संवेदनशील व्याकरण द्वारा मान्यता प्राप्त भाषाओं का सेट है, और यह अक्सर मामला है कि यह मोनोटोनिक व्याकरण पर आधार प्रमाणों के लिए आसान है। नतीजतन, यह "संदर्भ-संवेदनशील" देखने के लिए बहुत आम है क्योंकि इसका मतलब "मोनोटोनिक" था।