すべては1杯のビールから、 偶然の出会いが切り拓いたRuby パーサー開発の道のトップ画像
OSS応援最後まで読んで「応援」しよう

すべては1杯のビールから、 偶然の出会いが切り拓いたRuby パーサー開発の道

投稿日時:
高田 雄大のアイコン

高田 雄大

Xアカウントリンク

本記事では、「OSS応援企画」として記事末に「応援ボタン」を設置しています。1回の応援につき、Findyが100円をOSS団体などへ寄付し、エンジニアの成長とOSSの発展を応援する取り組みです。開発者の想いや取り組みに共感した気持ちが、OSSの支援にもつながっていく、そんな前向きな循環をFindyは目指しています。「応援ボタン」は、1日1回まで押すことができます。記事を読んで「いいな」と感じたら、ぜひボタンを押してあなたの応援の気持ちを届けてください。


こんにちは。高田 雄大(@ydah)と申します。普段はRuby on Railsを使っている会社で、Webアプリケーションのリアーキテクトをしています。余暇の時間を使って、OSSの開発もしています。2024年12月からは、Rubyのコミット権をいただいて、Rubyコミッタとして主にパーサー(構文解析器)周辺の開発を進めています。また、Ruby製のLRパーサージェネレーターであるLramaのコミッターとして、パーサージェネレーターの開発もしています。その他にも、ライブラリやツールを作成・公開したり、普段使用しているライブラリやツールに問題があればパッチを送ったりしています。加えて、関西Ruby会議08大阪Ruby会議04のチーフオーガナイザーとして地域Ruby会議と呼ばれるカンファレンスも主催しています。

今回の寄稿記事では、私がRubyのパーサー開発に携わるようになったキッカケや、OSSを開発している中で出会った人たちとの話を中心にお話しします。

パーサーとの出会い

「昔から構文解析器(パーサー)やその関連技術に興味があったのですか?」と聞かれますが、実はそうではありません。私がパーサーに興味を持ち始めたのは、2023年の春頃からで、それまでは特別な関心を持っていたわけではありませんでした。きっかけはRubyKaigi 2023でした。RubyKaigiとは、2006年からほぼ毎年日本で開催されている、オブジェクト指向スクリプト言語Rubyに関する国際カンファレンスです。そこでRubyコミッターであり、Lramaの作者である金子雄一郎(@yui-knk)さんが「The future vision of Ruby Parser」というセッションで、Rubyのパーサーの未来について話されていました。

詳細は割愛しますが、Rubyのパーサーが抱えている問題をどのように解決していくかという内容でした。その中で、それらの問題点を解決するために、Lramaという新しいLRパーサージェネレーターに置き換えてRubyのパーサーを改善していくという話がありました。正直なところ、内容はまったくわからなかったのですが、「現在の問題点はどこにあって、こうしていけば解決できる」という話の構造になっていて、わからないなりにもワクワクしながら聞いていたことを覚えています。

とはいえ、まだ技術で問題を倒していくかっこいいトークだったなという印象で、まさか後に自分がLramaの開発に関わることになるとは思ってもいませんでした。そして、RubyKaigi 2023が終わった翌日、Lramaの開発に関わることになるキッカケが訪れることになります。

RubyKaigi 2023は長野県の松本での開催だったので、翌日はゆっくりと散策してから帰ろうと思い、松本の街を歩いていました。松本といえば、ビールが好きな私としては松本ブルワリーに行ってビールを飲んでから帰ろう、と思っていたところ、タップルームでRubyKaigiのチーフオーガナイザーである松田明(@amatsuda)さんがたまたまビールを飲まれていたので、お声がけして一緒に飲むことになりました。

最初は「RubyKaigi 2023とても良かったです」と、参加の感想について話していたのですが、せっかくなので聞いておきたいという気持ちがあり、私がRubyKaigiに提出して落選したプロポーザルについてのフィードバックをもらえないかとお願いしました。 「どうすれば、30分のセッションで話せますかね」と率直に聞いてみたところ、「OSSにパッチを送っているという点においてはいいと思うのですが、まだ“誰でもやれること”しかやれていないのではないでしょうか」というフィードバックをいただきました。確かにそれはそうで、RubyKaigiでは“誰でもできること”ではなく“その人にしかできないトーク”が求められていますし、私がそういったものに取り組めていたかというと、そうではなかったと思います。

