Antlr के लाभ (बनाम, लेक्स / याक / बाइसन) [बंद]


143

मैंने विभिन्न परियोजनाओं के लिए अतीत में आमतौर पर lex और yacc (आमतौर पर bison) का उपयोग किया है, आमतौर पर अनुवादक (जैसे कि EDIF का एक सबसेट EDA ऐप में स्ट्रीम किया जाता है)। इसके अतिरिक्त, मुझे lex / yacc व्याकरणों के आधार पर कोड का समर्थन करना पड़ा है जो दशकों से डेटिंग कर रहे हैं। इसलिए मैं उपकरणों के आसपास अपना रास्ता जानता हूं, हालांकि मैं कोई विशेषज्ञ नहीं हूं।

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

जवाबों:


145

अद्यतन / चेतावनी: यह उत्तर पुराना हो सकता है!


एक बड़ा अंतर यह है कि ANTLR एक LL (*) पार्सर उत्पन्न करता है, जबकि YACC और बाइसन दोनों ऐसे पार्सर उत्पन्न करते हैं जो LALR हैं। यह कई अनुप्रयोगों के लिए एक महत्वपूर्ण अंतर है, सबसे स्पष्ट ऑपरेटर हैं:

expr ::= expr '+' expr
       | expr '-' expr
       | '(' expr ')'
       | NUM ;

ANTLR इस व्याकरण को पूरी तरह से संभालने में असमर्थ है। ANTLR (या किसी अन्य एलएल पार्सर जनरेटर) का उपयोग करने के लिए, आपको इस व्याकरण को ऐसी चीज़ में परिवर्तित करना होगा जो वाम-पुनरावर्ती नहीं है। हालांकि, बाइसन को इस फॉर्म के व्याकरण से कोई समस्या नहीं है। आपको '+' और '-' को बाएं-सहयोगी ऑपरेटरों के रूप में घोषित करने की आवश्यकता होगी, लेकिन यह कि बाएं पुनरावृत्ति के लिए कड़ाई से आवश्यक नहीं है। एक बेहतर उदाहरण प्रेषण हो सकता है:

expr ::= expr '.' ID '(' actuals ')' ;

actuals ::= actuals ',' expr | expr ;

ध्यान दें कि नियम exprऔर actualsनियम दोनों पुनरावर्ती हैं। जब कोड पीढ़ी के लिए समय आता है तो यह बहुत अधिक कुशल एएसटी का उत्पादन करता है क्योंकि यह कई रजिस्टरों की आवश्यकता से बचता है और अनावश्यक स्पिलिंग (एक बाएं झुकाव वाला पेड़ ढह सकता है जबकि एक सही झुकाव वाला पेड़ नहीं हो सकता है)।

व्यक्तिगत स्वाद के संदर्भ में, मुझे लगता है कि LALR व्याकरण निर्माण और डिबग करने में बहुत आसान है। नकारात्मक पक्ष यह है कि आपको शिफ्ट-कम और (खूंखार) कम-कटौती जैसी कुछ गंभीर त्रुटियों से निपटना होगा। ये त्रुटियाँ हैं जो बाइसन पार्सर उत्पन्न करते समय पकड़ती हैं, इसलिए यह अंतिम-उपयोगकर्ता अनुभव को प्रभावित नहीं करता है, लेकिन यह विकास प्रक्रिया को थोड़ा अधिक रोचक बना सकता है। आमतौर पर ANTLR को इस कारण से YACC / Bison की तुलना में उपयोग करना आसान माना जाता है।


2
तो Antlr के बड़े, संभवतः एकल, आपकी धारणा में लाभ यह है कि यह निर्माण चरण के दौरान sr और rr जैसी कम त्रुटियाँ उत्पन्न करता है? मुझे उम्मीद है कि मैं इसे एक कोशिश करूँगा, लेकिन शायद मैं जो जानता हूं उसके साथ चिपके रहूंगा ...
डॉन वेकफील्ड

