はじめに
本連載では、日本語プログラミング言語の中で高いシェアを占める「なでしこ」を使用して、BASICライクな自作言語のコンパイラを作成します。
前回、「MASMとなでしこによるオリジナルコンパイラの制作 3」では、自作プログラミング言語「VEFBL」のコンパイラを作成しました。今回はメッセージボックス関数の拡張と変数の実装をします。今まで作成してきたソースコードは過去の記事を参照してください。
過去の記事
メッセージボックスの実装 1
複数の引数の実装
メッセージボックスは既に実装していますが、タイトルはまだ実装していません。また、タイトルの指定は普通のBASIC言語と同じように、特別設定しなくてもデフォルトの値が使われるようにしたいところです。
しかし、そのためにはトークン分割で複数の引数を取れるようにする必要があります。ここでは引数をバッファを配列形式にすることで複数取得できるようにします。1つ目の引数は「バッファ¥0」、2つ目の引数は「バッファ¥1」、3つ目の引数は「バッファ¥2」……というようになります。
もし、コマンドライン¥1が空ならば、 「ファイル名を指定してください」と表示。 終わる。 コマンドライン¥1を開く。 それを表示。 バッファは空。 //変数「空」の中身には何も入っていません 文字列中は、いいえ。 //現在の位置が文字列の中であるか 最新命令は、空。 //さっき指定されたばかりの命令 アセンブリは空。 //出力するアセンブリ アセンブリデータは空。 //出力するアセンブリデータ 文字列数は0。 //文字列の数 コマンドライン¥1を開く。 それを文字列分解して、反復 //このようにすれば文字列に変数を埋め込めます もし、バッファが「print」ならば、 最新命令はバッファ。 バッファは空。 //まだ他の場所にprintがあっても //「print(なんとか)print」などとなってしまい //検出できなくなる 違えば、もし、バッファが「msgbox」ならば、 最新命令はバッファ。 バッファは空。 違えば、もし、対象が「,」&&文字列中がいいえならば、 //「&&」は「両方OKだったらOK」 バッファは「{バッファ}{改行}」。 違えば、もし、対象が「"」ならば、 //「"」は一般的な言語では文字列の最初を表す もし、文字列中がはいならば、 文字列中は、いいえ。 もし、最新命令が「print」ならば、 アセンブリデータに「STR{文字列数} db "{バッファ}", 0」を配列追加。 アセンブリに「invoke OutputString, offset STR{文字列数}」を配列追加。 文字列数は文字列数+1。 バッファは空。 違えば、もし、最新命令が「msgbox」ならば、 アセンブリデータに「STR{文字列数} db "{バッファ¥0}", 0」
を配列追加。 もし、バッファ¥1が空ならば、 アセンブリに「invoke MessageBoxA, 0, offset STR{文字列数},
offset STR{文字列数}, 0」を配列追加。 違えば、 アセンブリデータに「STR{文字列数+1} db "{バッファ¥1}",
0」を配列追加。 アセンブリに「invoke MessageBoxA, 0, offset STR{文字列数},
offset STR{文字列数+1}, 0」を配列追加。 文字列数は文字列数+1。 //文字列を1つ多く使ったので 文字列数は文字列数+1。 バッファは空。 違えば、 文字列中は、はい。 バッファは空。 //文字列の最初についてしまう「"」対策 違えば、もし、対象が改行でなければ、 バッファは「{バッファ}{対象}」。 //上記以外の場合 //printの後の半角スペースとかは //この行から5行上で対処してしまっています 「.586 .model flat, stdcall include iolib.inc includelib iolib.lib include kernel32.inc includelib kernel32.lib .data {アセンブリデータ} .code _start: {アセンブリ} invoke ExitProcess, 0 end _start 」を「{コマンドライン¥1}.asm」に保存。
実装が終わったら、実行ファイル「build.exe」を作成し、「vefbl」フォルダ内に配置します(旧「build.exe」を上書きします)。