てきとうなさいと べぇたばん

PHPのソースを覗いて、字句解析と構文解析がある事を知る

構文解析

メモ。Zend/zend_language_scanner.cのcompile_string関数にて。bisonの使い方を調べるか。

とりあえず、電卓をつくった

構文解析で、電卓をつくった。

ソース

https://github.com/youkidearitai/calc-modoki

構文解析

PHPでは、字句解析を行った後に構文解析を行うという手順になっている。

bison

ためしに、bisonを使って電卓を作ってみる。構文が結構簡単に処理できるのはいいと思った。しかしこれでは、構文解析だけで行けるんじゃね?という謎が出てきた。

字句解析

例えば式に対してインデントやスペースを混ぜてみたいとかなると、yylex関数の中にその処理を入れないといけなくなる。構文が増えれば増えるほど、yylex関数にはどんどんルールがたまっていくので、結構たいへんになる気がする。

その問題を解消するために、字句解析器(re2c)を使ってみることにする。今までyylexにはC言語でガリガリ書いていたのだけど、これをre2cに任せる。すると、拡張子が.reのファイルからre2cプログラムでC言語のソースに変換されるのである。

変換されたソースは、goto文だらけ。時々PHPのソースを漁るとでてくるソースみたいだと思った。

字句解析でスペースをとり、数値や特定の記号をシンボルに変換したものを構文解析に回す。字句解析のおかげで、記法を追加するのも調整するのもだいぶ楽になったと思う。

結果

$ ./calc
38 + 24 * (222 - 22)
4838
999 + 1 / 100
999
999 + (1 / 100)
999
(999 + 1) / 100
10

残っている問題

  • すべて整数として扱っているので、3 / 4といった答えが小数点以下の計算に対応していない。小数点以下は切り捨てられるので、この例では0になる。
  • 構文解析時の具体的な計算と表示を分離するべきだと思う。
    • 3 / 0といった、ゼロ除算に対してのエラー処理がない。構文解析器は構文解析に対して責任を持つべきであって、計算結果に対しての責任を持つべきではないと思う。
    • printfしている部分を分離すべきかなと思っている。

さんこう