2012-06-29 13 views
5

मेरे पास एक बीबीकोड है -> एचटीएमएल कनवर्टर जो टेक्स्टरेरा में परिवर्तन घटना का जवाब देता है। वर्तमान में, यह नियमित अभिव्यक्तियों की एक श्रृंखला का उपयोग करके किया जाता है, और कई रोगजनक मामले हैं। मैं हमेशा इस व्याकरण पर पेंसिल को तेज करना चाहता था, लेकिन यक शेविंग में नहीं जाना चाहता था। लेकिन ... हाल ही में मुझे pegjs के बारे में पता चला, जो पीईजी पार्सर पीढ़ी का एक पूर्ण पूर्ण कार्यान्वयन प्रतीत होता है। मेरे पास सबसे अधिक व्याकरण निर्दिष्ट है, लेकिन अब मैं सोच रहा हूं कि यह एक पूर्ण उड़ा पार्सर का उचित उपयोग है या नहीं।बीबीसीओडी पार्सिंग के लिए पीईजी पार्सर का उपयोग करना: pegjs या ... क्या?

मेरे विशिष्ट प्रश्न हैं:

  1. अपने आवेदन है कि मैं क्या कर सकते हैं HTML में अनुवाद करने और कच्चे पाठ के रूप में बाकी छोड़ने पर निर्भर करता है, एक पार्सर कि एक सिंटैक्स त्रुटि मेकअप भावना पर असफल हो सकता है का उपयोग कर BBCode को लागू करता है के रूप में ? उदाहरण के लिए: बंद टैग पर समापन ब्रैकेट दर्ज होने के बाद [url=/foo/bar]click me![/url] निश्चित रूप से सफल होने की उम्मीद की जाएगी। लेकिन इस दौरान उपयोगकर्ता क्या देखेगा? रेगेक्स के साथ, मैं केवल गैर-मेल खाने वाली सामग्री को अनदेखा कर सकता हूं और इसे पूर्वावलोकन उद्देश्यों के लिए सामान्य पाठ के रूप में मान सकता हूं। एक औपचारिक व्याकरण के साथ, मुझे नहीं पता कि यह संभव है क्योंकि मैं एक पार्स पेड़ से HTML बनाने पर भरोसा कर रहा हूं और एक पार्स विफल क्या है ... क्या?

  2. मुझे अस्पष्ट है कि परिवर्तन कहाँ किया जाना चाहिए। एक औपचारिक लेक्स/yacc- आधारित पार्सर में, मेरे पास हेडर फाइल और प्रतीक होंगे जो नोड प्रकार को दर्शाते हैं। Pegjs में, मुझे नोड पाठ के साथ घोंसला वाले सरणी मिलती है। मैं अनुवादित कोड को pegjs उत्पन्न पार्सर की क्रिया के रूप में उत्सर्जित कर सकता हूं, लेकिन यह एक पार्सर और एक उत्सर्जक को गठबंधन करने के लिए कोड गंध की तरह लगता है। हालांकि, अगर मैं PEG.parse.parse() कहते हैं, मैं वापस कुछ इस तरह मिलती है:

[ 
     [ 
      "[", 
      "img", 
      "", 
      [ 
      "/", 
      "f", 
      "o", 
      "o", 
      "/", 
      "b", 
      "a", 
      "r" 
      ], 
      "", 
      "]" 
     ], 
     [ 
      "[/", 
      "img", 
      "]" 
     ] 
    ]

की तरह एक व्याकरण दिया:

document 
    = (open_tag/close_tag/new_line/text)* 

open_tag 
    = ("[" tag_name "="? tag_data? tag_attributes? "]") 


close_tag 
    = ("[/" tag_name "]") 

text 
    = non_tag+ 

non_tag 
    = [\n\[\]] 

new_line 
    = ("\r\n"/"\n") 

मैं, व्याकरण abbreviating रहा हूँ ज़ाहिर है, लेकिन आप विचार प्राप्त करें। इसलिए, यदि आप ध्यान देते हैं, तो सरणी की सरणी में कोई प्रासंगिक जानकारी नहीं है जो मुझे बताती है कि मेरे पास किस प्रकार का नोड है और मुझे स्ट्रिंग तुलना करने के लिए छोड़ दिया गया है फिर से यह भी सोचा कि पार्सर ने पहले से ही यह किया है। मुझे उम्मीद है कि कॉलबैक को परिभाषित करना और पर्स के दौरान उन्हें चलाने के लिए कार्रवाइयों का उपयोग करना संभव है, लेकिन वेब पर उपलब्ध छोटी जानकारी उपलब्ध है कि कोई ऐसा कैसे कर सकता है।

क्या मैं गलत पेड़ को भड़क रहा हूं? क्या मुझे रेगेक्स स्कैनिंग पर वापस आना चाहिए और पार्सिंग के बारे में भूल जाना चाहिए?

धन्यवाद

+0

