2012-03-31 12 views
11

हम सभी जानते हैं कि नियमित अभिव्यक्तियों का उपयोग करके HTML को पार्स करना आम तौर पर संभव नहीं है, क्योंकि यह संदर्भ-संवेदनशील व्याकरण को पार्स कर रहा है, जबकि नियमित अभिव्यक्ति केवल नियमित व्याकरण को पार्स कर सकती है। अन्य प्रोग्रामिंग भाषाओं के लिए भी यह सच है।नियमित अभिव्यक्तियों का उपयोग कर प्रोग्रामिंग भाषाओं को सिंटैक्स-हाइलाइट करना संभव है?

अब, हाल ही में, Rainbow.js वाक्य रचना हाइलाइटर घोषणा की गई है। इसका आधार यह बहुत ही सरल रूप में वर्णित है: अपने आप ही

इंद्रधनुष बहुत सरल है। यह कोड ब्लॉक, प्रक्रिया regex पैटर्न, और टैग में मिलान पैटर्न wraps के माध्यम से चला जाता है।

मैं लगा वाक्य रचना हाइलाइटिंग अनिवार्य रूप से, भाषा पार्स के रूप में ही जटिलता का एक काम है अगर हम यह मान यह दोनों अच्छे और कई भाषाओं के लिए उपयुक्त हो गया है। फिर भी, जबकि वहाँ काफी है कि पुस्तकालय के criticism, न कि का एक सा है और न ही HackerNews discussion (तकनीकी रूप से इच्छुक द्वारा एक चर्चा के लिए एक उदाहरण के रूप में लिया है) का उल्लेख किया है कि नियमित रूप से अभिव्यक्ति का उपयोग करते वाक्य रचना पर प्रकाश डाला एक सामान्य मामले में मूल रूप से असंभव है, जो मैं एक प्रमुख, शो-स्टॉपिंग दोष पर विचार करें। वहाँ कुछ मैं याद कर रहा हूँ है:

अब सवाल यह है कि? विशेष रूप से:

  1. सामान्य रूप से सामान्य अभिव्यक्तियों के साथ सिंटैक्स हाइलाइटिंग संभव है?
  2. क्या यह एक लागू 80/20 नियम का एक उदाहरण है, जहां नियमित अभिव्यक्तियों के साथ पर्याप्त संभव है?

उत्तर

3

आप समाधान के भाग के रूप में नियमित अभिव्यक्तियों का उपयोग करके सिंटैक्स हाइलाइटिंग कर सकते हैं। अधिक विशेष रूप से, "लेक्सर" के हिस्से के रूप में जो इनपुट टेक्स्ट को प्रतीकों में जोड़ता है। यह वास्तव में सबसे अधिक संकलक/दुभाषिया काम करते हैं।

रेगेक्स अकेले का उपयोग करके ऐसा करने के लिए, परेशानी के लिए पूछ रहा है। पायथन में एक स्ट्रिंग से मिलान करने के मामले पर विचार करें। पायथन स्ट्रिंग को एकल कोट्स ' या डबल कोट्स " द्वारा सीमित करने की अनुमति देता है। इसके अतिरिक्त, यह ट्रिपल-कोट्स, ''' या """ का उपयोग करके मल्टी-लाइन स्ट्रिंग्स ("हेरेडोक सिंटैक्स") की अनुमति देता है।

तो अनुसरण कर रहे हैं तार के जो भागों, और कौन से नहीं? क्या आप नियमित अभिव्यक्ति का निर्माण कर सकते हैं जो स्ट्रिंग अक्षर str1 - str6 सही ढंग से पहचानता है?

str1 = "hello, world!" 

str2 = 'hello, world!' 

str3 = "The canonical test program is 'Hello World'." 

str4 = '"Why," Peter said, "That\'s ludicrous. Who would do that?"' 

str5 = """The heredoc syntax is handy for cases where you don't want to escape strings. "Very convenient." 
""" 

str6 = """Code sample: 
s1 = "hi!" 
s2 = 'Hi!' 
S3 = ''' 
- apples 
- oranges 
- bananas 
''' 
""" 

तर्क यह है कि "आप (पार्स HTML | प्रक्रिया प्रोग्राम) नहीं कर सकते regex के साथ क्योंकि (एचटीएमएल | प्रोग्रामिंग भाषाओं) संरचनाओं नेस्ट है - वे नियमित नहीं हैं" पूरी तरह सच नहीं है - आधुनिक नियमित अभिव्यक्तियों (विशेष रूप से पर्ल में) कंप्यूटर विज्ञान विज्ञान में कड़ाई से नियमित अभिव्यक्तियों की तुलना में अधिक अभिव्यक्तिपूर्ण शक्ति होती है। लेकिन सिर्फ इसलिए कि आप can use regular expressions का मतलब यह नहीं है कि होना चाहिए।


संपादित करें: स्ट्रिंग मिलान समस्या ऊपर बहुत बुरा अपने regex स्वाद खोज पैटर्न में backreferences समर्थन करता है तो नहीं है। ('|"|'''|""").+?\1 जैसे बहु-लाइन रेगेक्स शायद ऐसा करेंगे।


