RustでオレオレMarkdownパーサーつくった

github.com

MarkdownのString与えるとそれっぽいHTMLのStringを吐くライブラリです。

せつめい

CommonMarkの仕様を見ながらよく使いそうな機能をかいつまんで実装した。
オレオレとあるのはこの仕様を網羅してないからだ。なんか細かい挙動の仕様は気にせずつくったので、多分いじわるな書き方されるとうまくパースできない気がする。
それでも# 見出し- リスト[リンク]: URL "title"![画像](URL)やコードブロックなどのよく使いそうな機能はそろったのでノリで公開してみた。

そんな雑な出来だけど、アピールポイントを挙げるとするなら、Rustが公式提供しているRegexを除けば外部ライブラリを使用していないので軽量なことかなと思う。

振り返りと反省

雰囲気としては、

markdownテキスト

字句解析

なんか中間表現的なやつ

構文解析

HTML

って感じです。パーサー書くのこれが初めてなので分からないけど割とオーソドックスな構成なんじゃないだろうか。
出力フォーマットが現状HTMLだけなのでわざわざ中間表現にするうま味が薄いように思えたけど、字句解析のコードと構文解析のコードをすっぱり分けることができたのでやった価値はある気がする。
字句解析のコードは、字ではなく行単位で舐めていくなんとも雑な実装になっており、素直に1charづつ進め先読みをしながらtokenizeしたほうが良かった気もする。なぜならその方がカッコいいから。
字句を消費する関数と字句解析を実行する関数のガワが完成した後は、その中に字句の種類を判別するコードを継ぎ足していく段階となる。やってることは正規表現ゲーなので、あまり見栄えのよいコードではない。

きっかけとか一区切りついての感想

最近Rustの勉強しはじめ、はやく慣れたいのでなんか書きたいというのがモチベーションにあり、去年buildersconというカンファレンスではてなのエンジニアさんが話していたGoで書かれた軽量マークアップ言語パーサーのセッションを思い出して、おもしろそうだったのでチャレンジした。実際パーサを書くのはおもしろかった。

先述したセッションのなかでもお話されているが、パーサーは構文機能をちょこちょこ継ぎ足していくことでつくっていくのだけど、
個々の機能は少量の記述で済むので継続しやすく、なにより成果が目に見えやすいのでやる気の維持で悩むことはなかった。
今みるとスピーカーの方は入門としてJSONのパーサーを薦めていたがすっかり忘れてた。次はJSONパーサー書いてみたいね。

勉強したこと

パーサー書くのこれが初めてなので、世界観理解するためにOreillyの言語実装パターン―コンパイラ技術によるテキスト処理から言語実装までって本をよんで勉強した。
はじめに、括弧と文字列だけの単純な構造をしたテキストのパーサーをつくっていく章があり、それが雰囲気をつかむことにとても役立った。
サンプルコードはJavaでかかれていて、Javaはまともに書いたことがなかったけど、ちょっと難しい機能(アノテーションとか)は使ってないやさしいコードだったので割と読めた。

僕はちなみに、ホイホイと技術書買えるお金もないので、学校の図書館でそれ借りたのだけど返却をせかされて、結局その序盤のページしかまともに読んでない。
それでも雰囲気はつかめた気はしたので、この本はすごいためになった。(小並感)

言語実装パターン ―コンパイラ技術によるテキスト処理から言語実装まで

言語実装パターン ―コンパイラ技術によるテキスト処理から言語実装まで