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に prepend
や append
でルールを追加することで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
結果:
デバッグ実行
-L debug=1
を渡すと、デバッグモードで実行できます。ステートの遷移やどのルールにマッチしてどういうtokenを生成したかという情報を見れます。