2011-01-06 13 views
6

जैसे, इनमें से कई अन्य प्रश्न, मैं Boost.Spirit.Qi का उपयोग करके structs के पेड़ में एक साधारण व्याकरण को पार्स करने की कोशिश कर रहा हूं।Boost.Spirit.Qi: नियम की विशेषता लें और इसे एक संलग्न नियम की संरचना विशेषता के क्षेत्र के रूप में सेट करें?

मैं सबसे आसान संभव मामले में जो करने की कोशिश कर रहा हूं उसे दूर करने की कोशिश करूंगा। मेरे पास है:

struct Integer { 
    int value; 
}; 
BOOST_FUSION_ADAPT_STRUCT(Integer, (int, value)) 

बाद में, के अंदर एक व्याकरण struct की, मैं निम्नलिखित सदस्य चर है:

qi::rule<Iterator, Integer> integer; 

जो मैं

integer = qi::int_; 

साथ परिभाषित करने कर रहा हूँ मैं वास्तव में पार्स करने के लिए प्रयास करते हैं एक पूर्णांक, हालांकि,

qi::phrase_parse(iter, end, g, space, myInteger); 
का उपयोग कर एक सफल पार्स के बाद

myInteger.value हमेशा अनियमित किया जाता है।

integer = qi::int_[qi::_val = qi::_1]; //compiles, uninitialized value 
integer = qi::int_[qi::_r1 = qi::_1]; //doesn't compile 
integer = qi::int_[phoenix::bind(&Integer::value, qi::_val) = qi::_1]; //doesn't 
integer = qi::int_[phoenix::at_c<0>(qi::_val) = qi::_1]; //doesn't 

जाहिर है मैं आत्मा, फीनिक्स, या कुछ और के बारे में कुछ गलतफहमी हूँ: इसी तरह, मैं निम्नलिखित परिभाषा (जाहिर है जो कि संकलन नहीं है गलत कर रहे हैं) की कोशिश की है। मेरी समझ यह है कि qi::_1qi::int_ की पहली विशेषता है, यहां, और पार्स किए गए पूर्णांक का प्रतिनिधित्व करना चाहिए, जब स्क्वायर ब्रैकेट में भाग फ़ंक्शन ऑब्जेक्ट के रूप में निष्पादित हो जाता है। मैं तब मान रहा हूं कि फ़ंक्शन ऑब्जेक्ट integer विशेषता qi::_val विशेषता लेगा और इसे पार्स किए गए पूर्णांक को आज़माएं और असाइन करें। मेरा अनुमान था कि मेरे BOOST_FUSION_ADAPT_STRUCT कॉल के कारण, दोनों संगत होंगे, और यह निश्चित रूप से एक स्थिर विश्लेषण परिप्रेक्ष्य का मामला प्रतीत होता है, लेकिन डेटा संरक्षित नहीं किया जा रहा है।

क्या कोई संदर्भ है() पदनाम मुझे कहीं या कुछ याद आ रहा है?

qi::rule<Iterator, Integer()> integer; 

(कोष्ठक ध्यान दें):

+0

मैं सिर्फ एक और संयोजन है कि संकलित है, हालांकि यह initialized डेटा प्राप्त नहीं पाया , फिर मेरे 'पूर्णांक' पार्सर को' पूर्णांक = qi :: long_long [qi :: _ val = phx :: निर्माण (qi :: _ 1)]; ' – jtolds

+0

ओप्स के रूप में परिभाषित किया गया, मेरा मतलब है 'qi :: int_' – jtolds

+0

अधिक डिबगिंग टिप्पणियाँ। मेरे पूर्ण कोड में, मेरे पास वास्तव में 'qi :: rule integer; 'है, जो ऐसा लगता है कि अगर मैं' इंटीजर 'को' इंटीजर() 'से बदलता हूं, और सभी उदाहरणों में यह टूट जाता है पीछे की ओर '() ', जिसे मैंने उपेक्षित किया था। तो शायद 'नियम' के लिए टेम्पलेट तर्क खराब हो रहे थे। खुदाई। – jtolds

उत्तर

13

