कंपाइलर कंपाइलर लिखना - इनसाइट ऑन यूज एंड फीचर्स


10

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

इन प्रश्नों से जुड़े कुछ अन्य पृष्ठ, संरचनात्मक टाइपिंग से संबंधित, यहाँ देखे जा सकते हैं और उपयोग में आसानी हो सकती है । रूपरेखा के बारे में पूछताछ और पोस्ट करने के उचित स्थान के बारे में मेटा-विषय यहां पाया जा सकता है

मैं उस बिंदु पर पहुंच रहा हूं, जहां मैं एक दिए गए व्याकरण में से पार्स ट्री को निकालना शुरू करने वाला हूं, उसके बाद एक रिकर्सिव डिसेंट पार्सर है जो आगे के रास्तों को भेदने के लिए DFA का उपयोग करता है (ANTLR 4 के LL (*) के समान, इसलिए मैं मुझे लगा कि मैं इसे जानकारी प्राप्त करने के लिए खोलूंगा।

पार्सर कंपाइलर में, किस प्रकार की विशेषताएं आदर्श हैं?

अब तक यहाँ क्या लागू है का एक संक्षिप्त अवलोकन है:

  1. टेम्पलेट्स
  2. आगे की भविष्यवाणी देखें, यह जानते हुए कि किसी दिए गए बिंदु पर क्या मान्य है।
  3. नियमों के भीतर शाब्दिक रूप से 'डिलेरलाइज़ेशन' नियम लेना और हल करना कि वे किस टोकन से हैं।
  4. ननदेर्तिमान आटोमैटा
  5. नियतात्मक ऑटोमेटा
  6. टोकन मान्यता के लिए सरल शाब्दिक राज्य मशीन
  7. टोकन स्वचालन विधि:
    • स्कैन - टिप्पणियों के लिए उपयोगी: टिप्पणी: = "/ *" स्कैन ("* /");
    • घटाव - पहचानकर्ताओं के लिए उपयोगी: पहचानकर्ता: = घटाना (पहचानकर्ता, खोजशब्द);
      • यह सुनिश्चित करता है कि पहचानकर्ता खोजशब्दों को स्वीकार नहीं करता है।
    • एनकोड - बेस एन संक्रमण की एक श्रृंखला एक्स गिनती के रूप में एक स्वचालन को एनकोड करता है।
      • यूनिकोडएस्केप: = "\\ u" बेसएकोड (पहचानकर्ताचेरोइस्केप, 16, 4);
        • हेक्साडेसिमल में एक यूनिकोड से बच जाता है, हेक्स 4-संक्रमण के साथ। इस के बीच का अंतर और: [0-9A-Fa-f] {4} परिणामी स्वचालन है, जिसमें एनकोड के साथ हेक्साडेसिमल मानों के अनुमत सेट को IdentifierCharNoEscape के दायरे में सीमित किया गया है। इसलिए यदि आप इसे \ u005c देते हैं, तो एन्कोड संस्करण मान को स्वीकार नहीं करेगा। इस तरह की चीजों में एक गंभीर चेतावनी है: संयम से उपयोग करें। परिणामस्वरूप स्वचालन काफी जटिल हो सकता है।

क्या लागू नहीं किया गया है सीएसटी पीढ़ी, मुझे इस काम को पाने के लिए उचित संदर्भ को ले जाने के लिए निर्धारक स्वचालन को समायोजित करने की आवश्यकता है।

रुचि रखने वाले किसी भी व्यक्ति के लिए, मैंने T * yप्रोजेक्ट के मूल रूप का एक सुंदर प्रिंट अपलोड किया है । प्रत्येक फ़ाइल को हर दूसरी फ़ाइल से लिंक करना चाहिए, मैंने उन्हें अनुसरण करने के लिए अलग-अलग नियमों में लिंक करना शुरू किया, लेकिन इसमें बहुत लंबा समय लगेगा (स्वचालित करने के लिए सरल हो गया होगा!)

यदि अधिक संदर्भ की आवश्यकता है, तो कृपया तदनुसार पोस्ट करें।

5-14-2013 को संपादित करें : मैंने दिए गए भाषा के भीतर राज्य मशीनों के लिए ग्राफविज़ ग्राफ बनाने के लिए कोड लिखा है। यहाँ विधानसभापार्ट का ग्राफविज़ डिग्राफ है । भाषा विवरण में जुड़े सदस्यों के पास उस नियम के लिए उनके संबंधित फ़ोल्डर में एक rulename.txt होना चाहिए। उदाहरण पोस्ट करने के बाद से कुछ भाषा विवरण बदल गए हैं, यह व्याकरण के बारे में चीजों को सरल बनाने के कारण है। यहाँ एक दिलचस्प ग्राफविज़ छवि है


8
दीवार ओ ’पाठ। इसे गलत तरीके से न लें, मैं पूरी तरह से बताई गई समस्या की सराहना करता हूं। इस मामले में यह बस थोड़ी बहुत क्रिया है। जो मैंने इकट्ठा किया है, उससे आप पूछ रहे हैं कि एक व्याकरण पार्सर में क्या विशेषताएं शामिल होनी चाहिए या खरोंच से शुरू किए बिना एक कैसे बनाएं? कृपया निम्नलिखित प्रश्नों का उत्तर देने के लिए संपादित करें (आपको फिर से लिखना नहीं है, बस सारांश में अंत तक संलग्न करें): आपकी समस्या क्या है? आपकी समस्या के संभावित समाधानों में आप किस बाधा से बंधे हैं (यह तेजी से होना चाहिए, यह एलएल * होना चाहिए, आदि)?
नील

1
मैं फीचर सेट के बारे में जानकारी मांग रहा हूं। उपयोग में आसानी पर ध्यान केंद्रित किया गया है। कठिनाई किसी ऐसे व्यक्ति को प्राप्त करने में है जो परियोजना को नहीं जानता है, परियोजना पर अंतर्दृष्टि इसलिए कि वे इसके फोकस की ओर सूचित हैं। मैं 'कैसे करना है' के लिए नहीं कह रहा हूँ, मैं प्रयोज्य से संबंधित पूछ रहा हूँ। प्रश्न को कैसे ट्रिम किया जाए, इसके सुझाव की सराहना की जाती है।
एलन क्लार्क कोपलैंड जूनियर

1
मेरे लिए, यह स्पष्ट नहीं है कि परियोजना क्या है। उदाहरण के लिए, याक के दिनों से, हमने बहुत सारे पार्सर जनरेटर देखे हैं। आपके OILexer में क्या अलग है? नया क्या है?
इंगो'

1
इस परियोजना का लक्ष्य पार्सर पीढ़ी को सरल बनाना है। इसी तरह की हां, YACC / Bison और FLEX / LEX के लिए। मुख्य अंतर उन कार्यक्रमों में शामिल जटिलता से बचने के लिए है। चीजों को सरल और बिंदु पर रखना मुख्य लक्ष्य है। यही कारण है कि मैंने एक प्रारूप बनाया जो विषम सेक्शनिंग से रहित है, बल्कि यह लक्ष्य है कि इसे नियमित प्रोग्रामिंग के समान बनाया जाए: केवल भाषा विकास के लिए। उनके नाम के बाद '': = '' का उपयोग कर परिभाषित किया गया है, उनके नाम के बाद नियमों का उपयोग किया गया है। टेम्प्लेट '::' = '' के बाद उनके तर्क के लिए '<' और '>' का उपयोग करते हैं क्योंकि वे नियम वाक्य विन्यास साझा करते हैं।
एलन क्लार्क कोपलैंड जूनियर

3
पार्सिंग पर यह नारकीय ध्यान गलत लगता है; इसकी एक अच्छी तरह से हल की गई समस्या है, और यह प्रोग्रामिंग भाषाओं को संसाधित करने के लिए आपको शायद ही कुछ देता है। मेरे जीवन पर "निबंध के बाद जीवन" के लिए Google।
इरा बैक्सटर

जवाबों:


5

यह एक अच्छा सवाल है।

मैं हाल ही में बहुत सारे पार्सिंग पर काम कर रहा हूं, और IMHO की कुछ प्रमुख विशेषताएं हैं:

  • एक प्रोग्राम एपीआई - तो इसका उपयोग प्रोग्रामिंग भाषा के भीतर से किया जा सकता है, आदर्श रूप से बस एक पुस्तकालय आयात करके। इसमें GUI या BNF जैसा इंटरफ़ेस हो सकता है, लेकिन प्रोग्रामेटिक एक ही कुंजी है, क्योंकि आप अपने टूलिंग, IDE, स्थैतिक विश्लेषण, परीक्षण, भाषा अमूर्त सुविधाओं, प्रोग्रामर परिचित, प्रलेखन जनरेटर, बिल्ड प्रक्रिया का पुनः उपयोग कर सकते हैं, आदि, आप छोटे पार्सरों के साथ अंतःक्रियात्मक रूप से खेल सकते हैं, जो नाटकीय रूप से सीखने की अवस्था को कम करता है। ये कारण इसे मेरी "महत्वपूर्ण विशेषताओं" सूची में सबसे ऊपर रखते हैं।

  • त्रुटि रिपोर्टिंग, जैसा कि @guysherman ने उल्लेख किया है। जब कोई त्रुटि पाई जाती है, तो मैं जानना चाहता हूं कि त्रुटि कहां थी और ऐसा होने पर क्या हो रहा था। दुर्भाग्य से, मैं यह समझाने में सक्षम नहीं हो पाया कि जब बैकग्राउंड खेलने के लिए आता है तो सभ्य त्रुटियों को कैसे उत्पन्न किया जाए। (हालांकि नीचे @ Sk- तर्क की टिप्पणी)।

  • आंशिक परिणाम। जब पार्सिंग विफल हो जाता है, तो मैं यह देखना चाहता हूं कि त्रुटि के स्थान से पहले इनपुट के भाग से सफलतापूर्वक क्या पार्स किया गया था।

  • अमूर्त। आप कभी भी पर्याप्त कार्यों में निर्माण नहीं कर सकते हैं, और उपयोगकर्ता को हमेशा अधिक की आवश्यकता होगी, इसलिए सभी संभावित कार्यों को अप-फ्रंट करने की कोशिश करने से विफलता का संकेत मिलता है। क्या इसका मतलब है कि आप टेम्प्लेट से हैं?

  • मैं आपके # 2 (देखो-आगे की भविष्यवाणी) से सहमत हूं। मुझे लगता है कि यह अच्छी त्रुटि रिपोर्ट उत्पन्न करने में मदद करता है। क्या यह किसी और चीज के लिए उपयोगी है?

  • पार्सिंग के रूप में पार्स ट्री बनाने के लिए समर्थन होता है, शायद:

    • एक ठोस वाक्यविन्यास पेड़, जिसके लिए पेड़ की संरचना सीधे व्याकरण से मेल खाती है और बाद के चरणों की त्रुटि रिपोर्टिंग के लिए लेआउट जानकारी शामिल है। इस मामले में, ग्राहक को सही पेड़ संरचना प्राप्त करने के लिए कुछ भी नहीं करना चाहिए - यह सीधे व्याकरण पर निर्भर होना चाहिए।
    • एक सार वाक्यविन्यास पेड़। इस मामले में, उपयोगकर्ता किसी भी और सभी पार्स पेड़ों के साथ बेला करने में सक्षम है
  • किसी प्रकार का प्रवेश। मुझे इस पर यकीन नहीं है; हो सकता है कि नियमों के एक ट्रेस दिखाने के लिए पार्सर ने कोशिश की हो, या व्हाट्सएप या टिप्पणियों जैसे जंक टोकन का ट्रैक रखने के लिए, उदाहरण के लिए (उदाहरण के लिए) आप HTML प्रलेखन उत्पन्न करने के लिए टोकन का उपयोग करना चाहते हैं।

  • संदर्भ संवेदनशील भाषाओं से निपटने की क्षमता। यह निश्चित नहीं है कि यह कितना महत्वपूर्ण है, या तो - व्यवहार में, यह एक संदर्भ-मुक्त व्याकरण के साथ भाषा के सुपरसेट को पार्स करने के लिए क्लीनर लगता है, फिर अतिरिक्त-बाद में पास के संदर्भ-संवेदनशील बाधाओं की जांच करने के लिए।

  • कस्टम त्रुटि संदेश, ताकि मैं विशिष्ट स्थितियों में त्रुटि रिपोर्ट को ट्यून कर सकूं और शायद अधिक तेज़ी से समझ और समस्याओं को ठीक कर सकूं।

दूसरी ओर, मुझे त्रुटि-सुधार विशेष रूप से महत्वपूर्ण नहीं लगता - हालाँकि मैं वर्तमान प्रगति पर अद्यतित नहीं हूँ। मैंने जिन समस्याओं पर ध्यान दिया है वे हैं कि संभावित सुधार जो उपकरण आपूर्ति करते हैं: 1) बहुत सारे, और 2) वास्तविक गलतियों के अनुरूप नहीं हैं, और इसलिए यह सब मददगार नहीं हैं। उम्मीद है कि इस स्थिति में सुधार होगा (या शायद पहले से ही ऐसा किया गया है)।


