川合のプログラミング言語自作のためのテキスト#0003

  • (by K, 2019.02.25)

(7) TL-3

  • TL-2に少し命令を追加して、while命令を使えるようにしようと思います。
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    typedef unsigned char *String;	// こう書くと String は unsigned char * の代用になる. 
    
    void loadText(int argc, const char **argv, String t, int siz) → TL-1と同じなので省略
    int isNumber(unsigned char c) → TL-2と同じなので省略
    int isAlphabet(unsigned char c) → TL-2と同じなので省略
    int isSymbol(unsigned char c) → TL-2と同じなので省略
    int isSymbol1(unsigned char c) → TL-2と同じなので省略
    int lexer(String s, String b, String t[]) → TL-2と同じなので省略
    
    int var[256];	// 変数.
    String varName[256];	// 変数名.
    unsigned char txt[10000]; // ソースコード.
    int pc = 0;	// プログラムカウンタ.
    
    int varNumber(String t) → TL-2と同じなので省略
    int getNumber(String t) → TL-2と同じなので省略
    
    int main(int argc, const char **argv)
    {
        int i, pc0, wpc;
        unsigned char buf[10000];
        String t[1000];	// トークン.
        loadText(argc, argv, txt, 10000);
        i = lexer(txt, buf, t);
        t[i + 0] = t[i + 1] = t[i + 2] = t[i + 3] = "";	// エラー表示用のために末尾にいくつか長さ0の文字列を登録しておく.
        for (;;) {
            pc0 = pc;
            if (strcmp(t[pc], "") == 0)		// ファイル終端.
                exit(0);
            if (strcmp(t[pc + 1], "=") == 0) { → TL-2と同じなので省略
            } else if (strcmp(t[pc], "while") == 0 && strcmp(t[pc + 1], "(") == 0 && strcmp(t[pc + 3], "<") == 0 && strcmp(t[pc + 5], ")") == 0 && strcmp(t[pc + 6], "{") == 0) {
                wpc = pc;
                if (getNumber(t[pc + 2]) < getNumber(t[pc + 4])) {
                    pc += 7;
                } else {	// 条件不成立なので } の次まで読み飛ばす.
                    while (strcmp(t[pc], "}") != 0 && strcmp(t[pc], "") != 0)
                        pc++;
                    if (strcmp(t[pc], "}") == 0)
                        pc++;
                }
                continue;
            } else if (strcmp(t[pc], "}") == 0) {
                pc = wpc;
                continue;
            } else if (strcmp(t[pc], "time") == 0 && strcmp(t[pc + 1], ";") == 0) { // time.
                printf("time=%.3f[sec]\n", clock() / (double) CLOCKS_PER_SEC);
            } else if (strcmp(t[pc], "print") == 0 && strcmp(t[pc + 2], ";") == 0) { // print.
                printf("%d\n", getNumber(t[pc + 1]));
            } else
                goto err;
            while (strcmp(t[pc], ";") != 0)
                pc++;
            pc++;
        }
    err:
        printf("syntax error : %s %s %s %s\n", t[pc0], t[pc0 + 1], t[pc0 + 2], t[pc0 + 3]);
        exit(1);
    }
  • 追加したのは、while命令のほかにtime命令もあります。
  • このTL-3は以下のプログラムを実行することができます。1億回ループです。
    i = 0;
    while (i < 100000000) {
        i = i + 1;
    }
    print i;
    time;

(8) TL-3の簡単な説明

  • main()の中に変数wpcを追加しています。これはwhile文があった場所を覚えておくためのものです。そして } が来るとwpcの場所へジャンプします。これで繰り返しを実現しています。
  • while文では条件式を評価しますが、もし評価結果が成立していない場合は、 } までをすべて読み飛ばします。
  • このプログラムはwpcが一つしかないので、入れ子になったwhile文には全く対応できていません。そういう問題はありますが、とにかく一重ループなら問題なくできますし、実行に要した時間を計測することもできます。
  • いきなりたくさんの問題を解決するというのはいい方法だとは思いません。少しずつ前進していくのが良いと私は思います。
  • また(入れ子を許す方法は分からないにしても)if文をどうすれば追加できるのかは、whileを参考にすれば自然にわかるでしょう。

次回に続く

こめんと欄


コメントお名前NameLink

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-03-22 (金) 22:37:59 (241d)