オリジナルのインタープリターを作成するコツ 計算式評価編

現在ワープロデーターベースなるものを作成しております。
今回は技術的な事のみを記載しております。

インタープリターを自作するのに一番早いのは、オープンソースの言語(C,PHP,PERLなど)のコンパイラソースコードを再利用したり、読んで学ぶのが良さそうでした。
しかし、何かかったるそうな感じもします。
そんな中、PHPでインタープリターの計算式を実行(計算式の評価)させる方法を見つけました。
私が作っているインタープリター(ワープロデーターベース)の計算式は、レコード変数を使用できるようにするので変数の表記がちょっと特徴的です。
この変数には、普通の変数、漢字カタカナ混じり表記の変数名、年・月などの日付変数、レコード変数(得意先:2 直前で取得した得意先というDBレコード1行の、2番目の項目を示す)

【式や変数の表記方法】
  [$WK1:2]=[$トクイサキNO]+5
【意味】
  一時ファイルとしてWK1というDBを生成し、そこから(検索などをして)特定の
  レコードを示させる。
  その状態で、トクイサキNOという変数をWK1の2番目の項目に5を足してから代入するという意味

【ポイント】
変数は [$WK1:2] のように [ ] で括られている。
レコード変数には :(コロン)があり、レコード名と項目名との区切文字となっている。
必ず = 文字がある。
[ ]で括られた変数は、PHPで連想配列で扱える構造だと気付く事ができた!

【解決方法】
変数は以下のようにPHPで扱う。
  [$トクイサキNO]を、$hensu['トクイサキNO']
[$WK1:2] を、$hensu['WK1'][1] ※PHPの[添え字]は0から始まるので、1は2番目を示すから。
PHPのeval関数を使用すると、PHPの変数内の文字列をPHPの式として評価(実行)させることができる!!!
この機能を使えば、PHP用の文法に文字列操作をちょちょっと行うのみで、インタープリターの最難関のひとつ、計算式の評価を行うことができるのです。

上記を踏まえて、変数名を以下のようにPHPの連想配列の変数名に置換していきます。
  [$トクイサキNO] から トクイサキNO 文字列を取り出し、$hensu['トクイサキNO'] と置換
  [$WK1:2]  から :をセパレータとしてWK1 と 2 文字列を取り出し、
    $hensu['WK1'][1] と置換(添え字の2から1を差し引く)
具体的には
  [$WK1:2]=[$トクイサキNO]+5 は
  $hensu['WK1'][1]=$hensu['トクイサキNO']+5
に置換され、PHPの文法に則った命令文になります。
連想配列最強(笑)


プログラムはコピペしただけなので、あまり参考にならないかもしれません。
概要としては上記の考え方で大丈夫です。
【プログラム例】
//左側の変数について $hensu['AA'] と変換する
$tmp_hensu_mei = str_replace('[$', '', $siki[0]);
$tmp_hensu_mei = str_replace(']', '', $tmp_hensu_mei);
if( preg_match('/:/', $tmp_hensu_mei) == 0 )
{//変数のとき
$left_hensu_mei = '$hensu[\''.$tmp_hensu_mei.'\']';
}else
{//レコード変数のとき
$tmp_hensu_mei_record = split(':', $tmp_hensu_mei);
$tmp_hensu_mei_record_left = $tmp_hensu_mei_record[0];
$tmp_hensu_mei_record_right = $tmp_hensu_mei_record[1]-1;//CSV配列は 0 オリジンなので
$left_hensu_mei = '$hensu[\''.$tmp_hensu_mei_record_left.'\'][\''.$tmp_hensu_mei_record_right.'\']';
}

//右側の変数について 評価された式にする 1+20
$right_hensu = self::NoaHensu2Tenkai( $siki[1] );//変数名を変数の値に置換する (S>[$トクイサキ] の変数を値に置換する)

//evalで実行可能な式を組み立てる
$eval_siki = $left_hensu_mei.'='.$right_hensu.';';
//式をevalで評価
eval($eval_siki);