मैंने प्रश्न निकाय को 'टेम्प्लेट' पढ़ने वाली बुलेट में PrecedenceHelper का लिंक शामिल करने के लिए संपादित किया है। यह पैरामीटर सरणी ट्यूपल्स की अनुमति देता है, इसलिए यदि आपके पास चार पैरामीटर हैं, तो प्रत्येक पैरामीटर सरणियों, टेम्पलेट का उपयोग चार के तर्क सेटों में किया जाना चाहिए।
एलन क्लार्क कोपलैंड

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

मैंने उपयोग के लिए उपलब्ध कार्यों के विषय पर फिर से प्रश्न संपादित किया है।
एलन क्लार्क कोपलैंड

मुझे लगता है कि मैंने टेम्प्लेट / फ़ंक्शंस के बारे में अपनी बात व्यक्त करते हुए एक बढ़िया काम नहीं किया: मेरा मतलब था कि क्योंकि आपके पास कभी भी पर्याप्त नहीं हो सकता है, सिस्टम को समय से पहले यह पता लगाने की कोशिश नहीं करनी चाहिए: उपयोगकर्ता को बनाने में सक्षम होने की आवश्यकता है उसका अपना।

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

5

मैं भाषा डिजाइन में अनुभवी नहीं हूं, लेकिन मैंने एक बार एक पार्सर लिखने के लिए जाना था, जब मैं एक गेम इंजन के लिए आईडीई और आईडीई बना रहा था।

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