स्टीव, आपका प्रश्न बहुत दिलचस्प है (+1), मैं सिर्फ एक ही विस्तार में एक ही काम करना चाहता हूं: बीबीसीओडी को टेक्स्टरेरा में पार्स करना (दुर्भाग्य से यह प्रारूप अभी भी एक मंच है जिसका उपयोग कर रहा है), और "लाइव" "नियमित अभिव्यक्ति को छोड़कर पीईजी.जेएस या किसी और चीज का उपयोग करके टाइप किए गए पाठ से पूर्वावलोकन करें। क्या आपने बीबीसीओडी पार्सर के लिए व्याकरण बनाने का प्रबंधन किया था? क्या आप गिटहब या कुछ और के माध्यम से अपना समाधान साझा नहीं कर सके? इससे मुझे बहुत मदद मिलेगी। अग्रिम में ही बहुत शुक्रिया! – Sk8erPeter

+0

मैंने [patorjk का bbcode पार्सर] (https://github.com/patorjk/Extendible-BBCode-Parser) का उपयोग किया। यदि आपके पास विशेष टैग हैं तो बहुत अच्छा काम करता है और आपकी खुद की जरूरतों के साथ tweaked किया जा सकता है। –

+0

धन्यवाद, मैंने पहले ही इस पुस्तकालय को देखा है, लेकिन यह नियमित अभिव्यक्तियों का उपयोग करता है, जिन्हें मैं टालना चाहता था, क्योंकि सैद्धांतिक रूप से, नियमित अभिव्यक्तियों का उपयोग करके बीबीसीओडी को पार्स करना बिना दोषों के किया जा सकता है ([»» लिंक] (http: // kore- nordmann.de/blog/do_NOT_parse_using_regexp.html)) कुछ मामलों में, उदाहरण के लिए जब उन्हें एक दूसरे में घोंसला, आदि। यही कारण है कि मैं इसे पार्सिंग अभिव्यक्ति व्याकरण औपचारिकता का उपयोग करके करना चाहता था। तो क्या आपने शुरू किए गए व्याकरण में सुधार करने की कोशिश नहीं की? :) क्या आप इसका आधार साझा नहीं कर सके? :) – Sk8erPeter

उत्तर

2

अपने पहले प्रश्न मैं tosay है कि एक लाइव पूर्वावलोकन मुश्किल होने जा रहा है है के बारे में। पार्सर के बारे में आपने जो समस्याएं इंगित की हैं, वे समझ नहीं पाएंगे कि इनपुट "प्रगति पर काम" सही है। Peg.js आपको बताता है कि किस बिंदु पर त्रुटि है, तो हो सकता है कि आप वह जानकारी ले सकें और कुछ शब्द वापस जाएं और दोबारा पार्स करें या यदि अंत टैग गुम हो जाए तो अंत में इसे जोड़ने का प्रयास करें।

आपके प्रश्न का दूसरा भाग आसान है लेकिन आपका व्याकरण बाद में बहुत अच्छा नहीं लगेगा। मूल रूप से आप क्या, हर नियम पर डाल कॉलबैक है तो उदाहरण

text 
    = text:non_tag+ { 
    // we captured the text in an array and can manipulate it now 
    return text.join(""); 
    } 

फिलहाल के लिए आप अपने व्याकरण में इनलाइन इन कॉलबैक लिखने के लिए की है। मैं अभी इस काम में बहुत सारी चीज़ें कर रहा हूं, इसलिए मैं इसे ठीक करने के लिए peg.js को पुल कर सकता हूं। लेकिन मुझे यकीन नहीं है कि मुझे ऐसा करने का समय मिल जाएगा।

1

इस प्रतिस्थापन नियम की तरह कुछ कोशिश करें। आप सही रास्ते पर हैं; आपको सिर्फ परिणामों को इकट्ठा करने के लिए यह बताना होगा।

टेक्स्ट = परिणाम: non_tag + {return result.join (''); }

3

पहला सवाल (अधूरा ग्रंथों के लिए व्याकरण):

आपopen_tag के बाद

incomplete_tag = ("[" tag_name "="? tag_data? tag_attributes?) 
//       the closing bracket is omitted ---^ 

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

दूसरा सवाल (कैसे कार्य इस प्रकार हैं करने के लिए):

आप भाव के बाद कार्यों socalled लिखें। एक क्रिया ब्रेसिज़ द्वारा संलग्न जावास्क्रिप्ट कोड है और एक pegjs अभिव्यक्ति के बाद अनुमति दी जाती है, i। ई। एक उत्पादन के बीच में भी!

अभ्यास कार्यों में { return result.join("") } लगभग हमेशा आवश्यक हैं क्योंकि pegjs एकल वर्णों में विभाजित होता है। जटिल घोंसला वाले सरणी भी लौटाए जा सकते हैं। इसलिए मैं आमतौर पर क्रियाओं को छोटा रखने के लिए व्याकरण के सिर पर pegjs प्रारंभकर्ता में सहायक कार्यों को लिखता हूं। यदि आप फ़ंक्शन नामों को ध्यान से चुनते हैं तो कार्रवाई स्वयं-दस्तावेज़िंग होती है।

एक परीक्षा के लिए PEG for Python style indentation देखें। अस्वीकरण: यह मेरा जवाब है।

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