自制编程语言(一、基本的编译器)

此教程实现一个simple语言

这是一个编译型语言,编译成nasm

simple.h

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <unordered_set>
#include <set>

void clearFileContent(const std::string& filePath) {
    std::ofstream file(filePath, std::ofstream::out | std::ofstream::trunc);
    if (!file) {
        std::cerr << "无法打开文件进行清空操作:" << filePath << std::endl;
    }
    file.close();
}

void copyFileContent(const std::string& sourceFilePath, const std::string& destinationFilePath) {
    std::ifstream sourceFile(sourceFilePath);
    if (!sourceFile) {
        std::cerr << "无法打开源文件:" << sourceFilePath << std::endl;
        return;
    }

    std::ofstream destinationFile(destinationFilePath, std::ios_base::app);
    if (!destinationFile) {
        std::cerr << "无法打开目标文件:" << destinationFilePath << std::endl;
        return;
    }

    std::string line;
    while (std::getline(sourceFile, line)) {
        destinationFile << line << std::endl;
    }

    sourceFile.close();
    destinationFile.close();
}
void convertToAsm(const std::string& inputFilePath, const std::string& outputFilePath, std::unordered_set<std::string>& processedFiles) {
    std::ifstream inputFile(inputFilePath);
    if (!inputFile) {
        std::cerr << "无法打开输入文件:" << inputFilePath << std::endl;
        return;
    }

    std::ofstream outputFile(outputFilePath, std::ios_base::app);
    if (!outputFile) {
        std::cerr << "无法创建输出文件:" << outputFilePath << std::endl;
        return;
    }

    std::string line;
    bool inBlockComment = false;
    bool inNasmBlock = false;
    std::string nasmContent;
    while (std::getline(inputFile, line)) {
        std::string trimmedLine = line;
        while (!trimmedLine.empty() && (trimmedLine[0] == ' ' || trimmedLine[0] == '\t')) {
            trimmedLine.erase(0, 1);
        }
        if (trimmedLine.empty()) continue;
        if (trimmedLine.find("//") == 0) continue;
        if (trimmedLine.find("/*")!= std::string::npos) {
            inBlockComment = true;
        }
        if (inBlockComment) {
            if (trimmedLine.find("*/")!= std::string::npos) {
                inBlockComment = false;
            }
            continue;
        }
        if (line.find("main()")!= std::string::npos) {
            outputFile << "main:\n    push rbp\n    mov rbp, rsp\n";
        } else if (line.find("print(")!= std::string::npos) {
            std::string content = line.substr(line.find("(") + 1, line.find(")") - line.find("(") - 1);
            outputFile << "    sub rsp, 20h\n";
            outputFile << "    mov rcx, " << content << "\n";
            outputFile << "    call printf\n";
            outputFile << "    add rsp, 20h\n";
        } else if (line.find("return")!= std::string::npos) {
            std::string content = line.substr(line.find("return") + 6, line.find("\n") - line.find("return") - 6);
            outputFile << "    mov eax," << content << "\n";
            outputFile << "    pop rbp\n    ret\n";
        } else if (line.find("str ")!= std::string::npos) {
            size_t spacePos = line.find(" ");
            size_t equalPos = line.find("=");
            if (spacePos == std::string::npos || equalPos == std::string::npos) {
                std::cerr << "错误的字符串定义格式:" << line << std::endl;
                continue;
            }
            std::string content1 = line.substr(spacePos + 1, equalPos - spacePos - 1);
            std::string content2 = line.substr(equalPos + 1);
            outputFile << "jmp " << content1 << "_end\n" << content1 << " db " << content2 << ",0\n" << content1 << "_end:\n";
        } else if (line.find("#NASM")!= std::string::npos) {
            size_t endPos = line.find("}#NASM_END");
            if (endPos == std::string::npos) {
                std::cerr << "未找到 #NASM_END :" << line << std::endl;
                continue;
            }
            std::string content = line.substr(line.find("#NASM{") + 6, endPos - line.find("#NASM{") - 6);
            outputFile << content << std::endl;
        } else if (line.find("int ")!= std::string::npos) {
            size_t spacePos = line.find(" ");
            size_t equalPos = line.find("=");
            if (spacePos == std::string::npos || equalPos == std::string::npos) {
                std::cerr << "错误的整数定义格式:" << line << std::endl;
                continue;
            }
            std::string content1 = line.substr(spacePos + 1, equalPos - spacePos - 1);
            std::string content2 = line.substr(equalPos + 1);
            outputFile << "jmp " << content1 << "_end\n" << content1 << " db " << content2 << "\n" << content1 << "_end:\n";
        } else if (line.find("input(")!= std::string::npos) {
            std::string content = line.substr(line.find("(") + 1, line.find(")") - line.find("(") - 1);
            outputFile << "    " << content << "1 resb 50\n";
            outputFile << "    sub rsp, 20h\n";
            outputFile << "    lea rdx, [" << content << "1]\n";
            outputFile << "    lea rcx, [aS]\n";
            outputFile << "    call scanf\n";
            outputFile << "    add rsp, 20h\n";
            outputFile << "    " << content << " db " << content << "1,0\n";
        } else if (line.find("system(")!= std::string::npos) {
            std::string content = line.substr(line.find("(") + 1, line.find(")") - line.find("(") - 1);
            outputFile << "    sub rsp, 20h\n";
            outputFile << "    lea rcx, [" << content << "]\n";
            outputFile << "    call system\n";
            outputFile << "    add rsp, 20h\n";
        } else if (line.find("#include")!= std::string::npos) {
            size_t startQuote = line.find('"');
            size_t endQuote = line.rfind('"');
            if (startQuote!= std::string::npos && endQuote!= std::string::npos && startQuote < endQuote) {
                std::string includeFileName = line.substr(startQuote + 1, endQuote - startQuote - 1);
                if (processedFiles.find(includeFileName) == processedFiles.end()) {
                    processedFiles.insert(includeFileName);
                    copyFileContent(includeFileName, outputFilePath);
                }
            }
        } else if (line.find("MessageBoxA(")!= std::string::npos) {
            size_t start = line.find("(");
            size_t mid = line.find(",");
            size_t end = line.find(")");
            std::string content1 = line.substr(start + 1, mid - start - 1);
            std::string content2 = line.substr(mid + 1, end - mid - 1);
            outputFile << "    sub rsp, 20h\n    mov r9d, 0\n    lea r8, [" << content1 << "]\n";
            outputFile << "    lea rdx, [" << content2 << "]\n" << "    mov rcx, 0\n    mov rax, [__imp_MessageBoxA]\n    call rax\n    add rsp, 20h\n";
        } else if (line.find("if(")!= std::string::npos) {
            size_t startOpenParen = line.find("(");
            size_t endOpenParen = line.find(")");
            std::string condition = line.substr(startOpenParen + 1, endOpenParen - startOpenParen - 1);
            size_t comparisonOpPos = 0;
            if ((comparisonOpPos = condition.find("=="))!= std::string::npos) {
                std::string leftOperand = condition.substr(0, comparisonOpPos);
                std::string rightOperand = condition.substr(comparisonOpPos + 2);
                std::string labelTrue = "__if_true_" + std::to_string(outputFile.tellp());
                std::string labelEnd = "__if_end_" + std::to_string(outputFile.tellp());
                outputFile << "    push rax\n";
                outputFile << "    mov rax, " << leftOperand << "\n";
                outputFile << "    cmp rax, " << rightOperand << "\n";
                outputFile << "    push rax\n";
                outputFile << "    je " << labelTrue << "\n";
                outputFile << "    jmp " << labelEnd << "\n";
                outputFile << labelTrue << ":\n";
                // Process the code inside the if block.
                while (std::getline(inputFile, line) &&!line.find("}")) {
                    convertToAsm(line, outputFilePath, processedFiles);
                }
                outputFile << "    jmp " << labelEnd << "\n";
                outputFile << labelEnd <&
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值