2016-02-14 4 views
18

सी ++ में, प्रतीकों '<' और '>' प्रतीकों के साथ-साथ टेम्पलेट तर्क को इंगित करने के लिए उपयोग किए जाते हैं। इस प्रकार, कोड स्निपेटसी ++ के लिए एक पार्सर तुलना और टेम्पलेट तत्काल के बीच अंतर कैसे करता है?

[...] Foo <Bar> [...] 

निम्नलिखित दो तरीकों में से किसी रूप में समझा जा सकता है:

  • टेम्पलेट तर्क बार के साथ प्रकार फू की एक वस्तु
  • फू बार से तुलना करें, तो परिणाम की तुलना जो कुछ भी आता है

सी ++ कंपाइलर के लिए पार्सर उन दो संभावनाओं के बीच कुशलतापूर्वक निर्णय कैसे लेता है?

+0

एलएल व्याकरण की जांच करके आप क्या देख सकते हैं इसका एक अच्छा विचार हो सकता है। ;-) – Caduchon

+1

@ कैडचॉन AFAIK सी ++ व्याकरण एलएल और न ही एलआर है। असल में मेरा मानना ​​है कि यह संदर्भ-मुक्त नहीं है; यह उस उत्तर में संकेत दिया गया है जहां संदर्भ के बारे में ज्ञान सही ढंग से विश्लेषण करने के लिए आवश्यक लगता है। – Bakuriu

+0

@ बाकुरीयू: अधिकांश पारंपरिक व्याकरण (एकल-nonterminal बाएं हाथ की तरफ) परिभाषा के अनुसार संदर्भ मुक्त हैं। सी ++ इसे नहीं बदलता है। सिंटैक्स की व्याख्या अधिकांश लैंगुगों के लिए अभ्यास में मुक्त नहीं है। इस संबंध में सी ++ अलग नहीं है। –

उत्तर

12

Foo एक टेम्पलेट नाम (जैसे एक template <...> Foo ... घोषणा दायरे में है, या संकलक एक template Foo अनुक्रम देखता है) हो जाता है, तो Foo < Bar नहीं एक तुलना हो सकती है। यह एक टेम्पलेट त्वरण की शुरुआत होनी चाहिए (या जो भी Foo <Bar> इस सप्ताह कहा जाता है)।

यदि Foo एक टेम्पलेट नाम नहीं है, तो Foo < Bar तुलना है।

ज्यादातर मामलों में यह ज्ञात है कि Foo है, क्योंकि पहचानकर्ताओं को आमतौर पर उपयोग से पहले घोषित किया जाना चाहिए, इसलिए एक तरफ या दूसरे को तय करने में कोई समस्या नहीं है। हालांकि एक अपवाद है: टेम्पलेट कोड पार्सिंग। यदि Foo<Bar> एक टेम्पलेट के अंदर है, और Foo का अर्थ टेम्पलेट पैरामीटर पर निर्भर करता है, तो यह ज्ञात नहीं है कि Foo एक टेम्पलेट है या नहीं। व्यवहार करने के लिए भाषा मानक निर्देश गैर-टेम्पलेट के रूप में है जब तक कि कीवर्ड template से पहले नहीं।

पार्सर संदर्भ वापस lexer को खिला द्वारा यह लागू हो सकता है। लेजर द्वारा प्रदान किए गए संदर्भ के आधार पर लेजर Foo को विभिन्न प्रकार के टोकन के रूप में मान्यता देता है।

+0

जोड़ने के लिए यह उत्तर: जब कंपाइलर में संदर्भ नहीं है, उदाहरण के लिएजब 'Foo' एक आश्रित नाम है, तो आपको कंपाइलर को यह बताने की आवश्यकता है कि यह एक टेम्पलेट है: 'टेम्पलेट Foo ' –

+0

@Revolver_Ocelot धन्यवाद, इस पर विस्तार किया गया। –

+0

मैं देखता हूं। इसलिए सी ++ में सब कुछ इस्तेमाल होने से पहले घोषित किया जाना चाहिए, लेक्सर और पार्सर चरणों को अंतःस्थापित किया जा सकता है, और पार्सर लगातार वर्तमान प्रकार और चर नामों को लेक्सर में वापस खिलाता है ताकि यह सबसे संभावित टोकन उत्पन्न कर सके, या तो * पहचानकर्ता * या * पहचान पहचानकर्ता *, सही? और यदि यह अनावश्यक है, तो प्रोग्रामर को "टेम्पलेट" कीवर्ड के साथ * प्रकार पहचानकर्ता * को उपसर्ग करना होगा। – Askaga

5

सी और सी ++ पार्सर्स "संदर्भ संवेदनशील" हैं, दूसरे शब्दों में, दिए गए टोकन या लेक्समे के लिए, यह विशिष्ट होने की गारंटी नहीं है और केवल एक ही अर्थ है - यह उस संदर्भ पर निर्भर करता है जिसमें टोकन का उपयोग किया जाता है।

