मुश्किल रास्ता
आप एक पुनरावर्ती वंश पार्सर चाहते हैं ।
पूर्वता प्राप्त करने के लिए आपको पुनरावर्ती सोचने की जरूरत है, उदाहरण के लिए, अपने नमूना स्ट्रिंग का उपयोग करते हुए,
1+11*5
इसे मैन्युअल रूप से करने के लिए, आपको पढ़ना होगा 1
, फिर प्लस को देखना होगा और एक नया पुनरावर्ती पार्स "सत्र" शुरू करना होगा11
... और 11 * 5
अपने स्वयं के कारक को पार्स ट्री के साथ पैरेडिंग करना सुनिश्चित करें 1 + (11 * 5)
।
यह सब समझाने की कोशिश करने पर भी इतना दर्दनाक लगता है, विशेष रूप से सी। की शक्तिहीनता के साथ, देखें। 11 को पार्स करने के बाद, यदि * वास्तव में + इसके बजाय, आपको एक शब्द बनाने के प्रयास को छोड़ना होगा और इसके बजाय पार्स करें 11
खुद एक कारक के रूप में। मेरा सिर पहले से ही फट रहा है। यह पुनरावर्ती सभ्य रणनीति के साथ संभव है, लेकिन एक बेहतर तरीका है ...
आसान (दाएं) तरीका
यदि आप Bison जैसे GPL टूल का उपयोग करते हैं, तो आपको लाइसेंसिंग के मुद्दों के बारे में चिंता करने की आवश्यकता नहीं है क्योंकि bison द्वारा उत्पन्न C कोड GPL (IANAL) द्वारा कवर नहीं किया गया है, लेकिन मुझे पूरा यकीन है कि GPL उपकरण GPL को बाध्य नहीं करते हैं उत्पन्न कोड / बायनेरिज़, उदाहरण के लिए ऐप्पल कोड कहते हैं, जीसीसी के साथ एपर्चर और वे इसे जीपीएल कोड के बिना बेचते हैं)।
बाइसन डाउनलोड करें (या कुछ समकक्ष, ANTLR, आदि)।
आमतौर पर कुछ सैंपल कोड होते हैं, जिन पर आप केवल बायसन चला सकते हैं और अपना वांछित C कोड प्राप्त कर सकते हैं जो इस चार फ़ंक्शन कैलकुलेटर को प्रदर्शित करता है:
http://www.gnu.org/software/bison/manual/html_node/Infix-Calc.html
उत्पन्न कोड को देखें, और देखें कि यह जितना आसान लगता है उतना आसान नहीं है। इसके अलावा, बाइसन जैसे उपकरण का उपयोग करने के फायदे 1 हैं) आप कुछ सीखते हैं (खासकर यदि आप ड्रैगन पुस्तक पढ़ते हैं और व्याकरण के बारे में सीखते हैं), 2) आप पहिया को सुदृढ़ करने की कोशिश कर रहे एनआईएच से बचते हैं । असली पार्सर-जनरेटर उपकरण के साथ, आपको वास्तव में बाद में स्केलिंग करने की उम्मीद है, अन्य लोगों को दिखाते हुए कि आप जानते हैं कि पार्सर्स पार्सिंग टूल का डोमेन है।
अपडेट करें:
यहां के लोगों ने बहुत अच्छी सलाह दी है। पार्सिंग टूल्स को छोड़ देने या केवल शंटिंग यार्ड एल्गोरिथ्म का उपयोग करने या एक हाथ से पुनरावर्ती सभ्य पार्सर का उपयोग करने के खिलाफ मेरी चेतावनी है कि छोटी खिलौना भाषाएँ 1 किसी दिन बड़े वास्तविक भाषाओं में फ़ंक्शन (पाप, कॉस, लॉग) और चर, शर्तों और साथ के लिए बदल सकती हैं छोरों।
फ्लेक्स / बाइसन एक छोटे, सरल दुभाषिया के लिए बहुत अच्छी तरह से ओवरकिल हो सकता है, लेकिन एक बंद पार्सर + मूल्यांकनकर्ता को नीचे की ओर परेशानी पैदा हो सकती है जब परिवर्तन करने की आवश्यकता होती है या सुविधाओं को जोड़ने की आवश्यकता होती है। आपकी स्थिति अलग-अलग होगी और आपको अपने निर्णय का उपयोग करने की आवश्यकता होगी; बस अपने पापों के लिए अन्य लोगों को दंडित न करें [2] और पर्याप्त उपकरण से कम का निर्माण करें।
पार्सिंग के लिए मेरा पसंदीदा उपकरण
नौकरी के लिए दुनिया में सबसे अच्छा उपकरण पारसेक पुस्तकालय (पुनरावर्ती सभ्य पार्सर के लिए) है जो प्रोग्रामिंग भाषा हास्केल के साथ आता है। यह बीएनएफ की तरह बहुत कुछ दिखता है , या पार्सिंग (नमूना कोड [3]) के लिए कुछ विशेष उपकरण या डोमेन विशिष्ट भाषा की तरह है, लेकिन यह वास्तव में हास्केल में सिर्फ एक नियमित पुस्तकालय है, जिसका अर्थ है कि यह बिलकुल बाकी के समान निर्माण चरण में संकलित करता है। अपने हास्केल कोड, और आप मनमाने ढंग से हास्केल कोड लिख सकते हैं और अपने पार्सर के भीतर कॉल कर सकते हैं, और आप सभी पुस्तकालयों को एक ही कोड में मिला सकते हैं और मेल कर सकते हैं । (हास्केल के अलावा अन्य भाषा में पार्सिंग भाषा को एंबेड करना से सिंटैक्टिक क्रॉफ्ट के भार के परिणामस्वरूप होता है। मैंने सी # में ऐसा किया है और यह काफी अच्छी तरह से काम करता है लेकिन यह इतना सुंदर और संक्षिप्त नहीं है।)
टिप्पणियाँ:
1 रिचर्ड स्टेलमैन कहते हैं, में आपको Tcl का उपयोग क्यों नहीं करना चाहिए
Emacs का मुख्य सबक यह है कि एक्सटेंशन के लिए एक भाषा केवल "एक्सटेंशन भाषा" नहीं होनी चाहिए। यह एक वास्तविक प्रोग्रामिंग भाषा होनी चाहिए, जो पर्याप्त कार्यक्रमों को लिखने और बनाए रखने के लिए डिज़ाइन की गई हो। क्योंकि लोग ऐसा ही करना चाहेंगे!
[२] हां, मैं उस "भाषा" के उपयोग से हमेशा के लिए डर गया।
यह भी ध्यान दें कि जब मैंने इस प्रविष्टि को प्रस्तुत किया था, तो पूर्वावलोकन सही था, लेकिन SO के पर्याप्त पार्सर से कम ने पहले पैराग्राफ पर मेरे करीबी एंकर टैग को खा लिया , यह साबित करते हुए कि पार्सर कुछ के साथ trifled होने के लिए नहीं हैं क्योंकि यदि आप regexes का उपयोग करते हैं और एक आपको हैक करता है शायद कुछ सूक्ष्म और छोटा गलत मिलेगा ।
[३] पार्सेक का उपयोग कर एक हास्केल पार्सर का स्निपेट: एक चार फंक्शन कैलकुलेटर एक्सपेक्टर्स, कोष्ठक, गुणन के लिए व्हाट्सएप, और स्थिरांक (जैसे पी और ई) के साथ विस्तारित।
aexpr = expr `chainl1` toOp
expr = optChainl1 term addop (toScalar 0)
term = factor `chainl1` mulop
factor = sexpr `chainr1` powop
sexpr = parens aexpr
<|> scalar
<|> ident
powop = sym "^" >>= return . (B Pow)
<|> sym "^-" >>= return . (\x y -> B Pow x (B Sub (toScalar 0) y))
toOp = sym "->" >>= return . (B To)
mulop = sym "*" >>= return . (B Mul)
<|> sym "/" >>= return . (B Div)
<|> sym "%" >>= return . (B Mod)
<|> return . (B Mul)
addop = sym "+" >>= return . (B Add)
<|> sym "-" >>= return . (B Sub)
scalar = number >>= return . toScalar
ident = literal >>= return . Lit
parens p = do
lparen
result <- p
rparen
return result