非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

C++ の調査(8)

【西川和久の不定期コラム】かつて筆者にとって初のパソコン、MC6802搭載ワンボードマイコンが2025年に復活!? - PC Watch」によるとMC6802互換CPUのワンボードマイコン風のものがあるそうです。「GAME」、「TL/1」、「TINY BASIC」などのプログラミング言語が使えるらしいです。

これは手動で16進で入力するのでしょうか。Z80 はまだなんとかわかるのですが MC6802 はよくわかりません。

X68000エミュレーターでは BASIC 風の言語が使えるようなので、X68000 向けには必要ないのですが、BASIC 風の言語を C++ で書いてみたいと思います。

プログラム電卓」では BASIC 風の言語で記述するようになっていましたが、TypeScript から C++ に変換する方法を調べるためにこれを C++ で書き直してみたいと思います。

C++ で BASIC インタープリターを作ってください

と ChatGPT で入力すると以下の結果となりました。

C++ で簡単な BASIC インタープリターを作るには、以下のような機能が必要になります:

1. 字句解析(Lexer) トークンに分解。
2. 構文解析(Parser) 文や式の構造を解析。
3. 実行(Evaluator) 構文木に従って実行。
4. ステート管理 変数、行番号、GOTO などの制御構造。

以下は、最小限の BASIC インタープリター(`LET`, `PRINT`, `GOTO`, `END` をサポート)です。

サンプルコード(簡易 BASIC インタープリター)

#include <iostream>
#include <map>
#include <sstream>
#include <vector>
#include <string>
#include <cstdlib>

using namespace std;

map<string, int> variables;
map<int, string> program;

void executeLine(const string& line);

void runProgram() {
    auto it = program.begin();
    while (it != program.end()) {
        stringstream ss(it->second);
        string command;
        ss >> command;
        if (command == "END") {
            break;
        }
        if (command == "GOTO") {
            int target;
            ss >> target;
            it = program.find(target);
            if (it == program.end()) {
                cerr << "Invalid GOTO target: " << target << endl;
                break;
            }
            continue;
        }
        executeLine(it->second);
        ++it;
    }
}

void executeLine(const string& line) {
    stringstream ss(line);
    string cmd;
    ss >> cmd;

    if (cmd == "PRINT") {
        string var;
        ss >> var;
        if (variables.count(var)) {
            cout << variables[var] << endl;
        } else {
            cout << "0" << endl;
        }
    } else if (cmd == "LET") {
        string var, eq;
        int val;
        ss >> var >> eq >> val;
        variables[var] = val;
    }
}

int main() {
    cout << "Enter BASIC code (empty line to run):" << endl;
    string line;
    while (true) {
        getline(cin, line);
        if (line.empty()) break;
        stringstream ss(line);
        int lineNumber;
        ss >> lineNumber;
        string rest;
        getline(ss, rest);
        if (!rest.empty() && rest[0] == ' ') rest.erase(0, 1);
        program[lineNumber] = rest;
    }

    runProgram();
    return 0;
}

使い方(実行例)

10 LET X = 5
20 PRINT X
30 LET X = 10
40 PRINT X
50 GOTO 20
60 END

このコードは `X` を 5 に設定して表示し、次に 10 に変更してまた表示し、20行目に戻って繰り返します。

今後の拡張案

  • `IF` 文のサポート
  • 四則演算の追加 (`X = X + 1` など)
  • `INPUT` コマンド
  • エラーチェックや文法解析の強化
  • 字句解析(トークナイザー)と構文解析の分離

もう少し構文解析を強くしたり、再帰下降パーサを使った本格的なものを作ることもできますが、この例は「最小限のBASIC動作」の導入に向いています。

必要なら、さらに高機能な実装を一緒に拡張していきましょうか?