Files
PCCCompiler/PCCcompiler/main.cpp
2026-02-06 16:04:23 +01:00

135 lines
4.2 KiB
C++

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib> // do std::system
#include "compiler_types.h"
#include "parser.h"
#include "codegen.h"
int main(int argc, char* argv[]) {
std::string inputFile, outputName;
std::string Version = "v1.5.0-modular"; // Zaktualizowałem wersję :)
bool showHelp = false, showVersion = false, showCredits = false;
// --- PARSOWANIE ARGUMENTÓW ---
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
if (arg == "--help" || arg == "-h") {
showHelp = true;
}
else if (arg == "--version" || arg == "-v") {
showVersion = true;
}
else if (arg == "--credits" || arg == "-c") {
showCredits = true;
}
else if (arg.substr(0, 2) == "-o") {
if (arg.size() > 2) {
outputName = arg.substr(2);
}
else if (i + 1 < argc) {
outputName = argv[++i];
}
}
else {
inputFile = arg;
}
}
// --- OBSŁUGA INFORMACYJNA ---
if (showVersion) {
std::cout << "PCC Compiler " << Version << " (x64, Modular structure)\n";
return 0;
}
if (showCredits) {
std::cout << "Created by: Michal Lewandowski\n";
std::cout << "Contact : slawek.1q2w3e4r@gmail.com\n"; // Twój email z oryginału
std::cout << "Docs: https://nodrop.xyz/PCC_docs.html\n";
return 0;
}
if (showHelp || inputFile.empty()) {
std::cout << "PCC Compiler " << Version << "\n";
std::cout << "Usage: PCC [Options] File.pcc\n\n";
std::cout << "Options:\n";
std::cout << " -h, --help Show Help\n";
std::cout << " -v, --version Show Version\n";
std::cout << " -o Name Exe Name (output\\Name.exe)\n";
return 0;
}
// --- WCZYTYWANIE PLIKU ---
std::ifstream in(inputFile);
if (!in) {
std::cerr << "Error: Cannot open file " << inputFile << "\n";
return 1;
}
std::string src((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
in.close();
// --- LOGIKA KOMPILATORA ---
CompilerState state;
std::cout << "[INFO] Parsing code...\n";
// 1. Parsowanie tekstu do struktur
processSource(src, state);
std::cout << "[INFO] Calculating expressions...\n";
// 2. Obliczanie matematyki
calculateExpressions(state);
std::cout << "[INFO] Generating Assembly...\n";
// 3. Generowanie kodu ASM
std::string asmCode = generateAssembly(state);
// --- ZAPIS I KOMPILACJA ZEWNĘTRZNA ---
std::system("if not exist output mkdir output");
std::string baseName = outputName.empty() ?
inputFile.substr(0, inputFile.find_last_of(".")) : outputName;
// Upewnij się, że nazwa nie ma rozszerzenia .exe w środku ścieżki
if (outputName.empty()) {
if (baseName.find(".exe") == std::string::npos) baseName += ".exe";
}
else {
// Jeśli użytkownik podał nazwę bez .exe, dodaj ją
if (outputName.find(".exe") == std::string::npos) outputName += ".exe";
baseName = outputName;
}
// Ścieżki wyjściowe
// Uwaga: zakładam proste nazewnictwo, można tu poprawić usuwanie ścieżek z nazwy pliku
std::string asmPath = "output\\" + baseName + ".asm";
std::string objPath = "output\\" + baseName + ".obj";
std::string exePath = "output\\" + baseName;
// Zapisz ASM
std::ofstream asmOut(asmPath);
asmOut << asmCode;
asmOut.close();
std::cout << "ASM saved to: " << asmPath << "\n";
// Uruchom NASM
std::string nasmCmd = "nasm -f win64 \"" + asmPath + "\" -o \"" + objPath + "\"";
if (std::system(nasmCmd.c_str()) != 0) {
std::cerr << "NASM Error! Check if NASM is in PATH.\n";
return 1;
}
// Uruchom GoLink
std::string linkCmd = "go-link.exe /console /entry:main \"" + objPath + "\" msvcrt.dll kernel32.dll user32.dll \"" + exePath + "\"";
if (std::system(linkCmd.c_str()) != 0) {
std::cerr << "GoLink Error! Check if go-link.exe is in PATH.\n";
return 1;
}
std::cout << "SUCCESS! Executable created: " << exePath << "\n";
return 0;
}