तो आपको इसके बजाय क्या चाहिए? मुझे लगता है कि इसके बजाय सिर्फ यह जानना कि क्या एक बिंदु पर मान्य नहीं है / है, आपको यह जानने की जरूरत है कि कैसे मान्य नहीं है और इसे मान्य बनाने के लिए न्यूनतम परिवर्तन करें - ताकि आप संबंधित गलत त्रुटियों को उत्पन्न किए बिना पार्सिंग जारी रख सकें। अपने पुनरावर्ती वंश में भ्रमित हो रहे हैं। एक पार्सर का निर्माण करने में सक्षम होना जो इस जानकारी को उत्पन्न कर सकता है, न केवल आपको बहुत मजबूत पार्सर देता है, बल्कि यह सॉफ्टवेयर के लिए कुछ शानदार विशेषताओं को खोलता है जो पार्सर का उपभोग करता है।

मुझे एहसास है कि मैं वास्तव में कुछ मुश्किल, या मूर्खतापूर्ण स्पष्ट रूप से सुझाव दे सकता हूं, अगर ऐसा है तो क्षमा करें। यदि यह उस प्रकार की चीज नहीं है जिसे आप खोज रहे हैं, तो मैं खुशी से अपना उत्तर हटा दूंगा।


यह एक ऐसी चीज है जिसे मैं करने की योजना बना रहा हूं। डोमेन के अपने ज्ञान के साथ सहायता करने के लिए, मेरे एक दोस्त ने सुझाव दिया कि इसे स्वचालित करने के लिए हाथ से एक वास्तविक पार्सर लिखना। एक बात मुझे बहुत जल्दी महसूस हुई: पार्सर जटिल हैं और ऐसी चीजें हैं जो हम हाथ से करते हैं जो प्रक्रिया को सरल बनाते हैं। नियम और टेम्पलेट समान सिंटैक्स साझा करते हैं; हालाँकि, ऐसे भाषा तत्व हैं जो टेम्प्लेट में मान्य हैं, लेकिन नियम नहीं हैं, इस कार्य को संभालने वाले आंतरिक राज्य हैं। जो मन में एक विचार लाया: नियमों को साझा करने के उप-नियमों को आसान बनाने के लिए पथ सहायक निर्दिष्ट करने में सक्षम होना चाहिए।
एलन क्लार्क कोपलैंड जूनियर

