क्या जावा सी की तुलना में पार्स करना आसान बनाता है?


90

मैं इस तथ्य से परिचित हूं कि C और C ++ के व्याकरण संदर्भ के प्रति संवेदनशील हैं , और विशेष रूप से आपको C. में "lexer hack" की आवश्यकता है। दूसरी ओर, मैं इस धारणा के तहत हूं कि आप केवल जावा को पार्स कर सकते हैं दो भाषाओं के बीच काफी समानता के बावजूद, 2-लुक-फ़ोकस।

पार्स करने के लिए इसे और अधिक सुव्यवस्थित बनाने के लिए आपको C के बारे में क्या बदलना होगा?

मैं पूछता हूं क्योंकि मैंने C के संदर्भ-संवेदनशीलता के जो उदाहरण देखे हैं, वे सभी तकनीकी रूप से स्वीकार्य हैं लेकिन अजीब तरह से अजीब हैं। उदाहरण के लिए,

foo (a);

fooतर्क के साथ शून्य फ़ंक्शन को कॉल किया जा सकता है a। या, इसे aएक प्रकार की वस्तु घोषित किया जा सकता है foo, लेकिन आप आसानी से परांठे से छुटकारा पा सकते हैं। भाग में, यह अजीबता इसलिए होती है क्योंकि सी व्याकरण के लिए "प्रत्यक्ष घोषणाकर्ता" उत्पादन नियम दोनों कार्यों और चर को घोषित करने के दोहरे उद्देश्य को पूरा करता है।

दूसरी ओर, जावा व्याकरण में चर घोषणा और फ़ंक्शन घोषणा के लिए अलग-अलग उत्पादन नियम हैं। अगर आप लिखेंगे

foo a;

तब आप जानते हैं कि यह एक चर घोषणा है और fooस्पष्ट रूप से टाइपनाम के रूप में पार्स किया जा सकता है। यह मान्य कोड नहीं हो सकता है यदि वर्ग fooको वर्तमान दायरे में कहीं परिभाषित नहीं किया गया है, लेकिन यह शब्दार्थ विश्लेषण के लिए एक नौकरी है जिसे बाद के संकलक पास में किया जा सकता है।

मैंने देखा है कि C टाइप करने की वजह से पार्स करना मुश्किल है, लेकिन आप अपने खुद के प्रकार भी जावा में घोषित कर सकते हैं। कौन से C व्याकरण के नियम, इसके अलावा direct_declarator, गलती पर हैं?


7
अच्छा सवाल है। शायद रास्ता बहुत व्यापक या मुख्य रूप से माना जाता है।
आकाशी

37
यह पार्सर्स के बारे में एक वैध सवाल है और इसके बारे में केवल एक चीज व्यापक या राय है, यह अंतिम युगल वाक्य है (जिसे संभवतः गिरा दिया जाना चाहिए या बदल जाना चाहिए)। करीबी वोटों से बाहर निकलें।
आर .. गिटहब स्टॉप हेल्पिंग ICE

1
मैंने तदनुसार प्रश्न संपादित किया, प्रतिक्रिया के लिए @R .. के लिए धन्यवाद।
कोरोक

3
वस्तुतः हर (मानक) कंप्यूटर भाषा संदर्भ संवेदनशील है ; आप एक प्रकार का एक चर की घोषणा नहीं कर सकते हैं और यह सबसे अधिक दुरुपयोग भाषाओं । यह " भाषा के लिए सभी व्याकरणों " से अलग है , संदर्भ संवेदनशील हैं; पार्सर्स बनाने वाले अधिकांश लोग एक संदर्भ-मुक्त (या इससे भी अधिक प्रतिबंधक) पार्सर का निर्माण करते हैं, और फिर संदर्भ-मुक्त गुणों की जांच करने के लिए पार्सर के बाहर हैक्स का उपयोग करते हैं।
इरा बैक्सटर

