C言語-インタプリタminiCASL |
5. 命令を1行で書けるようにする
これまでは、命令語と計算に使用するデータを、それぞれ1行ずつに書いた。これではプログラムらしくないので、1行に書けるようにする。
命令文を1行に書いた場合、それぞれ、意味のある単位で語句を取り出さなければならない。これを字句解析という。
例えば、mc(miniCASL)言語のプログラムを次のように記述する。
add 123.4 211.2
この場合、空白で区切られた"add", "123.4", "211.2"の3つの語句に分解しなければならない。この処理をする関数get_tokenを利用してプログラムを作成すると簡単である。関数get_token(gettoken.c)は、標準関数ではなく、この課題研究用に作成したものである。使用するには、#include "gettoken.h"が必要である。
#include "gettoken.h"; char *get_token(void); グローバル変数char *gt_line;に文字列(MAX=256文字)を格納しておき、関数get_tokenを呼び出すとグローバル変数char *token;に取り出された単語が格納されて戻ってくる。返却値は、取り出した単語の先頭アドレス(tokenの先頭アドレス)である。 |
グローバル変数とは、プログラム中のどこでも利用可能な変数と考えればよい。
例えば、次の計算式がグローバル変数gt_lineに格納されているとする。
2.1 + 3 + 4.33 + 5e2
最初にget_token()を呼び出すと、変数tokenには、2.1が格納される。次に呼び出すと空白は無視されて+3が格納される。次に +4.33, +5e2 と順に格納され、最後は\0(ナル)が格納される。
このように、
[mc06.c] | |
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 34: 35: 40: 41: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "@ " #define STRMAX 80 /* 文字列配列の大きさ */ void main(int argc, char *argv[]) { double data1, data2, ans; FILE *fp; /* ファイル操作用 */ if(argc != 2){ /* パラメータのチェック */ printf("使い方:MC filename\n"); exit(1); } if((fp = fopen(argv[1], "r")) == NULL){ /* ファイルのオープン */ printf("ファイルがオープンできませんでした。\n"); exit(1); } while(fgets(gt_line, STRMAX, fp)){ /* データの読み込み */ A ; if(!strcmp(token, "add")){ /* 命令判定 */ A ; /* 1語取り出し */ data1 = atof(B ); /* 実数値に変換 */ A ; data2 = atof(B ); ans = data1 + data2; }else if(!strcmp(token, "sub")){ <<赤色の部分(24〜27行)と同じ>> ans = data1 - data2; }else if(!strcmp(token, "mul")){ <<赤色の部分(24〜27行)と同じ>> ans = data1 * data2; }else if(!strcmp(token, "div")){ <<赤色の部分(24〜27行)と同じ>> ans = data1 / data2; }else if(!strcmp(token, "end")){ break; }else{ printf("Error : コマンドエラー\n"); continue; } printf("%f\n", ans); /* 結果表示 */ } fclose(fp); /* ファイルのクローズ */ } |
D:\Data\src>cc mc06.c gettoken.obj lld @link.i D:\Data\src>mc06 reidai02.mc 23.450000 12.340000 123.400000 -2.345000 |
add 12.34 11.11 sub 23.45 11.11 mul 12.34 10 div 23.45 -10 end |
21行目while文の中で1行読み込みをしている。関数fgets()はファイルfpから読み込むデータがなくなったとき0を返却するのでwhile文の繰り返しを終了する。mc言語のプログラム中にend命令がなくても終了する。
1行のデータ(文)を単語に分解する関数get_token()を使うためヘッダファイルgettoken.hをインクルードしている。この中で1行のデータを記憶させるグローバル変数gt_lineが宣言されているので、1行読み込みの関数fgets()の中でgt_lineに読み込んでいる。したがって、配列buffは不要になる。
Copyright © 2001 Hiroshi Masuda |