1
हाँ, यह बहुत ज्यादा है। :-) मैं वास्तव में लोकप्रिय राय से सहमत नहीं हूं कि ANTLR बाइसन की तुलना में आसान है, इसलिए मुझे लगता है कि मैं आपके निर्णय से सहमत हूं।
डैनियल स्पाइवाक

2
क्या 'वास्तविक' नियम को यह दर्शाने के लिए दूसरे नियम की आवश्यकता है कि एक सरल 'एक्सप' वास्तविक है? अन्यथा, अच्छी व्याख्या।
जोनाथन लेफ्लर 7

8
एक और टिप्पणी जो मुझे हाल ही में मिली, हालांकि एक दशक पुरानी है, जो आउटपुट का उचित अवलोकन करती है : compilers.iecc.com/comparch/article/98-11-040 : "ANTLR / PCCS LL हैं जो व्याकरण लेखन को और अधिक कठिन बनाता है, लेकिन उत्पन्न कोड पठनीय है। Yacc LALR जा रहा है (बेशक आप जानते हैं कि) व्याकरण लेखन को आसान बनाता है, लेकिन उत्पन्न कोड चित्रलिपि भी हो सकता है। "
डॉन वेकफील्ड

72
मैंने अभी ANTLR की अगली रिलीज v3.4 के लिए तत्काल लेफ्ट-रिकर्सन सपोर्ट पूरा किया है। एलआर एक्सप्रेशन रूल्स और सी डिक्लेयर रूल्स जैसे सामान को हैंडल करता है। :)
टेरेंस पर्र

117

YACC / बाइसन और ANTLR के बीच सबसे महत्वपूर्ण अंतर व्याकरण का प्रकार है जो ये उपकरण प्रक्रिया कर सकते हैं। YACC / बाइसन LALR व्याकरण संभालती है, ANTLR LL व्याकरण संभालती है।

अक्सर, जिन लोगों ने लंबे समय तक LALR व्याकरण के साथ काम किया है, वे एलएल व्याकरण के साथ काम करना अधिक कठिन और इसके विपरीत पाएंगे। इसका मतलब यह नहीं है कि व्याकरण या उपकरण स्वाभाविक रूप से अधिक कठिन काम करते हैं। आपको किस उपकरण का उपयोग करना आसान लगता है, ज्यादातर व्याकरण के प्रकार से परिचित हो जाएगा।

जहां तक ​​फायदे हैं, ऐसे पहलू हैं जहां एलएएलआर व्याकरण में एलएलआर व्याकरण से अधिक लाभ हैं और अन्य पहलू भी हैं जहां एलएल व्याकरण में एलएएलआर व्याकरण से अधिक लाभ हैं।

YACC / बाइसन तालिका संचालित पार्सर उत्पन्न करते हैं, जिसका अर्थ है कि "प्रसंस्करण तर्क" पार्सर प्रोग्राम के डेटा में निहित है, पार्सर कोड में इतना नहीं है। पे ऑफ यह है कि बहुत जटिल भाषा के लिए भी एक पार्सर के पास अपेक्षाकृत छोटे कोड पायदान होते हैं। यह 1960 और 1970 के दशक में अधिक महत्वपूर्ण था जब हार्डवेयर बहुत सीमित था। टेबल चालित पार्सर जनरेटर इस युग में वापस जाते हैं और छोटे कोड पदचिह्न तब एक मुख्य आवश्यकता थी।

ANTLR पुनरावर्ती वंश पार्सर उत्पन्न करता है, जिसका अर्थ है कि "प्रसंस्करण तर्क" पार्सर कोड में निहित है, क्योंकि व्याकरण के प्रत्येक उत्पादन नियम को पार्सर कोड में एक फ़ंक्शन द्वारा दर्शाया जाता है। पे ऑफ यह है कि यह समझना आसान है कि पार्सर इसके कोड को पढ़कर क्या कर रहा है। इसके अलावा, पुनरावर्ती वंश पार्सर आमतौर पर टेबल संचालित वाले की तुलना में तेजी से होते हैं। हालांकि, बहुत जटिल भाषाओं के लिए, कोड पदचिह्न बड़ा होगा। यह 1960 और 1970 के दशक में एक समस्या थी। इसके बाद, उदाहरण के लिए पास्कल जैसी अपेक्षाकृत छोटी भाषाओं को हार्डवेयर सीमाओं के कारण इस तरह लागू किया गया।