1
@IraBaxter मैं उस "हैक्स" को कॉल नहीं करूंगा। समस्या को दो में विभाजित करना एक उचित बात लगती है, क्योंकि संदर्भ-संवेदनशील भाषाओं को पार्स करने का काम कुशलता से नहीं किया जा सकता है (और वास्तव में संदर्भ-मुक्त भाषाओं को पार्स करना भी कुशल नहीं है, और इसीलिए हम आम तौर पर संदर्भ-मुक्त के सबसेट तक सीमित रहते हैं) । एएसटी पर केवल संदर्भ-संवेदनशील गुणों की जांच करने के लिए एक संदर्भ-मुक्त पार्स + स्थैतिक विश्लेषण यह एक उचित बात है।
बकुरीउ

जवाबों:


76

पार्सिंग C ++ कठिन हो रही है। Parsing जावा बस के रूप में मुश्किल हो रहा है।

इस SO उत्तर पर चर्चा करें कि पार्स करने के लिए C (और C ++) "कठिन" क्यों है । संक्षिप्त सारांश यह है कि C और C ++ व्याकरण स्वाभाविक रूप से अस्पष्ट हैं; वे आपको कई पर्स देंगे और अस्पष्टता को हल करने के लिए आपको संदर्भ का उपयोग करना चाहिए । लोग तब आपको यह मानने की गलती करते हैं कि आपको अस्पष्टता को हल करना है जैसे कि आप पार्स करते हैं; ऐसा नहीं, नीचे देखें। यदि आप पार्स के रूप में अस्पष्टताओं को हल करने पर जोर देते हैं, तो आपका पार्सर अधिक जटिल हो जाता है और निर्माण के लिए बहुत कठिन होता है; लेकिन यह जटिलता एक स्व-सूजन वाला घाव है।

IIRC, जावा 1.4 का "स्पष्ट" LALR (1) व्याकरण अस्पष्ट नहीं था, इसलिए इसे पार्स करना "आसान" था। मुझे यकीन नहीं है कि आधुनिक जावा को कम से कम लंबी दूरी की स्थानीय अस्पष्टताएं नहीं मिली हैं; हमेशा यह तय करने की समस्या है कि क्या "... >>" दो टेम्पलेट बंद करता है या "सही शिफ्ट ऑपरेटर" है। मुझे संदेह है कि आधुनिक जावा अब एलएएलआर (1) के साथ पार्स नहीं करता है

लेकिन व्यक्ति दोनों भाषाओं के लिए मजबूत पार्सर (या कमजोर पार्सर और सी और सी ++ फ्रंट एंड के रूप में ज्यादातर अब करते हैं) के उपयोग से पार्सिंग समस्या को पा सकता है। C और C ++ में प्रीप्रोसेसर होने की अतिरिक्त जटिलता है; वे देखने में अभ्यास से अधिक जटिल हैं। एक दावा है कि C और C ++ पार्सर इतने कठिन हैं कि उन्हें हाथ से लिखना होगा। यह सच नहीं है; आप GLR पार्सर जनरेटर के साथ ठीक जावा और C ++ पार्सर का निर्माण कर सकते हैं।

लेकिन पार्सिंग वास्तव में समस्या नहीं है।

एक बार जब आप पार्स करते हैं, तो आप एएसटी / पार्स ट्री के साथ कुछ करना चाहेंगे। व्यवहार में, आपको यह जानना होगा कि हर पहचानकर्ता के लिए, उसकी परिभाषा क्या है और उसका उपयोग कहां किया जाता है ("नाम और प्रकार रिज़ॉल्यूशन", धीरे-धीरे, प्रतीक तालिकाओं का निर्माण)। यह पार्सर सही होने की तुलना में बहुत अधिक काम करता है, विरासत, इंटरफेस, ओवरलोडिंग और टेम्प्लेट द्वारा जटिल, और इस तथ्य से भ्रमित होता है कि यह सब के लिए शब्दार्थ दसियों से सैकड़ों पृष्ठों तक अनौपचारिक प्राकृतिक भाषा में लिखा गया है। भाषा मानक का। सी ++ यहां बहुत खराब है। जावा 7 और 8 इस दृष्टिकोण से बहुत भयानक हो रहे हैं। (और प्रतीक सारणी आप सभी की जरूरत नहीं हैं, "लाइफ आफ्टर पार्सिंग" पर एक लंबे निबंध के लिए मेरा बायो देखें)।

