トップ 一覧 Farm 検索 ヘルプ RSS ログイン

MultiLineInputの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!! コンソールの複数行入力対応

ふと気がついた。
プロンプト上で、以下のようにif以降を1行に書かないで実行すると、

 $ ./moiforth.exe
 >0 if
 

反応がなくなる。
理由が分かった。構文解析関数parse()で、ifワードが現れたときの処理はこうである:

        } else if (strcmp(token, "if") == 0) {
            prog[idx] = CODE_IF;
            push_branch_stack(idx + 1);
            idx += 2;

それと、内部インタプリタ関数proc_prog()のif処理部は以下のようになっている:

        case CODE_IF:
            if (pop()) {
                prog_cnt += 2;
 
            } else {
                prog_cnt = prog[prog_cnt + 1];
 
            }
            break;

条件が真のときは、prog_cntは次の番地に進み、そのコードが0、CODE_ENDなので、プログラムは終了し、入力待ちプロンプトを表示する。
しかし、条件が偽のときは、ジャンプ先がCODE_IFの次のコードとなっているが、プロンプト入力はifで終わっているため、次のコードはCODE_END、つまり0である。
ということは、0番地に飛んでしまい、いつまで経っても終了しない。

どうすればよいか。
対策として、組となるワード、例えばifに対するelseやthen、が現れるまで内部インタプリタの呼び出しを行わないようにする。

 char proc_disable_cnt;          /**< 1以上のとき、プロンプトからの実行を禁止する */

この変数を用意し、parse()内でカウントする。ifの場合は+1し、thenの場合は-1する。

        } else if (strcmp(token, "if") == 0) {
            prog[idx] = CODE_IF;
            push_branch_stack(idx + 1);
            idx += 2;
            proc_disable_cnt++;
 
        } else if (strcmp(token, "else") == 0) {
            prog[idx] = CODE_ELSE;
            prog[pop_branch_stack()] = idx + 2;
            push_branch_stack(idx + 1);
            idx += 2;
 
        } else if (strcmp(token, "then") == 0) {
            prog[idx] = CODE_THEN;
            prog[pop_branch_stack()] = idx + 1;
            idx++;
            proc_disable_cnt--;

また、parse()内の変数idxは、いったん関数を抜けると位置を保持できないので、グローバル変数にして、構文解析を続けられるようにする。

    if (!proc_disable_cnt) {
        parse_idx = 0;
    }

対話環境では、proc_disable_cntが0以下ならば、プログラムを実行する。

        while (!quit_enabled) {
            printf(">");
            scanf("%100[^\n]%*[^\n]", cmd_buf);
            getchar();
 
            parse(cmd_buf);
            if (!proc_disable_cnt) {
                proc_prog();
            }
        }

実行してみた。

 $ ./moiforth.exe
 >2 if
 >       2 3 + .
 >else
 >       3 3 + .
 >then
 5>0 if
 >       1 1 + .
 >else
 >       3 3 + .
 >then
 6>

成功。これでif〜thenの複数行の入力に対応した。

[[戻る|ForthImplementation]] [[前へ|Make32bitForth]] [[次へ|Forthを作ってみる / スレッディングの変更]]

{{adsence}}
[[Forthを作ってみる / コンソールの複数行入力対応]]に移動しました。