ANTLR उत्पन्न पार्सर आमतौर पर कोड के 10.000 लाइनों और अधिक के आसपास के क्षेत्र में होते हैं। हस्तलिखित पुनरावर्ती वंश पार्सर अक्सर एक ही बॉलपार्क में होते हैं। Wirth का ओबेरॉन कंपाइलर शायद सबसे अधिक कॉम्पैक्ट है जिसमें कोड जनरेशन सहित 4000 लाइनों के बारे में है, लेकिन ओबेरॉन एक बहुत ही कॉम्पैक्ट भाषा है जिसमें केवल 40 उत्पादन नियम हैं।

जैसा कि किसी ने पहले ही बताया है, ANTLR के लिए एक बड़ा प्लस ग्राफिकल आईडीई टूल है, जिसे ANTLRworks कहा जाता है। यह एक पूर्ण व्याकरण और भाषा डिजाइन प्रयोगशाला है। यह आपके व्याकरण नियमों की कल्पना करता है क्योंकि आप उन्हें टाइप करते हैं और यदि यह किसी भी टकराव का पता लगाता है तो यह आपको ग्राफिक रूप से दिखाएगा कि संघर्ष क्या है और इसके कारण क्या हैं। यह स्वचालित रूप से भी रिफ्लेक्टर कर सकता है और वाम-पुनरावृत्ति जैसे संघर्षों को हल कर सकता है। एक बार जब आपके पास एक संघर्ष मुक्त व्याकरण होता है, तो आप ANTLRworks को आपकी भाषा की इनपुट फ़ाइल पार्स करने और आपके लिए एक पार्स ट्री और एएसटी का निर्माण करने और आईडीई में पेड़ को रेखांकन दिखाने के लिए दे सकते हैं। यह एक बहुत बड़ा लाभ है क्योंकि यह आपको कई घंटों के काम को बचा सकता है: कोडिंग शुरू करने से पहले आपको अपनी भाषा डिजाइन में वैचारिक त्रुटियां मिलेंगी! मुझे LALR व्याकरण के लिए ऐसा कोई उपकरण नहीं मिला है, ऐसा लगता है कि ऐसा कोई उपकरण नहीं है।

यहां तक ​​कि जो लोग अपने पार्सर उत्पन्न करना नहीं चाहते हैं, लेकिन उन्हें कोड करते हैं, ANTLRworks भाषा डिजाइन / प्रोटोटाइप के लिए एक महान उपकरण है। संभवतः इस तरह का सबसे अच्छा उपकरण उपलब्ध है। यदि आप LALR पार्सर का निर्माण करना चाहते हैं तो दुर्भाग्य से, यह आपकी मदद नहीं करता है। केवल ANTLRworks का लाभ लेने के लिए LALR से LL में स्विच करना अच्छी तरह से सार्थक हो सकता है, लेकिन कुछ लोगों के लिए, व्याकरण के प्रकारों को बदलना एक बहुत ही दर्दनाक अनुभव हो सकता है। दूसरे शब्दों में: YMMV।


4
यह पसंद है क्योंकि यह विभिन्न तंत्रों के पीछे के इतिहास की व्याख्या करता है जो लोगों को
imediately समझती है

35