अधिकांश लोग शुद्ध पार्सिंग भाग के साथ संघर्ष करते हैं (अक्सर कभी खत्म नहीं होते हैं; तो कई के लिए खुद ही एसओ की जांच करें, असली लैंगगेज के लिए काम करने वाले पार्सर बनाने के बारे में कई सवाल), इसलिए वे पार्स करने के बाद कभी जीवन नहीं देखते हैं। और फिर हमें इस बारे में लोक प्रमेय मिलते हैं कि पार्स के लिए क्या मुश्किल है और उस चरण के बाद क्या होता है इसके बारे में कोई संकेत नहीं है।

फिक्सिंग C ++ सिंटैक्स आपको कहीं नहीं मिलेगा।

C ++ सिंटैक्स को बदलने के बारे में: आप पाएंगे कि किसी भी C ++ व्याकरण में स्थानीय और वास्तविक अस्पष्टताओं की विविधता का ध्यान रखने के लिए आपको बहुत सारे स्थानों को पैच करना होगा। यदि आप जोर देते हैं, तो निम्नलिखित सूची एक अच्छी शुरुआत हो सकती है । मेरा मानना ​​है कि ऐसा करने का कोई मतलब नहीं है अगर आप सी ++ मानक समिति नहीं हैं; यदि आपने ऐसा किया है, और एक संकलक का उपयोग कर बनाया है, तो कोई भी समझदार इसका उपयोग नहीं करेगा। पार्सर्स बनाने वाले लोगों की सुविधा के लिए मौजूदा C ++ एप्लिकेशन में बहुत अधिक निवेश किया गया है; इसके अलावा, उनका दर्द खत्म हो गया है और मौजूदा पार्सर ठीक काम करते हैं।

आप अपने खुद के पार्सर लिखना चाह सकते हैं। हॉ, वह ठीक है; बस बाकी समुदाय से यह उम्मीद न करें कि आप जिस भाषा का उपयोग करना चाहते हैं उसे बदलने के लिए वे आपको इसे आसान बनाने दें। वे सभी चाहते हैं कि यह उनके लिए आसान हो, और वह भाषा का उपयोग दस्तावेज और कार्यान्वित के रूप में करे।


अच्छा उत्तर। डी और सी + भी देखें, जो इनमें से कुछ मुद्दों को सुलझाने की कोशिश करते हैं। s / सामग्री /
दावेदार

3
मैंने पहले जीवन को पार्स करने के बाद पढ़ा है और इसे एक वास्तविक आंख खोलने वाला पाया है; इसने मुझे स्पष्ट कर दिया कि अर्थ-विश्लेषण (नाम / प्रकार के संकल्प, ...) में कहीं अधिक काम है, जहाँ से पार्सिंग होती है। मैं किसी भी भाषा के वाक्य-विन्यास को बदलने की कोशिश नहीं कर रहा हूँ । मैं यह समझना चाहता हूं कि ऐसी भाषा के गुण क्या हैं जिसमें आप पहले वाक्य विश्लेषण और फिर शब्दार्थ विश्लेषण कर सकते हैं। सी ऐसी भाषा नहीं है (लेक्सर हैक की जरूरत है); मैंने हमेशा सोचा था कि जावा था और मैं जानना चाहता हूं कि क्यों।
कोरोक

1
@ कोरोक: जीएलआर पार्सर्स के साथ जावा / सी ++ बनाने के बारे में मेरा जवाब पढ़ें। आप किसी भी lexer हैक की जरूरत नहीं है । तो, भेद उन लोगों के दिमाग में है जो गलत पार्सिंग तकनीक का उपयोग कर रहे हैं। ... दीक्षित, एक पूर्ण C ++ फ्रंट एंड का निर्माण (esp। C ++ 14, जो हमने किया है) Java8 करने की तुलना में कठिन है, लेकिन वे दोनों कठिन हैं (प्रयास के संदर्भ में और विस्तार पर ध्यान देते हुए) और पार्सिंग सबसे आसान टुकड़ा है।
इरा बाक्सटर

1
मैं आपके "पार्सिंग के बाद का जीवन" के बारे में सहमत हूं: उदाहरण के लिए C # में अधिभार संकल्प किसी भी 3-SAT समस्या को एन्कोड कर सकता है और इस प्रकार एनपी-हार्ड है।
जॉर्ग डब्ल्यू मित्तग

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.