本家のHamlは以下の入力を与えるとSyntaxErrorになる。}これはHamlが単に{と}の数だけ合わせてパースしているからである。*1通常この問題を解決するには字句解析器を使い、現在パースしているのが何のトークンなのか判別する必要がある。Hamlitではこの問題を解決するため、標準ライブラリとして提供されているRipperを使っている。そのため、Hamlitでは上記の入力を以下のように正しく解釈することができる。上記のhamlの%divを取り除いた部分であればRubyのHashとして解釈できそうに見える。実際には以下のような入力もHamlのattributeとして有効である。helloもはやHashでもなんでもない。これが動くかというと、以下のようにコンパイルされるようになっているからだ。false);つまり{}の内側は_hamlout.attributesに渡す可変長の引数の一部なのである。*3末尾にHashっぽいのが書いてあるとそれは引数の一つとして解釈され、ここではHashが2つ渡されていることになる。"hello"]]とりあえず最後までスキャンしてくれる。ここで判別に使いたい}が:on_embexpr_endになっていることに着目する。interpolationの開始とか)と対になるトークンである。したがって、非常にRipperの実装依存っぽい感じだが、:on_embexpr_endの数が:on_embexpr_begの数より1つ少なくなる場所でストップすればいい感じに動く。現在のHamlitのmasterはこのように実装されている。:on_embexpr_endの手前まではvalidな式を渡せているのでこれ以上マシな使い方は思いつかなかったが、Rubyのバージョンが上がっても動きそうな使い方をしたい...文字列がRubyのHashとしてvalidか判別する方法Hamlitでは、attributeの{}内の部分がRubyの式としてvalidだった場合に限り静的なコンパイルを試みて最適化をしている。見ると、Ripper.sexpは引数がRubyの式としてinvalidなときはnilを返すようなことが書かれていて、Hamlitでも一度それに依存した実装を行った。バージョンによって異なる返り値しかしRipper.sexp(str)だけで判別するコードをpushしてみるとRuby2.1と2.0のCIが落ちた。nil結局、以下のように対応した。月別アーカイブ検索はてなブログをはじめよう!k0kubunさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。