!!! コンソールの複数行入力対応 ふと気がついた。 プロンプト上で、以下のように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の複数行の入力に対応した。 [[戻る|Forthを作ってみる]] [[前へ|Forthを作ってみる / Forthを32ビット化する]] [[次へ|Forthを作ってみる / スレッディングの変更]] {{adsence}}