此教程实现一个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 <&