संपादित करें 2: वाक्य रचना hilighting में कोने मामलों का एक उदाहरण के लिए, ऊपर कोड की StackOverflow की वाक्य रचना हाइलाइटिंग से स्थान है।

+0

ठीक है, क्योंकि एक लेक्सर संदर्भ-मुक्त व्याकरण (सीएफजी) को परिभाषित करता है, लेकिन नियमित अभिव्यक्ति केवल नियमित व्याकरण (आरजी) को परिभाषित कर सकती है। – Daniel

+1

"लेक्सर" का उपयोग जरूरी नहीं है कि संदर्भ-मुक्त व्याकरण - व्याख्यात्मक विश्लेषण कुछ ऐसा है जो आप सभी प्रकार की भाषाओं में कर सकते हैं। उस ने कहा, अधिकांश प्रोग्रामिंग भाषाओं में संदर्भ मुक्त व्याकरण होते हैं। –

+0

मुझे संदेह है कि आपको 1 9वीं शताब्दी में रेगेक्स की गणितीय परिभाषा में शामिल किसी भी फैंसी फीचर्स की भी आवश्यकता नहीं है। आपके द्वारा दिए गए बैक-रेफरेंस को आसानी से बदला जा सकता है क्योंकि यह केवल चार चीजों में से एक हो सकता है - '(' ... ') | ("...") | (' '' ... '' ') | ("" "..." "") '। [पायथन भाषा संदर्भ] (http://docs.python.org/reference/lexical_analysis.html#string-literals) में प्रत्येक प्रकार की स्ट्रिंग में क्या सटीक रूप से वर्णित किया जा सकता है और रेगेक्स में अनुवाद करने के लिए पर्याप्त सरल लगता है। – delnan

2

असल में, नहीं।

आपको एक पार्सर/टोकनेज़र की आवश्यकता है जो भाषा को समझने के लिए समझता है कि किन बिट्स को हाइलाइट करना है।

रेगेक्स इस तरह के कार्य के लिए सरसों काट नहीं देता है।

+3

-1 गलत: सिंटैक्स हाइलाइटिंग के लिए, आपको * भाषा * पार्स करने की आवश्यकता नहीं है, आपको बस * टोकननाइज़ करने की आवश्यकता है।आप जानते हैं, पता लगाएं कि कौन सा हिस्सा एक स्ट्रिंग शाब्दिक या पहचानकर्ता या एक पूर्णांक शाब्दिक या एक कीवर्ड है। गीलेर इसके चारों ओर माता-पिता हैं, और गीले वे संतुलित हैं, प्रासंगिक नहीं है। – delnan

+2

क्षमा करें, यह झूठा है। सिंटेक्स हाइलाइटिंग को घोंसले की संरचनाओं को पहचानने की आवश्यकता है। यह भाषा पर निर्भर करता है। कुछ भाषाओं के लिए, केवल टोकन की पहचान पर्याप्त नहीं है। और कुछ वाक्यविन्यास हाइलाइटिंग असंतुलित कोष्ठक पहचानता है: उदा। विम। – Kaz

+2

@ डेलनान मैं असहमत हूं, क्योंकि यह निर्भर करता है कि आप किस प्रकार की हाइलाइटिंग चाहते हैं। यदि यह केवल कीवर्ड ठीक है टोकननाइज है, लेकिन यदि आप मिलान करने वाले घुंघराले ब्रैकेट को हाइलाइट करना चाहते हैं, या किसी विधि को पतन करना चाहते हैं (जैसे एक्लिप्स करता है) - आपको भाषा के बारे में जानना होगा। इसके अलावा, "पार्स" और "टोकनिज" का काफी निकट अर्थ है, खासकर जब रेगेक्स का उपयोग करने की तुलना में। मैंने अपना जवाब "टोकनइज़" शामिल करने के लिए संपादित किया है और ऐसा करने से मुझे विश्वास नहीं है कि मेरे उत्तर का मूल अर्थ बदलता है। साथ ही, उच्चतम मतदान वाले उत्तर को पढ़ें - यह मूल रूप से कहता है कि मैं क्या कह रहा हूं। – Bohemian

11

regexp का उपयोग कर सिंटेक्स हाइलाइटिंग एक पुरानी कला है। मुझे लगता है कि यहां तक ​​कि Emacs और vi भी इस तरह से शुरू किया।

मैं लगा वाक्य रचना हाइलाइटिंग अनिवार्य रूप से, भाषा पार्स के रूप में ही जटिलता का एक काम है [...]

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

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

बेशक वहाँ कोने के मामले हैं जो अकेले regexp पकड़ नहीं सकते हैं। एक विशिष्ट उदाहरण है:

foo(bla, bar); 

यहाँ foo एक स्थिर विधि या एक उदाहरण विधि या किसी मैक्रो या कुछ और करने के लिए एक फोन हो सकता है। लेकिन आपका regexp हाइलाइटर इसे कम नहीं कर सकता है। यह केवल "सामान्य कॉल" के लिए रंग जोड़ सकता है।

तो: यदि आपकी आवश्यकताएं निम्न स्तर (यानी उपरोक्त उदाहरण के बिना) हैं और आम तौर पर असली दुनिया सामग्री के लिए 90/10 नियम हैं तो यह 100/0 प्रतिशत नियम है।

+0

+1। सभी उत्कृष्ट अंक। –

1

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

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

यह दृष्टिकोण विभिन्न शब्दावली गुणों के साथ एम्बेडिंग के विभिन्न स्तरों को संभाल सकता है।

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

इस के उदाहरण के लिए: http://www.kylheku.com/cgit/txr/tree/genman.txr देखें। यदि आप सिंटैक्स (do खोजते हैं तो आप पाएंगे कि एक उदाहरण रंगीन बैंगनी है, और दूसरा हरा है। वे अलग हैं: एक टेक्स्ट निष्कर्षण भाषा में है, और दूसरा एम्बेडेड लिस्प बोली में है। विम का सिंटैक्स हाइलाइटिंग कीवर्ड के विभिन्न सेटों के साथ भाषाओं के मिश्रण को संभालने के लिए पर्याप्त शक्तिशाली है। (हाँ, हालांकि यह वेब पर पेश किया जाता है, यह वास्तव में वाक्य रचना हाइलाइटिंग कर एक विम प्रक्रिया है।)

या खोल, आप एक स्ट्रिंग शाब्दिक प्रकार वाक्य रचना हो सकता है जहां, "foo bar" की तरह की तरह कुछ है, लेकिन वहाँ के अंदर विचार करते हैं, आपके पास कमांड प्रतिस्थापन हो सकता है, जिसके अंदर आपको शेल सिंटैक्स को दोबारा पहचानना और रंगना होगा: "foo $(for x in *; do ...; done) bar"

तो नहीं, आप रेगेक्स टोकनिंग के साथ उपयोगी, सटीक सिंटैक्स higlighting नहीं कर सकते हैं, लेकिन पदानुक्रमित पार्सिंग के साथ regexes एक अच्छा काम कर सकते हैं।

संबंधित मुद्दे

 संबंधित मुद्दे