個人的に Ruby parser についてまとめてみた
RubyKaigi Takeout 2021 の Ruby Committers vs the World で議題になった「A maintainable, flexible, and usable Ruby parser」部分だけ個人的に気になったのでまとめてみた*1。
A maintainable, flexible, and usable Ruby parser(保守性、柔軟性、使用性に優れた Ruby パーサー)
- Objective
- Problems
- The current parse.y is a hell
- LSP often requires more detailed syntax tree (concrete syntax tree?)
- Need the location of comments, punctuations, etc.
- The current AST node keeps only a range (the beginning and the end)
- LSP requires an error-tolerant parse
- IDE needs to handle incomplete source code
- Ideas
ちなみにこれらの項目は、動画で mame さんが言及している通り、整理された項目ではない。”何かもやもや不満があるもの”をスライドに書きあげてみただけで、スライドに書いてあることをやりたいわけではない(と mame さんは言っていた)。つまり、実際に実現できるようなことをスライドに書いているわけではない。
俺なりの訳。
- 目的
- 問題点
- 代替案
- (Python みたいに)PEG で書き換える?
- parser gem を使うか? Ripper を使うか?
”何かもやもや不満があるもの”をもう少し具体的に
- やりたいこと
- どうにかしたいこと
パーシングの速度について
- soutaro: Ruby 実行時のパーシングはは速くないといけないのか?Ruby のパーシングが現バージョン*3から 10 倍遅くなっても無視できるか?
- naruse: パーサーの部分と ISEQ のコンパイルの部分を混同して話をしていないか?
parser gem について
ブートストラップ問題
- nobu: 古いバージョンのシンタックスまでサポートする必要はないが、パーサーを動かすための Ruby はどうするのか?
- nobu: 5 倍遅くなるで収まるのか?
- mame: parser gem はもっと細かい情報をとるのでもっと遅くなると思う
- nobu: 10 倍遅くなるのは許容できない
- nobu: bundle?(聞き取れなかった…)が全部遅くなると思う
- nobu: 5 倍遅くなるで収まるのか?
- nobu: Ruby で書いたパーサーでやるならば、AOT*5にしないと困るのではないか?
- mrkn: 新しいパーサーは parse.y で解析したらいいのではないか?
- mrkn: parse.y は残しておいてブートストラップ用に使えばいいのではないか
- nobu: 新しいパーサーと prase.y を二重にメンテナンスすることにならないか?
- mrkn: parse.y はメンテナンスしなくていいと思う。パーサーは古い Ruby で書けばいい
- nobu: 新しいパーサーと prase.y を二重にメンテナンスすることにならないか?
- shyouhei: まずは「parse.y を捨てたい」という前提があるのではないか?
- nobu: 捨てるとまではいかなくても、整理しなくてはいけない
- mrkn: parse.y は残しておいてブートストラップ用に使えばいいのではないか
LSP について
- naruse: LSP は parser gem 同様古いバージョンでも動かなければならない
- naruse: 実は ruby 本体の実行用のパーサーではなく、parser gem のような複数の古いバージョンでも動くものが適切ととらえれば「parser gem と古いリビジョンで作ればいい」のかもしれない
- nobu: 現時点*6では LSP はそんなに厳密なパーサーではなくてもいいのではないか
- nobu: 逆に細かくエラーチェックが入ると困るし、細かいエラーチェックは不要なのではないか
- soutaro: そんなことはない
- naruse: ???(聞き取れなかった…)を通らないものに関しては何かエラーを出力して欲しいかも
- nobu: 逆に細かくエラーチェックが入ると困るし、細かいエラーチェックは不要なのではないか
車輪の再発明
- ko1: 「とにかく動かすためにパースすれば良かった」というものから、だんだん他の要件が増えてきたのでパーサーそのものを考え直す時期が来たのだと思う
- ko1: matz は趣味的に作り直したい気持ちはあったりする?
- matz: ない
- nobu: mruby でパーサーを作った人がいましたよね?
結局いまの Ruby パーサーの問題点って何?
- akr: parse.y が大変なのは何故なのか?
エラーハンドリング/エラーリカバリ
- ???: さっき話題に出ていたのはエラーハンドリングではないか?
- mame: 新しい要件が出てきた、という方が分かりやすい
- akr: エラーハンドリングであれば yacc にある
- mame: 必ずしも「今の bison を捨てろ」とは言っていない。Ripper を使っても良いと言っている
- nobu: 「エラーが起きても最後までパースして欲しい」というのがさっきの話題だった
- naruse: yui-knk さんが昔やっていた*12
- nobu: 「エラーが起きても最後までパースしてトークンを返す」というのを使っているのが今の irb ではないか?
- mame: lexer の方ができるという話ではないか?lexer はエラーハンドリングできるという話?
- soutaro: 「ここに構文エラーがあって、残りはこうなっている」というパーサーが欲しいんですよね*13?
- mame: yui-knk さんはエラーリカバリをやっていた?エラーハンドリングをやっていた?