From 196140f9b85ce3446d0b64dd5731962fd982f0f8 Mon Sep 17 00:00:00 2001 From: mmichlol Date: Fri, 6 Feb 2026 18:21:58 +0100 Subject: [PATCH] fixed parser --- PCCcompiler/codegen.cpp | 53 +++++++++++++++++------------------------ PCCcompiler/main.cpp | 29 +++++++++++++--------- PCCcompiler/parser.cpp | 42 +++++++++++++++++++++++++++----- 3 files changed, 76 insertions(+), 48 deletions(-) diff --git a/PCCcompiler/codegen.cpp b/PCCcompiler/codegen.cpp index 841cf96..e6b6712 100644 --- a/PCCcompiler/codegen.cpp +++ b/PCCcompiler/codegen.cpp @@ -6,7 +6,6 @@ std::string generateAssembly(const CompilerState& state) { std::string result; - // --- NAG£ÓWEK --- result += "global main\n"; result += "extern printf\n"; result += "extern GetAsyncKeyState\n\n"; @@ -20,28 +19,25 @@ std::string generateAssembly(const CompilerState& state) { result += "section .text\n"; - // --- GENEROWANIE FUNKCJI --- + // --- FUNKCJE --- for (const auto& func : state.functions) { result += func.first + ":\n"; result += " sub rsp, 40\n"; - // Iterujemy przez LISTÊ ROZKAZÓW danej funkcji - // Rozkazy mog¹ byæ typu "PRINT:x" albo "IF:index" for (const std::string& cmd : func.second) { - // 1. ZWYK£Y PRINT (format: "PRINT:nazwa_zmiennej") + result += " ; CMD: " + cmd + "\n"; + if (cmd.find("PRINT:") == 0) { - std::string varName = cmd.substr(6); // utnij "PRINT:" + std::string varName = cmd.substr(6); if (state.variables.count(varName)) { result += " mov edx, [" + varName + "]\n"; result += " lea rcx, [rel fmt]\n"; result += " call printf\n"; } } - // 2. BLOK IF (format: "IF:index_w_tablicy") else if (cmd.find("IF:") == 0) { - int ifIndex = std::stoi(cmd.substr(3)); // pobierz numer IFa - + int ifIndex = std::stoi(cmd.substr(3)); if (ifIndex >= 0 && ifIndex < state.ifBlocks.size()) { const auto& ifBlock = state.ifBlocks[ifIndex]; @@ -50,43 +46,30 @@ std::string generateAssembly(const CompilerState& state) { result += " ; --- IF START [" + ifBlock.conditionVar + "] ---\n"; result += " mov eax, [" + ifBlock.conditionVar + "]\n"; - result += " cmp eax, 1\n"; - result += " jne " + labelSkip + "\n"; // Skocz jeœli FA£SZ (0) - // Generuj zawartoœæ œrodka IFa - for (const std::string& innerCmd : ifBlock.prints) { - if (state.variables.count(innerCmd)) { - result += " mov edx, [" + innerCmd + "]\n"; + result += " test eax, eax\n"; + result += " jz " + labelSkip + "\n"; + + for (const std::string& innerPrint : ifBlock.prints) { + if (state.variables.count(innerPrint)) { + result += " mov edx, [" + innerPrint + "]\n"; result += " lea rcx, [rel fmt]\n"; result += " call printf\n"; } } - result += labelSkip + ":\n"; - result += " ; --- IF END ---\n"; } + } } } - result += " add rsp, 40\n"; result += " ret\n\n"; } - - // --- MAIN --- +// ==main== result += "main:\n"; result += " sub rsp, 40\n"; - // Globalne printy (bez zmian) - for (const std::string& var : state.globalPrints) { - if (state.variables.count(var)) { - result += " mov edx, [" + var + "]\n"; - result += " lea rcx, [rel fmt]\n"; - result += " call printf\n"; - } - } - - // Wywo³ania funkcji for (const std::string& call : state.printCalls) { if (call.find("CALL_") == 0) { std::string funcName = call.substr(5); @@ -96,7 +79,15 @@ std::string generateAssembly(const CompilerState& state) { } } - // Pauza + for (const std::string& var : state.globalPrints) { + if (state.variables.count(var)) { + result += " mov edx, [" + var + "]\n"; + result += " lea rcx, [rel fmt]\n"; + result += " call printf\n"; + } + } + + result += " lea rcx, [rel pause_msg]\n"; result += " call printf\n"; result += "pause_loop:\n"; diff --git a/PCCcompiler/main.cpp b/PCCcompiler/main.cpp index b52fe4a..9d53d9f 100644 --- a/PCCcompiler/main.cpp +++ b/PCCcompiler/main.cpp @@ -90,24 +90,31 @@ int main(int argc, char* argv[]) { // --- 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 + // 1. Ustal bazowÄ… nazwÄ™ (bez rozszerzenia) + std::string baseName; if (outputName.empty()) { - if (baseName.find(".exe") == std::string::npos) baseName += ".exe"; + // JeÅ›li nie podano -o, weź nazwÄ™ pliku wejÅ›ciowego i utnij .pcc + size_t lastDot = inputFile.find_last_of("."); + if (lastDot != std::string::npos) + baseName = inputFile.substr(0, lastDot); + else + baseName = inputFile; } else { - // JeÅ›li użytkownik podaÅ‚ nazwÄ™ bez .exe, dodaj jÄ… - if (outputName.find(".exe") == std::string::npos) outputName += ".exe"; - baseName = outputName; + // JeÅ›li podano -o, sprawdź czy ma .exe i ewentualnie utnij + // (żebyÅ›my mogli dodać .asm i .obj bez baÅ‚aganu) + size_t exePos = outputName.find(".exe"); + if (exePos != std::string::npos) + baseName = outputName.substr(0, exePos); + else + baseName = outputName; } - // Åšcieżki wyjÅ›ciowe - // Uwaga: zakÅ‚adam proste nazewnictwo, można tu poprawić usuwanie Å›cieżek z nazwy pliku + // Teraz budujemy Å›cieżki - czysto i Å‚adnie std::string asmPath = "output\\" + baseName + ".asm"; std::string objPath = "output\\" + baseName + ".obj"; - std::string exePath = "output\\" + baseName; + std::string exePath = "output\\" + baseName + ".exe"; + // Zapisz ASM std::ofstream asmOut(asmPath); diff --git a/PCCcompiler/parser.cpp b/PCCcompiler/parser.cpp index dc5f812..99b2d8c 100644 --- a/PCCcompiler/parser.cpp +++ b/PCCcompiler/parser.cpp @@ -33,18 +33,28 @@ void processSource(const std::string& src, CompilerState& state) { continue; } } - // } + // } ZAMYKANIE KLAMRY else if (line.find("}") != std::string::npos) { if (!state.braceStack.empty()) { + // Sprawdzamy co zamykamy PRZED zdjÄ™ciem ze stosu + bool wasFunction = state.braceStack.top(); state.braceStack.pop(); - if (!state.braceStack.empty()) { + + // JeÅ›li zdjÄ™liÅ›my 'true' (czyli znacznik funkcji) ORAZ stos jest pusty + // to znaczy, że zamknÄ™liÅ›my funkcjÄ™ głównÄ…. + if (wasFunction && state.braceStack.empty()) { state.inFunction = false; state.currentFunction.clear(); std::cout << " END FUNC\n"; } + else { + // ZamknÄ™liÅ›my IF-a (lub inny blok wewnÄ™trzny) + std::cout << " END BLOCK (IF)\n"; + } } continue; } + // INT if (line.length() > 3 && line.substr(0, 3) == "int") { size_t eqPos = line.find("=", 4); @@ -124,10 +134,16 @@ void processSource(const std::string& src, CompilerState& state) { IfBlock newIf; newIf.conditionVar = condition; - state.ifBlocks.push_back(newIf); // ZMIANA: state.ifBlocks + state.ifBlocks.push_back(newIf); + + // WAÅ»NE: Dodajemy instrukcjÄ™ "IF:numer" do listy rozkazów funkcji + if (state.inFunction) { + int ifIndex = state.ifBlocks.size() - 1; + state.functions[state.currentFunction].push_back("IF:" + std::to_string(ifIndex)); + } std::cout << " IF [" << condition << "] { <- blok #" << state.ifBlocks.size() - 1 << "\n"; - state.braceStack.push(false); + state.braceStack.push(false); // false oznacza, że to klamra IFa (a nie funkcji) continue; } } @@ -139,14 +155,28 @@ void processSource(const std::string& src, CompilerState& state) { std::string varName = line.substr(openParen + 1, closeParen - openParen - 1); size_t varStart = varName.find_first_not_of(" \t"); size_t varEnd = varName.find_last_not_of(" \t"); + if (varStart != std::string::npos) { varName = varName.substr(varStart, varEnd - varStart + 1); if (state.inFunction && !state.currentFunction.empty()) { - state.functions[state.currentFunction].push_back(varName); - std::cout << " FUNC PRINT " << state.currentFunction << ": " << varName << "\n"; + // SPRAWDZAMY CZY JESTEÅšMY W IFIE + // (sprawdzamy szczyt stosu klamerek: false = IF, true = FUNC) + if (!state.braceStack.empty() && state.braceStack.top() == false) { + // JesteÅ›my w IFie -> dodaj TYLKO do ifBlocks + if (!state.ifBlocks.empty()) { + state.ifBlocks.back().prints.push_back(varName); + std::cout << " IF PRINT: " << varName << "\n"; + } + } + else { + // JesteÅ›my w normalnej funkcji (poza ifem) -> dodaj jako rozkaz PRINT: + state.functions[state.currentFunction].push_back("PRINT:" + varName); + std::cout << " FUNC PRINT " << state.currentFunction << ": " << varName << "\n"; + } } else { + // Print globalny (poza funkcjami) state.globalPrints.push_back(varName); std::cout << " PRINT " << varName << "\n"; }