hnwの日記

PHPのTokenizer関数の紹介

お久しぶりです。Plaggerの件の続きが書きにくくて更新止まってました。ごめんなさい。リハビリがてら、書きたいことを書いてみます。


自動型変換 - PHP重箱の隅」を読みました。ナイスな記事ですね。筆者の方はPHPのundocumentedな部分の多さが不満のようですが、僕も似た不満を持っていた頃があった気がします。今後も(少なくとも僕にとって)楽しい記事を書いてもらえそうで、期待してます!


記事の内容としてはご推察の通りだと思います。この記事に関連して、PHPトークン分解をどうやっているのか、Tokenizer関数を使ってPHPから調べる方法について紹介してみます。(もちろん、本気で調べたいならzend_language_scanner.lやzend_language_parser.yを読むべきです)


PHPがどうトークン分解をするのかは、token_get_all関数を使って調べられます。

$ php -r 'var_dump(token_get_all("<?php -2147483648;?>"));'
array(5) {
  [0]=>
  array(3) {
    [0]=>
    int(367)
    [1]=>
    string(6) "<?php "
    [2]=>
    int(1)
  }
  [1]=>
  string(1) "-"
  [2]=>
  array(3) {
    [0]=>
    int(306)
    [1]=>
    string(10) "2147483648"
    [2]=>
    int(1)
  }
  [3]=>
  string(1) ";"
  [4]=>
  array(3) {
    [0]=>
    int(369)
    [1]=>
    string(2) "?>"
    [2]=>
    int(1)
  }
}


値の返し方が少々特徴的ですが、どうトークン分解しているかは一目瞭然かと思います。1文字のトークン以外のトークンはトークンの種類が数値で帰ってきますが、これが何を意味するかはtoken_name関数で調べることができます。例えば「"2147483648"」はトークンとしては「int(306)」だそうですから、調べてみます。

$ php -r 'var_dump(token_name(306));'
string(9) "T_DNUMBER"


このトークンのシンボル名の意味は「パーサトークンの一覧」に列挙してあります。T_DNUMBERというのはdoubleのリテラルですね。これらから、"-2147483648"はトークン分解の時点で単項マイナス演算子とdoubleのリテラルの2つのトークンとして解釈されていることがわかります。


これ、PHPの中身を覗く取っ掛かりとしては面白い機能だと思います。連休も残り一日ですが、興味のある方は少し遊んでみてはいかがでしょうか。(こんなことに興味がある人ならいずれソースコードを読む事になると思いますが…)