ANTLR के लिए कुछ फायदे:

  • विभिन्न भाषाओं में पार्सर का उत्पादन कर सकते हैं - जावा उत्पन्न पार्सर को चलाने के लिए आवश्यक नहीं है।
  • बहुत बढ़िया जीयूआई व्याकरण डिबगिंग को आसान बनाता है (जैसे आप जीयूआई में उत्पन्न एएसटी के अधिकार को देख सकते हैं, कोई अतिरिक्त उपकरण की आवश्यकता नहीं है)
  • उत्पन्न कोड वास्तव में मानव-पठनीय है (यह ANTLR के लक्ष्यों में से एक है) और यह तथ्य कि यह एलएल पार्सर्स उत्पन्न करता है निश्चित रूप से इस संबंध में मदद करता है।
  • टर्मिनलों की परिभाषा संदर्भ-मुक्त होने के साथ-साथ (f) lex में regex के विपरीत है - इस प्रकार अनुमति, उदाहरण के लिए, ठीक से बंद कोष्ठक वाले टर्मिनलों की परिभाषा।

मेरा .02 $


9

ANTRL का एक और लाभ यह है कि आप उपयोग कर सकते हैं ANTLRWORKS , हालांकि मैं यह नहीं कह सकते कि यह एक सख्त लाभ यह है कि, के रूप में वहाँ अन्य जनरेटर के लिए इसी तरह के उपकरण के रूप में अच्छी तरह से हो सकता है।


9
  • बाइसन और फ्लेक्स का परिणाम एक छोटी मेमोरी फुटप्रिंट है, लेकिन आपके पास कोई चित्रमय आईडीई नहीं है।
  • antlr अधिक मेमोरी का उपयोग करता है, लेकिन आपके पास antlrworks, एक चित्रमय IDE है।

बाइसन / फ्लेक्स मेमोरी का उपयोग आमतौर पर एक मैबेट या तो होता है। विरोधाभास है कि antlr के साथ - यह मानकर कि आप जिस फ़ाइल को पार्स करना चाहते हैं उसमें प्रत्येक टोकन के लिए 512 बाइट्स मेमोरी का उपयोग करता है। 4 मिलियन टोकन और आप 32-बिट सिस्टम पर वर्चुअल मेमोरी से बाहर हैं।

यदि आप जिस फ़ाइल को पार्स करना चाहते हैं, वह बड़ी है, तो एंटीएलआर मेमोरी से बाहर हो सकती है, इसलिए यदि आप किसी कॉन्फ़िगरेशन फ़ाइल को पार्स करना चाहते हैं, तो यह एक व्यवहार्य समाधान होगा। अन्यथा, यदि आप बहुत सारे डेटा के साथ फ़ाइल पार्स करना चाहते हैं, तो बाइसन का प्रयास करें।


7
मैं उत्सुक हूँ। क्या आप प्रति टोकन 512 बाइट्स मेमोरी की खपत का वर्णन करने वाले दस्तावेज़ को इंगित कर सकते हैं? मुझे वह चर्चा देखकर याद नहीं है। Google कीवर्ड की मेरी पसंद मुझे संतुष्टि भी नहीं दे रही है ...
डॉन वेकफील्ड

2
क्या आप पार्सर उत्पन्न करते समय पार्सर जनरेटर की मेमोरी फुटप्रिंट के बारे में बात कर रहे हैं, या आप स्रोत भाषा के लिए इनपुट पार्स करते समय उत्पन्न पार्सर की मेमोरी फुटप्रिंट के बारे में बात कर रहे हैं? एक व्याकरण में लाखों टोकन बिल्कुल पागल होंगे। यदि आप गंभीरता से इस तरह के विचार को बेचने की कोशिश करते हैं तो आपको एक मानसिक संस्थान में बंद कर दिया जाना चाहिए। जैसे ही पार्सर के लिए इनपुट फ़ाइलों के लिए, ऐसे मामले हो सकते हैं जहां इनमें बहुत बड़ी संख्या में टोकन हो सकते हैं, लेकिन अधिकांश भाषाएं मॉड्यूलर हैं, आप एक ही फाइल में पूरे इनपुट को पार्स नहीं करते हैं, व्यक्तिगत मॉड्यूल छोटे होते हैं।
trijezdci
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.