2010-02-26 14 views
8

मैं मजेदार और अभ्यास के लिए लैम्ब्डा कैलकुस दुभाषिया लिख ​​रहा हूं। मैं एक ctype पहलू जो खाली स्थान के रूप में परिभाषित करता है विराम चिह्न जोड़कर ठीक से tokenize पहचानकर्ता को iostreams मिला: (! classic_table() शायद क्लीनर होगा, लेकिन है कि ओएस एक्स पर काम नहीं करता है)ओवरराइडिंग सीटीपी <wchar_t>

struct token_ctype : ctype<char> { 
mask t[ table_size ]; 
token_ctype() 
: ctype<char>(t) { 
    for (size_t tx = 0; tx < table_size; ++ tx) { 
    t[tx] = isalnum(tx)? alnum : space; 
    } 
} 
}; 

और फिर स्वैप जब मैं एक पहचानकर्ता हिट में पहलू:

locale token_loc(in.getloc(), new token_ctype); 
… 
locale const &oldloc = in.imbue(token_loc); 
in.unget() >> token; 
in.imbue(oldloc); 

वेब पर आश्चर्यजनक रूप से कम लैम्ब्डा पथरी कोड हो रहा है। जो कुछ मैंने अभी तक पाया है, वह यूनिकोड λ वर्णों से भरा है। तो मैंने यूनिकोड समर्थन जोड़ने का प्रयास करने के लिए सोचा।

लेकिन ctype<wchar_t>ctype<char> से पूरी तरह से अलग तरीके से काम करता है। कोई मास्टर टेबल नहीं है; चार विधियां do_is x2, do_scan_is, और do_scan_not हैं। तो मैं इस किया था:

struct token_ctype : ctype<wchar_t> { 
typedef ctype<wchar_t> base; 

bool do_is(mask m, char_type c) const { 
    return base::do_is(m,c) 
    || (m&space) && (base::do_is(punct,c) || c == L'λ'); 
} 

const char_type* do_is 
    (const char_type* lo, const char_type* hi, mask* vec) const { 
    base::do_is(lo,hi,vec); 
    for (mask *vp = vec; lo != hi; ++ vp, ++ lo) { 
    if (*vp & punct || *lo == L'λ') *vp |= space; 
    } 
    return hi; 
} 

const char_type *do_scan_is 
    (mask m, const char_type* lo, const char_type* hi) const { 
    if (m & space) m |= punct; 
    hi = do_scan_is(m,lo,hi); 
    if (m & space) hi = find(lo, hi, L'λ'); 
    return hi; 
} 

const char_type *do_scan_not 
    (mask m, const char_type* lo, const char_type* hi) const { 
    if (m & space) { 
    m |= punct; 
    while (* (lo = base::do_scan_not(m,lo,hi)) == L'λ' && lo != hi) 
    ++ lo; 
    return lo; 
    } 
    return base::do_scan_not(m,lo,hi); 
} 
}; 

(फ्लैट प्रारूपण के लिए क्षमा याचना, पूर्वावलोकन टैब को अलग ढंग से बदल दिया।)

कोड रास्ता कम सुरुचिपूर्ण है। मैं बेहतर धारणा व्यक्त करता हूं कि केवल विराम चिह्न अतिरिक्त सफेद जगह है, लेकिन मूल में यह ठीक होगा कि मेरे पास classic_table था।

क्या ऐसा करने का कोई आसान तरीका है? क्या मुझे वास्तव में उन सभी अधिभारों की आवश्यकता है? (परीक्षण दिखाया गया है do_scan_not यहां अपरिहार्य है, लेकिन मैं अधिक व्यापक रूप से सोच रहा हूं।) क्या मैं पहले स्थान पर पहलुओं का दुरुपयोग कर रहा हूं? क्या ऊपर भी सही है? कम तर्क लागू करने के लिए बेहतर शैली होगी?

+1

