Ripper でパースエラーを検知しようとしてハマった
Ruby でパースエラーになっている箇所を調べたくて Ripper を使ったらハマったので覚書。
Ripper を使う
Ripper とは Ruby に標準で付属している Ruby のコードをパースするためのライブラリです。
Ripper では Ripper
というクラスがあり、これを継承してパース時の処理を実装していく感じになります。
例えば、以下のような感じで『任意の Ruby のテキスト』をパースしてエラーを検知することが出来ます
require "ripper" class FizzBuzz < Ripper def compile_error(msg) pp __method__ pp msg end end FizzBuzz.parse("@%") # :compile_error # output: # :compile_error # "`@%' is not allowed as an instance variable name"
こんな感じでコンパイルエラーを検知する事が出来ます。
パースエラーを検知する
さて、先ほどと同じように次のような Ruby のコードをパースしてみました。
require "ripper" class FizzBuzz < Ripper def compile_error(msg) pp __method__ pp msg end end FizzBuzz.parse(<<~EOS) def hoge 1 + end def foo EOS
しかし、上記の場合は #compile_error
は呼ばれません。
上記のような Ruby のコードでエラー箇所を検知する場合は #compile_error
ではなくて #on_parse_error
というメソッドが呼ばれます。
require "ripper" class FizzBuzz < Ripper def compile_error(msg) pp __method__ pp msg end def on_parse_error(msg) pp __method__ pp msg end end FizzBuzz.parse(<<~EOS) def hoge 1 + end def foo EOS # output: # :on_parse_error # "syntax error, unexpected end" # :on_parse_error # "syntax error, unexpected end-of-input"
これでいい感じに Ruby のコードのエラーを検知する事が出来ます。