【Ruby】パーサーから見た「a???」が構文エラーとならない理由
topic
study about parse.y ...a little.
ここの記事を読んでいます。
Rubyソースコード完全解説
パーサーの仕組みが詳しく載っている。
ちょっと難易度が高め!
ごめんカッコつけた。。。かなり高め
以前「どうしてこれが構文エラーにならないの」問題を考えたことがあったけど、
折角だから、パーサーからも探ってみよう。
なかださんのTweet。
@sora_h A. parse.y読了すれば自明
— なかだ の (@n0kada) 2013, 11月 14
無理だよー。。と思うんだけど、見てみよう!
そもそもparse.yがない
Ruby200フォルダ下にparse.yがない。
よく分からないけど、githubにコードがあるので、こちらで代用。
ruby/parse.y at trunk · ruby/ruby · GitHub
ここの、parser_yylexがみるべき関数みたい。
どこにparse.yがあるのか、なかださんに教えて頂いた。
@haisekai parse.yは実行時には不要なのでインストールされません。 https://t.co/cgJhBkMuKn
— なかだ の (@n0kada) 2013, 11月 30
えーどういうことー。
ヒントにしたがってyaccの項目を読めば、理解できました。
(記号列だけを見て解析できるようにする)自動化ツールをパーサジェネレータ(parser generator)と言う。
http://loveruby.net/ja/rhg/book/yacc.html
UNIXで一番使われているパーサジェネレータがyaccだ。rubyの パーサも御多分に漏れずこのyaccを使って書かれている。parse.yがその 入力だ。・・・yaccにかけるとCのソースコードができるので、 あとは普段通りそれをコンパイルすればよい。
つまり、parse.yはコンパイルされてparse.o になっているってこと。
調べてみるとこのファイルはちゃんとあった。
「Rubyのソースコード」には、parse.yが存在している。
「Windows版Rubyバイナリ」をDLしていたから、手元には存在しなかったんだ。
ダウンロード
C言語のコンパイルの流れが分かってないからこんな質問しちゃったんだなー。。。
お礼のtweetも済ませて。
分かりました!パーサジェネレータ(yacc)を使って書かれたものだからコンパイルされたものが配布されているのですね!コンパイル後のparse.oファイルの存在が確認できました。理解できました。ありがとうございました。。!>@n0kada
— sekai (@haisekai) 2013, 11月 30
肝心の中身は。。
switch (tok()[0]) { case '@': case '$': pushback(c); break; default: if ((c == '!' || c == '?') && !peek('=')) { tokadd(c); }
この箇所で、最初の"?"を識別子としてシフトする。
case '?': c = nextc(); if (!parser_isascii()) { } else { tokadd(c); #<= (ア) }
?の次の文字を取って、
エラーや特殊パターンに当てはまらなかったら(そのまま文字列に)加える。
だから、
a???
はa?メソッド(識別子)の、引数「?」です、ということになる。
位しか分からなかった。ちょっと貧しい。。
そもそも当たっているのか良く分からない。
また再び力がついたら見返してみよう。