2010-08-12 12 views
10

मैं Boost.Spirit में एक शैल भाषा पार्सर लिखने की कोशिश कर रहा हूं। हालांकि, मैं rule एस के अर्थशास्त्र के संबंध में कुछ बुनियादी मुद्दों के बारे में अस्पष्ट हूं।बूस्ट :: भावना के नियम <> की प्रतिलिपि या संदर्भ अर्थशास्त्र?

प्रलेखन को देखते हुए, r.alias() और r.copy()rule के सदस्य हैं। IIUC, इन सदस्यों को नियम के संदर्भ और नियम की सामग्री की प्रतिलिपि क्रमशः वापस करनी चाहिए। हालांकि, यह स्पष्ट रूप से निर्दिष्ट नहीं किया गया है कि जब मैं किसी अन्य नियम की परिभाषा में नियम का उपयोग करता हूं तो क्या होता है। अपने प्रयोगों से, मैं परस्पर पाया पुनरावर्ती नियमों के द्वारा परिभाषित किया जा सकता है:

rule<Iter> r1, r2; 
r1 = ... >> r2 >> ...; 
r2 = ... >> r1 >> ...; 

जिससे पता चलता है नियम पार्सर भाव अंदर संदर्भ द्वारा लिया जाता है। समस्या यह है, क्या यह क्या करता है जब चर दायरे से बाहर चला जाता है, जैसे:

rule<Iter> r1; 
{ 
    rule<Iter> r2; 
    r1 = ... >> r2 >> ...; 
    r2 = ... >> r1 >> ...; 
} 
... // use r1 

एक ही नोट पर, प्रकार नियम काम का एक rvalue (r.copy() युक्त होगा एक पार्स अभिव्यक्ति से एक नियम को बताए हैं rule प्रकार का एक रावल्यू भी है, है ना? जैसे।

rule<Iter> f() { return char_('a') << char_('b'); } 
rule<Iter> r1 = ... << f(); 

किसी को भी मुझे rule की प्रतियां और संदर्भ की विस्तृत अर्थ विज्ञान पर प्रबुद्ध कर सकते हैं, और संभवतः इस पोस्ट में किसी भी गलतफहमी को दूर?

उत्तर

13

उत्तर इस बात पर निर्भर करता है कि आप किस आत्मा का जिक्र कर रहे हैं।


आत्मा। क्लासिक (पूर्व आत्मा V1.x) नियमों के लिए विशेष प्रति अर्थशास्त्र लागू करता है। प्रलेखन कहते हैं:

जब एक नियम एक EBNF अभिव्यक्ति की दाहिने हाथ की ओर में कहीं भी संदर्भित है, नियम संदर्भ द्वारा अभिव्यक्ति द्वारा आयोजित किया जाता है। यह ग्राहक की जिम्मेदारी सुनिश्चित करने के लिए है कि संदर्भित नियम दायरे में रहता है और संदर्भित होने पर को नष्ट नहीं किया जाता है।

असाइनमेंट ऑपरेटर अनिवार्य रूप से एक गहरी प्रतिलिपि के बिना rhs नियम का संदर्भ देता है। यह अनुमति देने के लिए किया गया था:

rule<> r1, r2; 
r1 = ...; 
r2 = r1; 

लेकिन इस रूप में यह रोका निपटने के रूप में 'सामान्य' वस्तुओं उसी तरह नियमों अत्यधिक भ्रम साबित हुआ।

इसी कारण से सदस्य rule::copy() कार्य करता था, जो नियम की स्पष्ट गहरी प्रतियां बनाने के लिए अनुमति देता था (उदाहरण के लिए उन्हें एक एसटीएल कंटेनर में स्टोर करने के लिए)।

एक ही समय इस पर:

r2 = r1.copy(); 

सादा गलत है। r2r1 फ़ंक्शन copy() से लौटाए गए (विनाशकारी) अस्थायी प्रति को संदर्भित करेगा।


Spirit.Qi में (अर्थात आत्मा v2.x) व्यवहार आंशिक रूप से बदला गया है।जब पार्सर्स के बाहर संभाला जाता है तो नियम अब अपेक्षा के अनुसार व्यवहार कर रहे हैं। आप उन्हें आम तौर पर कंटेनरों में स्टोर कर सकते हैं (असाइनमेंट ऑपरेटर अपेक्षित व्यवहार का खुलासा करता है)। लेकिन सावधान रहना, कि एक पार्सर अंदर अभिव्यक्ति नियम अब भी संदर्भ, जो अभी भी एक नियम को पहले की तरह ही रास्ता उल्लेख करने के लिए अनुमति देता है द्वारा आयोजित की जाती हैं:

rule<> r1, r2; 
r1 = ... >> r2 >> ...; 
r2 = ... >> r1 >> ...; 

कभी कभी यह एक नियम की गहरी प्रतिलिपि बनाने के लिए आवश्यक है, इसलिए वहाँ अभी भी सदस्य Functon copy है।

परिवर्तित प्रति semantics का एक और दुष्प्रभाव है। निर्माणों की तरह:

r1 = r2; 

अब, खासकर अगर r2r2 के एक (गहरी) प्रति है, जो नहीं हो सकता है कि आप क्या उम्मीद पैदा कर रहे अपने आरएचएस के बाद ही r1 लिए की जा रही 'सौंपा' सौंपा मिल जाएगा। यही वजह है कि वहाँ नए सदस्य समारोह इस कोने मामले के लिए alias सक्रिय करने के संदर्भ अर्थ विज्ञान है:

r1 = r2.alias(); 

किसी भी मामले में, आत्मा के दोनों संस्करणों में आप झूलने संदर्भ के साथ खत्म हो जाएगा अगर नियमों का हिस्सा एक पार्सर से संदर्भित अभिव्यक्ति गुंजाइश से बाहर हो जाती है।

बीटीडब्ल्यू, न तो आत्मा संस्करण rule::ref() फ़ंक्शन लागू करता है।

+0

इस उत्तर के लिए धन्यवाद। मेरे पास सिर्फ एक फॉलो अप प्रश्न है: क्या किसी भी प्रकार के पार्सर अभिव्यक्ति में पार्सर एक्सप्रेशन के रावलस (अस्थायी) का उपयोग करना संभव है जैसे कि 'r1 = r1 | एक फंक्शन में स्ट्रिंग ("एबीसी") 'या जनरेटिंग नियम? – jpalecek

+0

अभिव्यक्ति 'आर 1 = आर 1 | स्ट्रिंग ("एबीसी") सैद्धांतिक रूप से संभव है कि यह एक बाएं रिकर्सन है, जिसके परिणामस्वरूप आत्मा एक अनंत पुनरावृत्ति होगी क्योंकि आत्मा रिकर्सिव वंश पार्सर्स उत्पन्न करती है। लेकिन अभिव्यक्ति 'आर 1 = स्ट्रिंग ("एबीसी") | आर 1 'उम्मीद के रूप में काम करेगा। यदि आप सुनिश्चित करते हैं कि यह किसी अन्य नियम का संदर्भ नहीं देता है, जो किसी दायरे से बाहर निकलता है तो आप किसी फ़ंक्शन में नियम उत्पन्न कर सकते हैं। इसके अलावा, Spirit.Classic में आपको फ़ंक्शन से r.copy() वापस करने की आवश्यकता है। – hkaiser

+0

'आर 1 = स्ट्रिंग ("एबीसी") | आर 1 'बाएं-रिकर्सन भी है :) लेकिन मैं जो करना चाहता था, आर 1 मैच बना रहा है जो आर 1 पहले और "एबीसी" से मेल खाता था। बीटीडब्ल्यू मैं एक समारोह में एक नियम कैसे उत्पन्न कर सकता हूं? यह मेरे लिए काम नहीं करता है: http://pastebin.org/482764 – jpalecek

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