また、「今回のRubyKaigiのセッションの中で、ydahさんと親和性がありそうなのは、普段RuboCopで抽象構文木を扱っている点から考えても、Lramaを見てみるといいんじゃないでしょうか。Lramaはとても面白そうですよ」というアドバイスをもらいました。補足すると、当時の私はRubyのLinter/FormatterツールであるRuboCopに主にパッチを送りつつ、RuboCop RSpecチームのメンバーとしてRuboCopのテストコード向けの静的解析を行う拡張機能群のコミッターとして活動していました。そのお話を聞いて、確かにRuboCopでは抽象構文木を扱っていますし、金子雄一郎さんのトークを聞いた時のワクワクした気持ちを思い出しました。「これは楽しいかもしれないな」と思い、そこからパッチを送り始めたのがLrama、そしてパーサーとの出会いでした。

Lramaにパッチを送り始めた当初は、パーサーの知識はほとんどなかったのですが、Lramaのコードを読んだり、本を読んだりして知識を深めつつ、手を入れられるところから手を入れていきました。初めは、Cosmetic changesが中心でしたが、あるとき、Parameterizing RulesというMenhir(OCaml製のLRパーサージェネレーター)の機能がLramaにもあるといい、という話を金子さんから聞き、Lramaにその機能を実装するパッチを送ることにしました。

このパッチを送ったのを皮切りに、Lramaが提供するパーサーの定義ファイルの新文法や機能を追加するパッチを送るようになりました。なので、このパッチは私のOSSプログラマとして思い入れのあるパッチの1つです。

パーサー/パーサージェネレーター開発の技術的な魅力と挑戦

それでは、なぜパーサーやパーサージェネレーターの開発に魅力を感じているのか、またどのような挑戦があるのかについてお話しします。 パーサーやパーサージェネレーターの歴史は非常に古く、1959年にTony BrookerとDerrick Morrisによって設計が開始されたBrooker Morris Compiler Compiler(BMCC)が最古のパーサージェネレーターとされています。1970年代初頭にはStephen C. JohnsonがAT&TでUNIX用にYaccを開発し、1985年にはRobert CorbettによってGNU Bisonというパーサージェネレーターが初回リリースされました。GNU Bisonは今でも広く使われており、PHPやPerl、PostgreSQLなどの多くのプロジェクトで使用されています。

2000年代以降、パーサージェネレーターは下火になり、手書きのパーサーが主流になっていきました。GCCは当初Bisonを使っていましたが手書きの再帰下降パーサーに置き換えられ、Goも同様に、2010年に手書きのスキャナとパーサーに置き換えられました。 では、なぜ今、我々はパーサージェネレーターを開発しているのでしょうか。

それは、特に柔軟でシンプルながらも強力な文法を持つRubyにおいては、パーサージェネレーターの方が適していると考えているからです。例えば、ある新たな文法をRubyに追加したい場合に、その文法が既存の文法を壊さないかを確認するためには、手書きのパーサーだと多くの場合、既存の文法と組み合わせた多数のテストケースを用意する必要があります。しかし、パーサージェネレーターを使うと、文法の定義ファイルに新たな文法を追加する際、既存の文法とのコンフリクトを検知してフィードバックを得ることができます。これにより、互換性を壊すことなく新しい文法を追加できるという大きな利点が生まれます。このフィードバックが得られることで、Rubyの開発者は多くのテストケースを用意して既存の文法とのコンフリクトを検証することなく、追加したいと考えている文法がどう表現できるかを考えることに集中できるようになります。

また、そんな1980年代からあるGNU Bisonって拡張の余地があるのかと疑問に思うかもしれませんが、まだまだ拡張の余地はあります。GNU Bisonは比較的プリミティブな文法のみをサポートしているので、もっと柔軟な表現を可能にするための拡張は可能です。 他のパーサージェネレーターの機能や文法を実装すれば、より強力なパーサージェネレーターをつくることができるのではないかと考えています。

文法や機能だけではなく、パーサーのアルゴリズムも改善の余地があります。Lramaのコミッターの小林純一(@junk0612)さんが取り組んでいるのがまさにこの部分で、Inadequacy Elimination LR(IELR)というBisonに実装されているLRパーサーのアルゴリズムをLramaに実装しています。 そして、さらにPseudo-Scannerless Minimal LR(PSLR)という新しいLRパーサーのアルゴリズムをLramaに実装することを目指しています。

