玄1.0·中文代“马”

一直是用c++写代码,这个c++的使用上一直要我切换输入法,我现在便借助大模型来实现这个愿望。代码可能有错,请大家多多指教。

先运行,在用:

📝 使用示例

  1. 打开 XuanIDE.exe

  2. 写代码(默认已提供示例)

  3. 点击 💾 保存 ,输入文件名(如 test.玄

  4. 点击 🛠 编译,下方显示"✅ 编译成功!"

  5. 点击 ▶ 运行,程序输出会显示在下方

  6. 若程序死循环,点击 ■ 停止 强制结束

cpp 复制代码
// ============================================================
// 《玄》IDE v2.0  --- 完整版:保存/编译/运行/报错
// 编译: g++ XuanIDE.cpp -o XuanIDE.exe -lgdi32 -lcomctl32 -std=c++17 -static
// ============================================================

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <regex>
#include <algorithm>
#include <thread>
#include <cstdio>
#include <cstdlib>
#include <cctype>

using namespace std;

// ---------- 全局变量 ----------
HWND g_hMainWnd, g_hEdit, g_hOutput, g_hStatusBar;
HWND g_hBtnSave, g_hBtnCompile, g_hBtnRun, g_hBtnStop, g_hBtnClear;
HFONT g_hFont, g_hOutputFont;
HINSTANCE g_hInst;
string g_currentFilePath = "";
string g_currentFileName = "未命名.玄";
bool g_isRunning = false;
bool g_isCompiling = false;

// ---------- 工具函数 ----------
string read_file(const string& path) {
    ifstream f(path, ios::binary);
    if (!f) return "";
    stringstream ss; ss << f.rdbuf();
    return ss.str();
}

void write_file(const string& path, const string& content) {
    ofstream f(path);
    f << content;
}

bool file_exists(const string& path) {
    ifstream f(path);
    return f.good();
}

// ---------- 核心转译(增强"比"处理,支持"或者"中的英文符号) ----------
string translate_xuan(const string& src) {
    // 预处理:将"或者"后面的括号内容直接移除(因为可能是英文符号,我们统一不处理)
    // 但我们更保守:保留原样,因为后续映射会处理 < > 符号(兼容模式)
    // 但为了规范化,我们把"(或者a<i)"这样的内容直接替换为""(空)
    // 这样用户就可以写"i 比 a 小"即可,括号内的额外说明会被忽略。
    string processed = src;
    // 移除 "(或者...)" 和 "(或者...)" 中的内容,保留括号占位
    regex or_pattern(R"([((]?或者\s*[\S\s]*?[))])");
    processed = regex_replace(processed, or_pattern, "");

    vector<pair<string, string>> patterns = {
        {"头文件《标准IO》", "#include <iostream>\nusing namespace std;\n"},
        {"主程序:", "int main() {"},
        {"输出:", "std::cout << "},
        {"输入:", "std::cin >> "},
        {"换行", "std::endl"},
        {"小于", "<"}, {"大于", ">"}, {"等于", "=="}, {"不等于", "!="},
        {"与", "&&"}, {"或", "||"}, {"非", "!"},
        {"递增", "++"}, {"递减", "--"},
        {"加", "+"}, {"减", "-"}, {"乘", "*"}, {"除", "/"}, {"模", "%"},
        {"《", "{"}, {"》", "}"}, {"「", "{"}, {"」", "}"},
        {"(", "("}, {")", ")"}, {";", ";"}, {":", " << "}, {"。", "}"},
        {"定义", "int"}, {"对于", "for"}, {"如果", "if"}, {"否则", "else"}, {"返回", "return"},
        {"输出", "std::cout << "}
    };
    sort(patterns.begin(), patterns.end(),
         [](const auto& a, const auto& b) { return a.first.size() > b.first.size(); });

    // 自定义替换函数(跳过字符串和注释)
    string out;
    size_t i = 0;
    while (i < processed.size()) {
        // 跳过字符串
        if (processed[i] == '"') {
            out += processed[i++];
            while (i < processed.size() && (processed[i] != '"' || (i > 0 && processed[i-1] == '\\'))) out += processed[i++];
            if (i < processed.size()) out += processed[i++];
            continue;
        }
        // 跳过单行注释
        if (processed[i] == '/' && i+1 < processed.size() && processed[i+1] == '/') {
            while (i < processed.size() && processed[i] != '\n') out += processed[i++];
            continue;
        }
        // 跳过多行注释
        if (processed[i] == '/' && i+1 < processed.size() && processed[i+1] == '*') {
            out += processed[i++]; out += processed[i++];
            while (!(processed[i-1] == '*' && processed[i] == '/') && i < processed.size()) out += processed[i++];
            if (i < processed.size()) out += processed[i++];
            continue;
        }

        bool matched = false;
        // 处理"比"结构(i 比 a 小)
        if (processed.compare(i, 1, "比") == 0) {
            size_t start = i;
            while (start > 0 && !isspace(processed[start-1]) && processed[start-1] != '(' && processed[start-1] != '(') start--;
            size_t var1_end = i;
            size_t j = i + 1;
            while (j < processed.size() && isspace(processed[j])) j++;
            if (j < processed.size() && (processed[j] == '小' || processed[j] == '大')) {
                char op = (processed[j] == '小') ? '<' : '>';
                size_t after_op = j + 1;
                while (after_op < processed.size() && isspace(processed[after_op])) after_op++;
                size_t var2_start = after_op;
                while (var2_start < processed.size() && isspace(processed[var2_start])) var2_start++;
                size_t var2_end = var2_start;
                while (var2_end < processed.size() && !isspace(processed[var2_end]) && processed[var2_end] != ';' && processed[var2_end] != ')' && processed[var2_end] != ')' && processed[var2_end] != '《' && processed[var2_end] != '{') var2_end++;
                if (var2_start < processed.size() && var2_end > var2_start) {
                    string var1 = processed.substr(start, var1_end - start);
                    string var2 = processed.substr(var2_start, var2_end - var2_start);
                    out += var1 + " " + op + " " + var2;
                    i = var2_end;
                    matched = true;
                }
            }
        }

        if (!matched) {
            for (const auto& [from, to] : patterns) {
                if (processed.compare(i, from.size(), from) == 0) {
                    out += to;
                    i += from.size();
                    matched = true;
                    break;
                }
            }
        }

        if (!matched) out += processed[i++];
    }
    return out;
}

// ---------- 编译并(可选)运行 ----------
void CompileAndRun(const string& src, bool runAfter) {
    if (g_isRunning || g_isCompiling) return;
    g_isCompiling = true;
    SetWindowText(g_hBtnCompile, "⏳ 编译中...");
    EnableWindow(g_hBtnCompile, FALSE);
    SetWindowText(g_hBtnRun, "⏳ 编译中...");
    EnableWindow(g_hBtnRun, FALSE);
    SetWindowText(g_hOutput, "📝 正在转译...\n");

    // 转译
    string cpp = translate_xuan(src);
    write_file("output.cpp", cpp);

    // 调用编译器
    string buildLog;
    char buffer[1024];
#ifdef _WIN32
    string cmd = "g++ output.cpp -o output.exe -std=c++17 2>&1";
#else
    string cmd = "g++ output.cpp -o output -std=c++17 2>&1";
#endif
    FILE* pipe = _popen(cmd.c_str(), "r");
    if (pipe) {
        while (fgets(buffer, sizeof(buffer), pipe)) buildLog += buffer;
        _pclose(pipe);
    }

    // 显示编译结果
    if (buildLog.find("error") != string::npos || buildLog.find("Error") != string::npos) {
        SetWindowText(g_hOutput, ("❌ 编译失败:\n" + buildLog).c_str());
        g_isCompiling = false;
        SetWindowText(g_hBtnCompile, "🛠 编译");
        EnableWindow(g_hBtnCompile, TRUE);
        SetWindowText(g_hBtnRun, "▶ 运行");
        EnableWindow(g_hBtnRun, TRUE);
        return;
    }

    SetWindowText(g_hOutput, ("✅ 编译成功!\n" + buildLog).c_str());

    if (runAfter) {
        SetWindowText(g_hOutput, (string(GetWindowText(g_hOutput)) + "\n▶ 程序输出:\n--------------------\n").c_str());
        string outputLog;
#ifdef _WIN32
        FILE* runPipe = _popen("output.exe", "r");
#else
        FILE* runPipe = _popen("./output", "r");
#endif
        if (runPipe) {
            while (fgets(buffer, sizeof(buffer), runPipe)) outputLog += buffer;
            _pclose(runPipe);
        }
        SetWindowText(g_hOutput, (string(GetWindowText(g_hOutput)) + outputLog + "\n--------------------\n").c_str());
    }

    g_isCompiling = false;
    SetWindowText(g_hBtnCompile, "🛠 编译");
    EnableWindow(g_hBtnCompile, TRUE);
    SetWindowText(g_hBtnRun, "▶ 运行");
    EnableWindow(g_hBtnRun, TRUE);
}

// ---------- 文件操作 ----------
bool SaveFile(const string& content) {
    if (g_currentFilePath.empty()) {
        OPENFILENAMEA ofn = {};
        char fileName[MAX_PATH] = "";
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = g_hMainWnd;
        ofn.lpstrFilter = "玄源文件\0*.玄\0所有文件\0*.*\0";
        ofn.lpstrFile = fileName;
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrDefExt = "玄";
        ofn.Flags = OFN_OVERWRITEPROMPT;
        if (!GetSaveFileNameA(&ofn)) return false;
        g_currentFilePath = fileName;
    }
    write_file(g_currentFilePath, content);
    g_currentFileName = g_currentFilePath.substr(g_currentFilePath.find_last_of("/\\") + 1);
    SetWindowText(g_hStatusBar, g_currentFileName.c_str());
    return true;
}

bool OpenFile() {
    OPENFILENAMEA ofn = {};
    char fileName[MAX_PATH] = "";
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = g_hMainWnd;
    ofn.lpstrFilter = "玄源文件\0*.玄\0所有文件\0*.*\0";
    ofn.lpstrFile = fileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_FILEMUSTEXIST;
    if (!GetOpenFileNameA(&ofn)) return false;
    g_currentFilePath = fileName;
    string content = read_file(g_currentFilePath);
    SetWindowText(g_hEdit, content.c_str());
    g_currentFileName = g_currentFilePath.substr(g_currentFilePath.find_last_of("/\\") + 1);
    SetWindowText(g_hStatusBar, g_currentFileName.c_str());
    return true;
}

// ---------- 窗口过程 ----------
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
            // 创建编辑区
            g_hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
                WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL,
                0, 0, 0, 0, hWnd, (HMENU)101, g_hInst, NULL);
            SendMessage(g_hEdit, WM_SETFONT, (WPARAM)g_hFont, TRUE);

            // 输出区
            g_hOutput = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
                WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL | ES_READONLY,
                0, 0, 0, 0, hWnd, (HMENU)102, g_hInst, NULL);
            SendMessage(g_hOutput, WM_SETFONT, (WPARAM)g_hOutputFont, TRUE);

            // 工具栏按钮
            g_hBtnSave = CreateWindow("BUTTON", "💾 保存", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                5, 5, 70, 28, hWnd, (HMENU)201, g_hInst, NULL);
            g_hBtnCompile = CreateWindow("BUTTON", "🛠 编译", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                80, 5, 70, 28, hWnd, (HMENU)202, g_hInst, NULL);
            g_hBtnRun = CreateWindow("BUTTON", "▶ 运行", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                155, 5, 70, 28, hWnd, (HMENU)203, g_hInst, NULL);
            g_hBtnStop = CreateWindow("BUTTON", "■ 停止", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                230, 5, 70, 28, hWnd, (HMENU)204, g_hInst, NULL);
            EnableWindow(g_hBtnStop, FALSE);
            g_hBtnClear = CreateWindow("BUTTON", "🗑 清空", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                305, 5, 70, 28, hWnd, (HMENU)205, g_hInst, NULL);

            // 状态栏
            g_hStatusBar = CreateWindow(STATUSCLASSNAME, "未命名.玄", WS_CHILD | WS_VISIBLE,
                0, 0, 0, 0, hWnd, (HMENU)301, g_hInst, NULL);

            // 默认示例
            string demo = 
                "头文件《标准IO》\n"
                "\n"
                "主程序:\n"
                "    定义 a = 10;\n"
                "    定义 总数 = 0;\n"
                "\n"
                "    对于(定义 i = 0;i 比 a 小;i 递增)《\n"
                "        如果(i 大于 2)《\n"
                "            总数 = 总数 加 1;\n"
                "            输出:\"当前i是:\":i:换行;\n"
                "        》\n"
                "    》\n"
                "\n"
                "    输出:\"循环结束,总数是:\":总数:换行;\n"
                "    返回 0;\n"
                "。// 结束\n";
            SetWindowText(g_hEdit, demo.c_str());
            break;
        }

        case WM_SIZE: {
            RECT rc; GetClientRect(hWnd, &rc);
            int w = rc.right - rc.left, h = rc.bottom - rc.top;
            int toolbarH = 40, outH = 120, statusH = 25;
            SetWindowPos(g_hEdit, NULL, 5, toolbarH+5, w-10, h-toolbarH-outH-statusH-15, SWP_NOZORDER);
            SetWindowPos(g_hOutput, NULL, 5, h-outH-statusH-5, w-10, outH-5, SWP_NOZORDER);
            SendMessage(g_hStatusBar, WM_SIZE, 0, 0);
            break;
        }

        case WM_COMMAND: {
            int id = LOWORD(wParam);
            if (id == 201) { // 保存
                int len = GetWindowTextLength(g_hEdit) + 1;
                char* buf = new char[len];
                GetWindowText(g_hEdit, buf, len);
                string content = buf;
                delete[] buf;
                if (SaveFile(content)) {
                    SetWindowText(g_hOutput, "✅ 已保存: " + g_currentFilePath + "\n");
                }
            }
            else if (id == 202) { // 编译
                if (g_isCompiling || g_isRunning) break;
                int len = GetWindowTextLength(g_hEdit) + 1;
                char* buf = new char[len];
                GetWindowText(g_hEdit, buf, len);
                string src = buf;
                delete[] buf;
                // 先保存
                if (!g_currentFilePath.empty()) {
                    write_file(g_currentFilePath, src);
                }
                SetWindowText(g_hOutput, "");
                thread t([src]() { CompileAndRun(src, false); });
                t.detach();
            }
            else if (id == 203) { // 运行
                if (g_isCompiling || g_isRunning) break;
                int len = GetWindowTextLength(g_hEdit) + 1;
                char* buf = new char[len];
                GetWindowText(g_hEdit, buf, len);
                string src = buf;
                delete[] buf;
                if (!g_currentFilePath.empty()) {
                    write_file(g_currentFilePath, src);
                }
                SetWindowText(g_hOutput, "");
                thread t([src]() { CompileAndRun(src, true); });
                t.detach();
                EnableWindow(g_hBtnStop, TRUE);
                g_isRunning = true;
            }
            else if (id == 204) { // 停止
                system("taskkill /F /IM output.exe >nul 2>nul");
                g_isRunning = false;
                EnableWindow(g_hBtnStop, FALSE);
                SetWindowText(g_hOutput, "⏹ 已终止运行\n");
            }
            else if (id == 205) { // 清空
                SetWindowText(g_hOutput, "");
            }
            break;
        }

        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

// ---------- 入口 ----------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    g_hInst = hInstance;
    INITCOMMONCONTROLSEX icex = {sizeof(icex), ICC_WIN95_CLASSES};
    InitCommonControlsEx(&icex);

    WNDCLASS wc = {};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = "XuanIDE";
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    RegisterClass(&wc);

    g_hMainWnd = CreateWindowEx(0, "XuanIDE", "《玄》IDE v2.0",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
        CW_USEDEFAULT, CW_USEDEFAULT, 950, 700,
        NULL, NULL, hInstance, NULL);
    if (!g_hMainWnd) return 1;

    g_hFont = CreateFont(20, 0, 0, 0, FW_NORMAL, 0, 0, 0,
        DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Consolas");
    g_hOutputFont = CreateFont(16, 0, 0, 0, FW_NORMAL, 0, 0, 0,
        DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Consolas");

    ShowWindow(g_hMainWnd, nCmdShow);
    UpdateWindow(g_hMainWnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}