... यह स्वचालन में ले जाने के लिए काफी सरल होना चाहिए, लेकिन ऑटोमेशन के लिए राज्य-आधारित स्थितियों की आवश्यकता होगी। मैं इस पर काम करूंगा और आपको वापस लाऊंगा। ANTLR कहती है: "T" *, जहां मैं इसे सबसे अधिक पार्स प्रक्रिया को संभालने के लिए उपयोग करूँगा, क्योंकि जब कोई नियम में 800+ भिन्नताएँ होती हैं, तो क्लीनर को संभालना चाहिए। जल्दी से मानक के रूप में स्पेगेटी कोड के रूप में अगर / और फार्म।)
एलन क्लार्क कोपलैंड जूनियर

0

व्याकरण में "पुनरावर्ती नियमों को नहीं छोड़ा है" जैसे प्रतिबंध नहीं होने चाहिए। यह हास्यास्पद है कि आज व्यापक रूप से उपयोग किए जाने वाले उपकरणों में यह है और केवल एलएल व्याकरण चूसने को समझ सकते हैं - याक के ठीक 50 साल बाद ।

सही पुनरावर्तन (याक सिंटैक्स का उपयोग करके) के लिए एक उदाहरण:

list: 
      elem                  { $$ = singleton($1); }
    | elem ',' list         { $$ = cons($1, $2);  }
    ;

