2013年8月2日 星期五

Parsec 練習:寫個 ass 字幕剖析程式

有些事情很講求緣份,像是遇到不錯且值得去認識的人,或是看到了不錯的程式語言,或是注意到某家餐廳的文宣...。這裡也一樣。

某天在讀 Real World Haskell 的 parsec 那章,有點累想看影片的時候,發現某個 ass 字幕和影片不同步...(差了一秒鐘左右)。隨手找了個叫做 AegisSub 的軟體,正打算安裝起來時發現它需要 wxWidget 2.9 (的樣子),而 Fedora 19 附帶的只有 wx 2.8。正在思考要不要安裝 wx 2.9 的時候突然有種靈光一閃的感覺:「這不是練習使用 hasell parser combinator 的好時機嗎?」,就動工了 :p

在 haskell 界最知名的兩個 parser combinator 程式庫是 parsec 以及 attoparsec。 兩者的功能相似,API 也極度相似,所以...既生瑜何生亮?訪問一下這兩個程式庫,可以發現它們在 parse 界生態系所佔據的地位有微小但重要的差異。 Parsec 所建立的 parser 可以輸出詳盡的錯誤訊息,而 attoparsec 則是為了建立高效率的 parser 而生的(關於這個比較可以參考attoparsec 作者所作的效能評測)。另外, parsec 的 parser 在遇到錯誤的時候不會做 traceback (也就是返回開始 parse 的狀態),而 attoparsec 的 parser 保證會做 traceback。

關於這個 traceback 最經典的例子是:

string "string" <|> string "strong"
如果是 parsec 的話,在處理 strong 時會發生錯誤,因為前面的 string "string" 已經吃了 str,然後在遇到 o 的時候發生錯誤,所以把球踢給 string "strong" 處理。然而,此時輸入資料只剩下ongstr 已經被 string "string" 的胃酸消化掉了),所以失敗變成了必然。

attoparsec 的話,因為第一個 string "string" 在遇到 o ,發生錯誤的時候會把之前吃下去的 str 吐回去,也就是,在 string "string" 交棒給 string "strong" 的時候,輸入資料和原來一樣是strong

這裡為了練習,也為了調整那個 ass 字幕檔,做出了 subtitle-timeshift,一個有工具程式以及程式庫的 haskell 程式包。該程式包放置在 Bitbucket,僅供參考。

另外,我也趁著這個機會試用 asciidoc 來寫這個軟體的說明檔。和 docbook 最大的不同在於 asciidoc 的格式標記簡單,不需要一直去看參考文件。此外,使用 asciidoc 的話,因為少打不少字,手指表示負擔大幅減少了。不過,我才剛認識 asciidoc ,所以也不方便介紹太多...或許找個機會好好介紹它。

沒有留言:

張貼留言