पूर्णांक विशेषता शासन द्वारा उजागर माना जाता है, तो आप के रूप में यह घोषणा करने के लिए की जरूरत है। आत्मा के 'इंटरफ़ेस' का वर्णन करने के लिए आत्मा को फ़ंक्शन घोषणा वाक्यविन्यास का उपयोग करने की आवश्यकता होती है। यह न केवल आत्मा में बल्कि कई अन्य पुस्तकालयों द्वारा भी प्रयोग किया जाता है (उदाहरण के लिए बूस्ट :: फ़ंक्शन देखें)।

इसका मुख्य कारण यह है कि यह फ़ंक्शन इंटरफ़ेस निर्दिष्ट करने का एक अच्छा संक्षिप्त तरीका है। यदि आप एक नियम के बारे में सोचते हैं, तो आप जल्दी से महसूस करते हैं कि यह एक फ़ंक्शन की तरह है: यह एक मान (पार्स किए गए परिणाम, यानी संश्लेषित विशेषता) वापस कर सकता है। इसके अतिरिक्त इसमें एक या अधिक तर्क (विरासत विशेषताएँ) लग सकती हैं।

एक दूसरा, लेकिन मामूली कारण यह है कि आत्मा को नियम के विभिन्न टेम्पलेट पैरामीटर को अलग करने में सक्षम होना चाहिए। टेम्पलेट पैरामीटर को किसी भी क्रम में निर्दिष्ट किया जा सकता है (इटरेटर को छोड़कर), इसलिए इसे समझने के कुछ तरीकों की आवश्यकता है कि क्या है। फ़ंक्शन घोषणा वाक्यविन्यास कप्तान या एन्कोडिंग (अन्य दो संभावित टेम्पलेट पैरामीटर) से पर्याप्त रूप से अलग है ताकि इसे संकलित समय पर पहचाना जा सके। यदि आप नियम परिभाषा जैसा कि ऊपर उल्लिखित बदल

यह किया जा सकता है काम करने के लिए:

के अपने अलग अलग प्रयास पर एक नजर है।

integer = qi::int_[qi::_val = qi::_1]; 

_val, अपने Integer को संदर्भित करता है, जबकि _1 एक int को दर्शाता है। इसलिए, आप इस काम करने के लिए int से एक असाइनमेंट ऑपरेटर निर्धारित करने होंगे:

struct Integer { 
    int value; 
    Integer& operator=(int) {...} 
};      

आप इस मामले में एक फ्यूजन अनुक्रम के रूप में अपने प्रकार अनुकूलित करने की आवश्यकता नहीं है।

लेकिन आप इसे लिख सकते हैं और भी आसान:

integer = qi::int_ >> qi::eps; 

जो 100% के बराबर (ईपीएस है एक पार्सर दृश्य है, जो उपयोग करने के लिए अनुमति देता है में दाहिने हाथ की ओर परिवर्तित करने के लिए प्रयोग किया जाता है एक चाल है निर्मित अनुक्रम के तत्वों के गुणों के लिए आपके अनुकूलित फ़्यूज़न अनुक्रम के तत्वों को मैपिंग विशेषता प्रक्षेपण)।

यह:

integer = qi::int_[qi::_r1 = qi::_1]; 

_r1 के रूप में काम नहीं करेगा एक नियम के पहले विरासत में मिला विशेषता को दर्शाता है। हालांकि, आपके नियम में कोई विरासत विशेषता नहीं है।

यह काम करेगा:

integer = qi::int_[phoenix::bind(&Integer::value, qi::_val) = qi::_1]; 

लेकिन एक फ्यूजन अनुक्रम के रूप में अपने प्रकार अनुकूल करने के लिए आवश्यकता नहीं है।

और इसलिए होगा इस: मुझे लगता है कि एक `मान` के लिए एक मूल्य लेता है` Integer` को एक निर्माता कहा:

integer = qi::int_[phoenix::at_c<0>(qi::_val) = qi::_1]; 
+0

ओह सुंदर, धन्यवाद। तो ऐसा लगता है कि मेरे पास सिर्फ एक टेम्पलेट टाइपो था। – jtolds

+2

'गिट प्रतिबद्ध-ए-एम' हार्टमूट कैसर आदमी है! ' – jtolds

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