このように、パーサー/パーサージェネレーターの開発にはまだまだ挑戦があり、解きがいのある問題がたくさんあります。

人とつくる体験の話

さて、ここまでパーサーやパーサージェネレーターの技術的な魅力と挑戦についてお話ししてきましたが、私がOSS開発で楽しさを感じるのは、開発の楽しさだけではありません。 人と一緒に作る体験や、同じくOSSを開発している人との出会いが、OSS開発の大きな魅力の1つだと感じています。

私がOSS開発を始めたのは、3年半ほど前のことです。 きっかけは、先述のRuboCopというRubyのLinter/Formatterツールの拡張機能で、特定のケースでエラーが発生してしまう問題を修正するパッチを送ったことでした。 業務で使用していたところ、あるケースでエラーが発生してしまうのをたまたま見つけた、というのが経緯でした。

はじめてだったのでドキドキしていたのですが、パッチを送った翌日には、RuboCopのコミッターである伊藤浩一(@koic)さんにレビューをしていただき、すぐにマージしていただいて、とても嬉しかったことを覚えています。 RubyKaigi 2024まではほとんどお話しする機会はなかったのですが、私のOSS開発の基礎は、伊藤さんが作成されたパッチや伊藤さんとのGitHub上でのやり取りを通じて学んだことが多いです。

また、コミッターとしていくつかのソフトウェアのメンテナンスをするようになった際、Issueの対応やパッチのレビューでなかなか自分のやりたいことに時間を割けないなと悩んでいた時に、Ruby on Railsのコミッターである本多康夫(@yahonda)さんに「我々は仕事ではなく趣味でOSSを開発しているのだから、無理にすべてをやる必要はない」とアドバイスをいただきました。 確かにその通りだと思い、無理にすべてをやろうとしてしまったがゆえに、楽しさが減ってしまっていたのだと気付かされました。自分のペースでOSS開発を楽しむことができるからこそ、今でもOSS開発は私の1番の趣味であり続けているのだなと感じています。

Lramaを共に開発している金子雄一郎さん、小林純一さんからも多くの刺激を受けています。 RubyKaigi 2024RubyKaigi 2025では、それぞれがRubyのパーサーやLramaの開発についてのセッションを行いましたし、Rubyに関するカンファレンスで集まれば、ずっとパーサーの話をしていることもあります。 共に同じ目標に向かって開発を進めている仲間がいることで、技術的な挑戦をより楽しめています。

これからの展望とメッセージ

これからの展望としては、Lramaをさらに発展させていきたいと考えています。実際にLramaに実装した新機能をRubyのパーサーで活用した際、改善すべき点がいくつか見つかりました。また、Rubyのパーサーの定義ファイルを整理して、メンテナンス性を向上させていきたいと考えています。

現在はRuby向けにLramaを開発していますが、将来的には他の言語向けのパーサージェネレーターとしても活用できるようにしていきたいと考えています。そのために、Ruby以外のコミュニティでもこの取り組みを紹介したり、パーサーやパーサージェネレーターに関心のある方々からのフィードバックを得て、Lramaをより良いものにしていきたいと考えています。

もしこの記事を読まれている方で、現在OSS開発に関心があり、始めたいと思っている方がいらっしゃれば、ぜひ一歩踏み出してみてください。自分のペースで取り組めますし、無料ですし、無限に課題はありますし、何よりも楽しいです。そして、楽しいだけではなく、自分が書いたコードが巡り巡って誰かの役に立つこともあります。さらに、一緒にOSS開発をした方と、どこかのタイミングで同じカンファレンスに参加していて、気がついたら一緒にお酒を酌み交わしているかもしれません。そこにはきっと、同じ音楽や映画やゲームを好きである必要はなくて、OSSという共通言語でつながっている仲間との出会いが待っていると思います。

何かのOSSで一緒に開発することがあって、どこかでお会いしたらぜひ乾杯しましょう。そんな日を楽しみにしています。

OSS応援企画

Findyはエンジニアの成長とOSSの発展を応援します

Loading...

現在22の応援が届いています🤝

Loading...

寄付期間:~ 9/4 上限金額:200,000

プロフィール