बाईं पुनरावृत्ति के लिए एक उदाहरण (yacc synatx का उपयोग करके):

funapp:
    term                    { $$ = $1; }
    | funapp term           { $$ = application($1, $2); }
    ;

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

एक उन्नत उपकरण से उम्मीद कर सकता है कि वे सामान को लिखने के लिए प्राकृतिक तरीके का समर्थन करते हैं, इसके बजाय एक को "रिफ्लेक्टर" की आवश्यकता होती है सब कुछ छोड़ दिया / सही पुनरावर्ती रूप से एक पर उपकरण थोपता है।


हां, यह अच्छा है कि इस तरह के मनमाने प्रतिबंध न हों। हालांकि, वाम-पुनरावृत्ति का एक उदाहरण क्या है जिसे पुनरावृत्ति ऑपरेटर (जैसे रेगेक्स *या एम्पलीफायरों +) के साथ प्रतिस्थापित नहीं किया जा सकता है ? मैं स्वतंत्र रूप से स्वीकार करता हूं कि इस क्षेत्र में मेरा ज्ञान सीमित है, लेकिन मैं कभी भी वाम-पुनरावृत्ति के उपयोग में नहीं चला हूं जिसे पुनरावृत्ति में शामिल नहीं किया जा सकता है। और मैंने पुनरावृत्ति संस्करण को और अधिक स्पष्ट पाया (हालांकि यह सिर्फ व्यक्तिगत पसंद है)।

1
@MattFenwick मेरा संपादन देखें सिंटैक्स ट्री बनाने के लिए सिंटैक्स निर्देश सरल और प्राकृतिक सिमेंटिक क्रियाओं (जैसे) की ओर जाता है। पुनरावृत्ति के साथ, (जो yacc, btw में उपलब्ध नहीं है), मुझे लगता है कि आपको अक्सर यह जांचने की आवश्यकता है कि क्या आपको एक खाली सूची, एक सिंगलटन इत्यादि मिली है
Ingo

जवाब देने के लिए धन्यवाद। मुझे लगता है कि मैं अब बेहतर ढंग से समझने - मैं उन उदाहरण के रूप में लिखने के लिए पसंद करेंगे list = sepBy1(',', elem)और funapp = term{+}(और निश्चित रूप से sepBy1और +बाईं / सही-प्रत्यावर्तन के संदर्भ में लागू किया जाएगा, और मानक वाक्य रचना पेड़ों की उपज)। तो ऐसा नहीं है कि मुझे लगता है कि लेफ्ट- और राइट-रिकर्सियन खराब हैं, यह सिर्फ इतना है कि मुझे लगता है कि वे निम्न स्तर के हैं और उच्च स्तरीय एब्सट्रैक्शन का उपयोग करना चाहते हैं जहां चीजें स्पष्ट करना संभव है। एक बार फिर धन्यवाद!

1
आपका @MattFenwick में स्वागत है। लेकिन फिर यह शायद स्वाद का मामला है। मेरे लिए, पुनरावृत्ति (कम से कम भाषाओं के संदर्भ में है, जो सभी स्वाभाविक रूप से पुनरावर्ती या पूरी तरह से निर्बाध हैं) इसके बारे में सोचने का अधिक प्राकृतिक तरीका है। इसके अलावा, एक पेड़ एक पुनरावर्ती डेटा संरचना है, इसलिए मुझे पुनरावृत्ति का अनुकरण करने के लिए पुनरावृति में गिरने की कोई आवश्यकता नहीं है । लेकिन, ज़ाहिर है, प्राथमिकताएं अलग हैं।
इंगो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.