簡體   English   中英

使用PEG Parser進行BB​​Code解析:pegjs或……什么?

[英]Using PEG Parser for BBCode Parsing: pegjs or … what?

我有一個bbcode-> html轉換器,它響應textarea中的change事件。 當前,這是使用一系列正則表達式完成的,並且存在許多病理情況。 我一直想在這種語法上使鉛筆更鋒利,但又不想into牛刮胡。 但是...最近,我意識到了pegjs ,這似乎是PEG解析器生成的相當完整的實現。 我已經指定了大部分語法,但是現在想知道這是否適合使用成熟的解析器。

我的具體問題是:

  1. 由於我的應用程序依賴於將我可以轉換的內容轉換為HTML並將其余內容保留為原始文本,因此使用可能因語法錯誤而失敗的解析器實現bbcode有意義嗎? 例如:一旦輸入close標簽上的右括號, [url=/foo/bar]click me![/url]當然會成功。 但是在此期間,用戶會看到什么? 使用正則表達式,我可以忽略不匹配的內容,並將其視為普通文本以進行預覽。 使用正式的語法,我不知道這是否可行,因為我依賴於從解析樹創建HTML,而解析失敗的原因是什么?

  2. 我不清楚應該在哪里進行轉換。 在基於lex / yacc的正式解析器中,我將具有表示節點類型的頭文件和符號。 在pegjs中,我得到帶有節點文本的嵌套數組。 我可以將翻譯后的代碼作為由pegjs生成的解析器的操作來發出,但是將解析器和發射器結合起來似乎具有代碼味道。 但是,如果我調用PEG.parse.parse()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")

當然,我在縮寫語法,但是您明白了。 因此,如果您注意到,在數組數組中沒有上下文信息可以告訴我我擁有哪種節點即使認為解析器已經做到了,我仍然可以再次進行字符串比較。 我希望可以在解析期間定義回調並使用操作來運行它們,但是Web上很少有關於如何做的信息。

我在樹上叫錯了嗎? 我應該退回到正則表達式掃描而忘記解析嗎?

謝謝

第一個問題 (不完整文本的語法):

你可以加

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

open_tag 之后 ,並將document更改為在末尾包含不完整的標簽。 訣竅在於,您為解析器提供了所有需要進行生產的產品,以始終進行分析,但是有效的產品優先。 然后,您可以在實時預覽期間忽略incomplete_tag

第二個問題 (如何包括動作):

您在表達式后編寫所謂的動作 動作是用大括號括起來的Javascript代碼,並且可以在pegjs表達式之后(即,在生產過程中)使用它!

在實踐中,幾乎總是需要諸如{ return result.join("") }類的動作,因為pegjs會分成單個字符。 還可以返回復雜的嵌套數組。 因此,我通常在語法的開頭的pegjs初始值設定項中編寫幫助程序函數,以保持較小的動作。 如果您仔細選擇函數名稱,則該操作是自記錄的。

例如,請參見PEG for Python樣式縮進 免責聲明:這是我的回答。

關於第一個問題,我不得不說實時預覽將很困難。 您指出的有關解析器無法理解輸入為“進行中的工作”的問題是正確的。 Peg.js會告訴您錯誤發生在哪一點,因此也許您可以獲取該信息並返回幾句話以再次解析,或者如果缺少結束標記,請嘗試在最后添加它。

問題的第二部分比較簡單,但是之后語法就不會那么好了。 基本上,您要做的是在每個規則上都放置回調,例如

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

目前,您必須在語法中內聯編寫這些回調。 我現在正在做很多這樣的事情,因此我可能會對peg.js提出pullrequest來解決此問題。 但是我不確定何時有時間這樣做。

嘗試類似此替換規則的操作。 您走在正確的軌道上; 您只需要告訴它來組合結果即可。

文字=結果:non_tag + {返回result.join(''); }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM