rougeのlexer開発ワークフロー

github.com

digdag の構文を追加するにあたって、Ruby製syntax highlighterであるところのRougeのlexerの開発方法を調べました。

基本

Rouge lexerはDSLで定義します: https://github.com/jneen/rouge#using-the-lexer-dsl

lexerはステートマシンとして振る舞うので、ただのキーワードマッチより遥かに強力で文脈を考慮した字句解析を行えます。

tokenの種類は token.rb に定義されているので、実際の出力はこれを見ながらふさわしいtoken typeを当てていくことになります。

また、lexerは継承もできます。たとえばdigdagファイルの構文はYAMLとほぼ互換性があるので、YAML lexerを継承することにしました。

そのなかで、カスタマイズしたいstateに prependappend でルールを追加することでlexerの拡張ができます。

例: https://github.com/jneen/rouge/pull/674/files#diff-801af56a286b5cd63a0e58c8cdad9867R64

テスト実行

lexerについて試行錯誤するときは、bin/rougify highlight でコンソールでハイライトを見れます。

たとえば今回であれば、以下のコマンドで確認しつつ開発をすすめました。

bundle exec bin/rougify highlight -m application/x-digdag -L debug=0 lib/rouge/demos/digdag

結果:

f:id:gfx:20170603153140p:plain

デバッグ実行

-L debug=1 を渡すと、デバッグモードで実行できます。ステートの遷移やどのルールにマッチしてどういうtokenを生成したかという情報を見れます。