तो, कंपाइलर का पार्सर हिस्सा ("स्रोत में कहां है" को समझकर) यह समझ जाएगा कि यह किसी प्रकार का प्रकार या किसी प्रकार की तुलना को पार्स कर रहा है (यह जानना आसान नहीं है, यही कारण है कि सक्षम सी या सी ++ संकलक का स्रोत पढ़ने पूरी तरह से सीधे आगे नहीं है - वहाँ की स्थिति के बहुत सारे हैं और समारोह की जाँच कॉल) "इन में से एक यदि ऐसा है तो यह करते हैं, बाकी कुछ और है,"।

कीवर्ड template संकलक को समझने में मदद करता है कि क्या हो रहा है, लेकिन ज्यादातर मामलों में, कंपाइलर बस जानता है क्योंकि < अन्य पहलू में समझ में नहीं आता है - और यदि यह किसी भी रूप में समझ में नहीं आता है, तो यह एक त्रुटि है, तो फिर यह पता लगाना है कि प्रोग्रामर चाहता था हो सकता है की कोशिश कर रहा का मामला है - और इस कारण यह है कि कभी कभी, एक साधारण ग़लती जैसे एक लापता } या template पूरे पार्स भटक नेतृत्व कर सकते हैं और परिणाम है सैकड़ों या त्रुटियों के हजारों में

9

महत्वपूर्ण बात को याद है कि सी ++ व्याकरण नहीं है [हालांकि समझदार compilers एक उचित संख्या में बंद हो जाएं त्रुटि संदेश के साथ पूरे ब्रह्मांड भर नहीं करने के लिए] विषय से मुक्त। अर्थात।, जब पार्सर Foo < Bar (ज्यादातर मामलों में) जानता है कि Foo एक टेम्पलेट परिभाषा (प्रतीक तालिका में इसे देखकर) को संदर्भित करता है, और इस प्रकार < तुलना नहीं हो सकता है।

कठिन मामले हैं, जब आपको सचमुच पार्सर को मार्गदर्शन करना होता है। उदाहरण के लिए, मान लीजिए कि टेम्पलेट सदस्य फ़ंक्शन के साथ क्लास टेम्पलेट लिख रहे हैं, जिसे आप स्पष्ट रूप से विशेषज्ञ बनाना चाहते हैं। (; जानकारी के लिए Calling template function within template class देखने के कुछ मामलों में)

इसके अलावा, गैर प्रकार टेम्पलेट तर्क के अंदर तुलना, यानी कोष्ठकों से घिरा होना चाहिए

a->template foo<int>(); 

:

foo<(A > B)> 
की तरह आप सिंटैक्स का उपयोग करना पड़ सकता है

नहीं

foo<A > B> 

गैर स्थिर डेटा सदस्य पहल lizers अधिक मज़ा लाने: http://open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#325

2

जवाब यहां प्रतीक पार्स करने साथ (मैं क्या "नाम संकल्प" कहते हैं) के अर्थ का निर्धारण भ्रमित के अधिकांश (बाल बाल के रूप में "कार्यक्रम की वाक्य रचना पढ़ सकते हैं" परिभाषित)।

आप do these tasks separately. कर सकते हैं।

इसका मतलब यह है कि आप सी ++ (मेरी कंपनी, अर्थात् डिज़ाइन करता है) के लिए एक पूरी तरह से संदर्भ मुक्त पार्सर बना सकते हैं, और यह तय करने के मुद्दों को छोड़ सकते हैं कि प्रतीक का अर्थ स्पष्ट रूप से अलग कार्य के लिए क्या है।

अब, यह कार्य स्रोत कोड की संभावित वाक्यविन्यास व्याख्याओं द्वारा संचालित है। हमारे पार्सर्स में, इन्हें पार्स में अस्पष्टता के रूप में कैप्चर किया जाता है।

नामों की घोषणाओं के बारे में जानकारी एकत्र करने का नाम क्या है, और उस जानकारी का उपयोग यह निर्धारित करने के लिए करें कि कौन से अस्पष्ट पार्स समझ में नहीं आते हैं, और बस उन्हें छोड़ दें। एक वैध वैध व्याख्या के साथ, एक वैध पारदर्शी बनी हुई है।

अभ्यास में नाम समाधान पूरा करने के लिए मशीनरी एक बड़ी गड़बड़ है। लेकिन यह सी ++ कमेटी की गलती है, न कि पार्सर या नाम रिज़ॉल्वर। हमारे उपकरण के साथ अस्पष्टता को हटाने वास्तव में स्वचालित रूप से किया जाता है, जिससे वह हिस्सा वास्तव में बहुत अच्छा होता है लेकिन यदि आप हमारे उपकरण के अंदर नहीं देखते हैं तो आप इसकी सराहना नहीं करेंगे, लेकिन हम ऐसा इसलिए करते हैं क्योंकि इसका मतलब है कि एक छोटी इंजीनियरिंग टीम इसे बनाने में सक्षम थी।

See an example of resolution of template-vs-less than on C++s most vexing parse हमारे पार्सर द्वारा किया गया।

संबंधित मुद्दे