उदाहरण कोड के मामले में, आप योजना या LISP को देखना चाहेंगे, क्योंकि ये दोनों भाषाएं लैम्ब्डा कैलकुस में आधारित हैं। कुछ एलआईएसपी या स्कीम कोड होना चाहिए जिनके साथ आप खेल सकते हैं। –

+0

सभी मानक कार्यात्मक भाषाएं अच्छी हैं, लेकिन मैं फॉर्म के कुछ कट-एंड-सूखे स्रोतों को ढूंढने की उम्मीद कर रहा था '(\ foo bar। Foo foo \ baz। ...' विज्ञापन मतली। मैं बाइनरी लैम्ब्डा के साथ खेलना चाहता हूं कैलकुस (http://en.wikipedia.org/wiki/Binary_lambda_calculus, http://homepages.cwi.nl/~tromp/cl/cl.html) गूढ़ कोड लिखने में समय बिताने के बजाय। लेकिन यह सवाल iostreams के बारे में है और व्यापक और संकीर्ण पात्रों के बीच लालित्य की असमानता। – Potatoswatter

+0

आप क्या हैं? आप टोकनिंग पार्सर बनाने के लिए पहलुओं का दुरुपयोग कर रहे हैं। मुझे उम्मीद है कि यह भी भंगुर और धीमी दोनों हो। फिर फिर, यह संभवतः _the_ सीखने का सबसे सीधा तरीका है Iostreams के इन्स और आउट। हमें दिखाने के लिए धन्यवाद! – sehe

उत्तर

3

(यह कोई ठोस जवाब के साथ एक साल हो गया है, और मैं इस बीच में iostreams बारे में बहुत कुछ सीखा है ...)

कस्टम पहलू विशेष रूप से स्ट्रिंग निष्कर्षण ऑपरेटर in >> token सेवा करने के लिए मौजूद है। अगले ऑपरेटर सी के लिए उस ऑपरेटर को use_facet< ctype<wchar_t> >(in.getloc()).is(ios::space, c) "के संदर्भ में परिभाषित किया गया है।" (§21.3.7.9) ctype::is बस ctype::do_is के लिए एक स्टब है, इसलिए ऐसा लगता है कि do_is पर्याप्त है।

फिर भी, जीसीसी मानक पुस्तकालय के हाल के संस्करण operator>>scan_is के संदर्भ में लागू करते हैं। पकड़ यह है कि do_scan_is को do_is, वर्चुअल प्रेषण और सभी को कॉल की श्रृंखला के रूप में कार्यान्वित किया जाता है। हेडर फ़ाइल उपयोगकर्ता अनुकूलन के लिए एक हुक के रूप में do_scan_is का वर्णन करती है।

तो, ऐसा लगता है कि जैसे-जैसे नियम एक कार्यान्वयन को आश्रय देता है जो केवल पहले ओवरराइड प्रदान करता है।

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


वैसे भी, यह सब अच्छी तरह से और अच्छा है, लेकिन बस एक tokenizer streambuf_iterator<wchar_t> का उपयोग कर लिख आसान, कहीं अधिक विस्तृत है, और अपवाद हैंडलिंग सरल करता है।

+0

हां। आपने अपने खुद के प्रश्न का उत्तर दिया। यह नहीं देखा कि यह एक पुराना था। अत्यधिक जानकारीपूर्ण सामान यह है। – sehe

2

आईएमएचओ आपके द्वारा पोस्ट किया गया कोड ठीक है। यदि आप सरल कोड चाहते थे (शायद दक्षता की कीमत पर), तो आप दूसरों का उपयोग करके कुछ विधियों को लागू कर सकते हैं, लेकिन जिस तरह से आपने इसे किया है ठीक है।

असमानता इस तथ्य पर आधारित है कि लोग अपने यूनिकोड कार्यक्रमों में कई मेगाबाइट टेबल नहीं चाहते हैं।