From 5fbd0f98a2ecbad0ba56fc5261907f9f4c02cde9 Mon Sep 17 00:00:00 2001 From: mmichlol Date: Fri, 6 Feb 2026 21:01:12 +0100 Subject: [PATCH] added int func(int x, int y), return int --- PCCcompiler/codegen.cpp | 255 ++++++++++++++++++++--------- PCCcompiler/compiler_types.h | 57 +++++-- PCCcompiler/parser.cpp | 309 +++++++++++++++-------------------- 3 files changed, 355 insertions(+), 266 deletions(-) diff --git a/PCCcompiler/codegen.cpp b/PCCcompiler/codegen.cpp index e6b6712..cb397ec 100644 --- a/PCCcompiler/codegen.cpp +++ b/PCCcompiler/codegen.cpp @@ -1,102 +1,209 @@ #include "codegen.h" -#include -#include #include +#include +#include + +// Pomocnicza funkcja: sprawdza czy string to czysta liczba +bool isNumber(const std::string& s) { + if (s.empty()) return false; + size_t start = (s[0] == '-') ? 1 : 0; + for (size_t i = start; i < s.length(); i++) { + if (!isdigit(s[i])) return false; + } + return true; +} + +// Zamienia nazw zmiennej na adres pamici [rbp-X] lub liczb +std::string getVarLocation(const std::string& name, const std::map& locals) { + std::string cleanName = name; + // Usuwamy ewentualne spacje + size_t first = cleanName.find_first_not_of(" \t"); + if (first != std::string::npos) cleanName = cleanName.substr(first); + size_t last = cleanName.find_last_not_of(" \t"); + if (last != std::string::npos) cleanName = cleanName.substr(0, last + 1); + + if (cleanName.empty()) return "0"; + if (isNumber(cleanName)) return cleanName; + + if (cleanName == "RAX") return "eax"; + + if (locals.count(cleanName)) { + int offset = locals.at(cleanName); + return "[rbp-" + std::to_string(offset) + "]"; + } + + // Zwracamy orygina (jeli to np. nazwa etykiety), ale to zazwyczaj bd dla zmiennych + return cleanName; +} std::string generateAssembly(const CompilerState& state) { std::string result; - result += "global main\n"; result += "extern printf\n"; - result += "extern GetAsyncKeyState\n\n"; - + result += "extern getchar\n"; // <--- DODAJ TO result += "section .data\n"; - for (const auto& v : state.variables) { - result += " " + v.first + " dd " + std::to_string(v.second) + "\n"; - } - result += " fmt db '%d', 10, 0\n"; - result += " pause_msg db 'Nacisnij ESC aby zamknac...', 10, 0\n\n"; + result += " fmt db '%d', 10, 0\n"; + result += "section .text\n\n"; - result += "section .text\n"; + for (const auto& pair : state.functions) { + const Function& func = pair.second; + result += func.name + ":\n"; - // --- FUNKCJE --- - for (const auto& func : state.functions) { - result += func.first + ":\n"; - result += " sub rsp, 40\n"; + result += " push rbp\n"; + result += " mov rbp, rsp\n"; + result += " sub rsp, 256\n"; - for (const std::string& cmd : func.second) { + std::map stackMap; + int currentStack = 8; - result += " ; CMD: " + cmd + "\n"; + // 1. ARGUMENTY + if (func.args.size() > 0) { + stackMap[func.args[0]] = currentStack; + result += " mov [rbp-" + std::to_string(currentStack) + "], rcx ; arg " + func.args[0] + "\n"; + currentStack += 8; + } + if (func.args.size() > 1) { + stackMap[func.args[1]] = currentStack; + result += " mov [rbp-" + std::to_string(currentStack) + "], rdx ; arg " + func.args[1] + "\n"; + currentStack += 8; + } - if (cmd.find("PRINT:") == 0) { - 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. INSTRUKCJE + for (const auto& instr : func.instructions) { + + // Rezerwacja miejsca dla nowych zmiennych + if ((instr.type == OpType::ASSIGN || instr.type == OpType::ADD || instr.type == OpType::EQ) + && stackMap.find(instr.arg1) == stackMap.end() && instr.arg1 != "RAX") { + stackMap[instr.arg1] = currentStack; + currentStack += 8; } - else if (cmd.find("IF:") == 0) { - int ifIndex = std::stoi(cmd.substr(3)); - if (ifIndex >= 0 && ifIndex < state.ifBlocks.size()) { - const auto& ifBlock = state.ifBlocks[ifIndex]; - if (state.variables.count(ifBlock.conditionVar)) { - std::string labelSkip = "skip_if_" + std::to_string(ifIndex); + switch (instr.type) { + case OpType::ASSIGN: { + std::string src = getVarLocation(instr.arg2, stackMap); + std::string dst = getVarLocation(instr.arg1, stackMap); + result += " mov eax, " + src + "\n"; + result += " mov " + dst + ", eax\n"; + break; + } + case OpType::ADD: { + std::string op1 = getVarLocation(instr.arg2, stackMap); + std::string op2 = getVarLocation(instr.arg3, stackMap); + std::string dst = getVarLocation(instr.arg1, stackMap); + result += " mov eax, " + op1 + "\n"; + result += " add eax, " + op2 + "\n"; + result += " mov " + dst + ", eax\n"; + break; + } + case OpType::EQ: { + std::string op1 = getVarLocation(instr.arg2, stackMap); + std::string op2 = getVarLocation(instr.arg3, stackMap); + std::string dst = getVarLocation(instr.arg1, stackMap); + result += " mov eax, " + op1 + "\n"; + result += " cmp eax, " + op2 + "\n"; + result += " sete al\n"; + result += " movzx eax, al\n"; + result += " mov " + dst + ", eax\n"; + break; + } + case OpType::JMP_FALSE: { + // PARSOWANIE WARUNKU: np. "suma == 30" lub "test" + std::string condRaw = instr.arg2; + size_t eqPos = condRaw.find("=="); - result += " ; --- IF START [" + ifBlock.conditionVar + "] ---\n"; - result += " mov eax, [" + ifBlock.conditionVar + "]\n"; + if (eqPos != std::string::npos) { + // Mamy porwnanie w IFie (a == b) + std::string leftStr = condRaw.substr(0, eqPos); + std::string rightStr = condRaw.substr(eqPos + 2); - result += " test eax, eax\n"; - result += " jz " + labelSkip + "\n"; + std::string op1 = getVarLocation(leftStr, stackMap); + std::string op2 = getVarLocation(rightStr, stackMap); - 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 += " mov eax, " + op1 + "\n"; + result += " cmp eax, " + op2 + "\n"; + result += " jne " + instr.arg1 + " ; jump if NOT equal\n"; + } + else { + // Zwyka zmienna boolowska (if test) + std::string cond = getVarLocation(condRaw, stackMap); + result += " mov eax, " + cond + "\n"; + result += " test eax, eax\n"; + result += " jz " + instr.arg1 + " ; jump if zero\n"; + } + break; + } + case OpType::LABEL: { + result += instr.arg1 + ":\n"; + break; + } + case OpType::RETURN: { + std::string val = getVarLocation(instr.arg1, stackMap); + result += " mov eax, " + val + " ; return value\n"; + result += " leave\n"; + result += " ret\n"; + break; + } + case OpType::PRINT: { + std::string val = getVarLocation(instr.arg1, stackMap); + result += " mov edx, " + val + "\n"; + result += " lea rcx, [rel fmt]\n"; + result += " call printf\n"; + break; + } + case OpType::CALL: { + // Parsowanie argumentw + std::string argsRaw = instr.arg2; + std::vector callArgs; + if (instr.arg1 == "input") { + result += " call getchar\n"; // Czeka na enter + break; // Wychodzimy, eby nie robi standardowego call + } + if (!argsRaw.empty()) { + size_t comma = argsRaw.find(','); + if (comma != std::string::npos) { + callArgs.push_back(argsRaw.substr(0, comma)); + callArgs.push_back(argsRaw.substr(comma + 1)); + } + else { + callArgs.push_back(argsRaw); } - } + + // Obsuga RDX (arg 2) + if (callArgs.size() > 1) { + std::string val = getVarLocation(callArgs[1], stackMap); + if (isNumber(val)) { + // Jeli liczba: mov rdx, 100 + result += " mov rdx, " + val + "\n"; + } + else { + // Jeli zmienna/pami: movsxd rdx, dword [rbp-8] + result += " movsxd rdx, dword " + val + "\n"; + } + } + + // Obsuga RCX (arg 1) + if (callArgs.size() > 0) { + std::string val = getVarLocation(callArgs[0], stackMap); + if (isNumber(val)) { + result += " mov rcx, " + val + "\n"; + } + else { + result += " movsxd rcx, dword " + val + "\n"; + } + } + + result += " call " + instr.arg1 + "\n"; + break; + } } } - result += " add rsp, 40\n"; - result += " ret\n\n"; - } -// ==main== - result += "main:\n"; - result += " sub rsp, 40\n"; - for (const std::string& call : state.printCalls) { - if (call.find("CALL_") == 0) { - std::string funcName = call.substr(5); - if (state.functions.count(funcName)) { - result += " call " + funcName + "\n"; - } + if (func.returnType == "void") { + result += " leave\n ret\n"; } + result += "\n"; } - 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"; - result += " mov ecx, 27\n"; - result += " call GetAsyncKeyState\n"; - result += " test ax, 8000h\n"; - result += " jz pause_loop\n"; - result += " add rsp, 40\n"; - result += " ret\n"; - return result; } diff --git a/PCCcompiler/compiler_types.h b/PCCcompiler/compiler_types.h index fdfd95c..907262d 100644 --- a/PCCcompiler/compiler_types.h +++ b/PCCcompiler/compiler_types.h @@ -6,28 +6,51 @@ #include #include -struct Expression { - std::string leftVar; - std::string op; - std::string rightVar; - std::string resultVar; +// Typy operacji, ktre nasz kompilator rozumie +enum class OpType { + ASSIGN, // a = 5 + ADD, // a = b + c + SUB, // a = b - c + MUL, // a = b * c + EQ, // a == b + PRINT, // print(a) + JMP_FALSE, // if (false) skocz... + JMP, // else / ptla + LABEL, // miejsce skoku + CALL, // wywoanie funkcji + RETURN, // return x + NOP // pusta instrukcja }; -struct IfBlock { - std::string conditionVar; - std::vector prints; +// Pojedynczy rozkaz kompilatora (Intermediate Representation) +struct Instruction { + OpType type; + std::string arg1; + std::string arg2; + std::string arg3; +}; + +// Definicja funkcji +struct Function { + std::string name; + std::string returnType; // "int", "void", "bool" + std::vector args; // Nazwy argumentw (np. "a", "b") + std::vector instructions; // Lista rozkazw w funkcji }; struct CompilerState { - std::vector expressions; - std::vector ifBlocks; - std::map variables; - std::vector printCalls; - std::vector globalPrints; - std::map> functions; - bool inFunction = false; - std::string currentFunction; - std::stack braceStack; + // Mapa wszystkich funkcji (klucz to nazwa) + std::map functions; + + // Zmienne globalne (tylko nazwa -> warto pocztkowa) + std::map globals; + + // Stan parsera + Function* currentFunction = nullptr; // Wskanik na aktualnie parsujc si funkcj + int labelCounter = 0; // Do generowania unikalnych nazw etykiet (L1, L2...) + std::stack loopStack; // Do break/continue (przyszociowo) + + std::stack blockStack; }; #endif diff --git a/PCCcompiler/parser.cpp b/PCCcompiler/parser.cpp index 99b2d8c..297145b 100644 --- a/PCCcompiler/parser.cpp +++ b/PCCcompiler/parser.cpp @@ -2,212 +2,171 @@ #include "utils.h" #include #include -#include "compiler_types.h" +#include + +std::vector parseArgs(const std::string& line) { + std::vector args; + size_t open = line.find('('); + size_t close = line.find(')'); + if (open == std::string::npos || close == std::string::npos) return args; + + std::string inside = line.substr(open + 1, close - open - 1); + if (inside.empty()) return args; + + std::stringstream ss(inside); + std::string segment; + while (std::getline(ss, segment, ',')) { + segment = trim(segment); + // segment to np. "int a". Szukamy ostatniej spacji, by wziąć nazwę "a" + size_t space = segment.find_last_of(" \t"); + if (space != std::string::npos) { + args.push_back(trim(segment.substr(space + 1))); + } + } + return args; +} void processSource(const std::string& src, CompilerState& state) { std::istringstream iss(src); std::string line; - std::cout << "Parsuje kod:\n"; - while (std::getline(iss, line)) { line = trim(line); - if (line.empty()) continue; + if (line.empty() || line.substr(0, 2) == "//" || line[0] == '#') continue; - // FUNKCJE - if (line.length() > 4 && line.substr(0, 4) == "void") { - size_t openParen = line.find("(", 4); - size_t closeParen = line.find(")", openParen); - if (openParen != std::string::npos && closeParen != std::string::npos) { - size_t nameStart = 4; - while (nameStart < openParen && (line[nameStart] == ' ' || line[nameStart] == '\t')) nameStart++; - size_t nameEnd = openParen; - while (nameEnd > nameStart && (line[nameEnd - 1] == ' ' || line[nameEnd - 1] == '\t')) nameEnd--; + // --- 1. DEFINICJA FUNKCJI --- + // Warunki: zaczyna się od typu, ma '(', ma '{' i NIE ma '=' (żeby nie mylić ze zmienną) + bool startsWithType = (line.rfind("int ", 0) == 0 || line.rfind("void ", 0) == 0 || line.rfind("bool ", 0) == 0); - // ZMIANA: używamy 'state' zamiast 'compilerState' - state.currentFunction = line.substr(nameStart, nameEnd - nameStart); - state.functions[state.currentFunction] = std::vector(); - state.inFunction = true; - std::cout << " FUNC " << state.currentFunction << "\n"; - state.braceStack.push(true); - continue; - } + if (startsWithType && line.find("(") != std::string::npos && line.find("{") != std::string::npos && line.find("=") == std::string::npos) { + + size_t openParen = line.find('('); + std::string typeRaw = line.substr(0, line.find(' ')); + std::string nameRaw = line.substr(typeRaw.length(), openParen - typeRaw.length()); + std::string funcName = trim(nameRaw); + + Function newFunc; + newFunc.name = funcName; + newFunc.returnType = typeRaw; + newFunc.args = parseArgs(line); + + state.functions[funcName] = newFunc; + state.currentFunction = &state.functions[funcName]; + + std::cout << "[PARSER] New Function: " << funcName << "\n"; + 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(); - // 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"; + // --- 2. ZAMYKANIE BLOKU '}' --- + if (line == "}") { + // Najpierw sprawdzamy, czy zamykamy IF-a (czy jest coś na stosie bloków) + if (!state.blockStack.empty()) { + std::string label = state.blockStack.top(); + state.blockStack.pop(); + if (state.currentFunction) { + state.currentFunction->instructions.push_back({ OpType::LABEL, label, "", "" }); } + std::cout << " [PARSER] } End IF block -> " << label << "\n"; + } + else { + // Jeśli stos pusty, to koniec funkcji + state.currentFunction = nullptr; + std::cout << " [PARSER] } End Function\n"; } continue; } - // INT - if (line.length() > 3 && line.substr(0, 3) == "int") { - size_t eqPos = line.find("=", 4); - if (eqPos != std::string::npos) { - size_t semiPos = line.find(";", eqPos); - if (semiPos != std::string::npos) { - std::string name = trim(line.substr(4, eqPos - 4)); - std::string rightSide = trim(line.substr(eqPos + 1, semiPos - eqPos - 1)); + // --- JESTEŚMY W ŚRODKU FUNKCJI --- + if (state.currentFunction) { + Function& f = *state.currentFunction; - std::string op; - size_t opPos; - - size_t eqPos2 = rightSide.find("=="); - if (eqPos2 != std::string::npos && (eqPos2 + 1 < rightSide.length()) && rightSide[eqPos2 + 2] != '=') { - op = "=="; - opPos = eqPos2; - } - else { - opPos = rightSide.find('+'); - if (opPos == std::string::npos) opPos = rightSide.find('-'); - if (opPos != std::string::npos) op = rightSide.substr(opPos, 1); - } - - if (opPos != std::string::npos && !op.empty()) { - std::string leftVar = trim(rightSide.substr(0, opPos)); - std::string rightVar = trim(rightSide.substr(opPos + op.length())); - - // ZMIANA: używamy 'state' - Expression expr{ leftVar, op, rightVar, name }; - state.expressions.push_back(expr); - state.variables[name] = 0; - std::cout << " " << op << " EXPR " << name << " = " << leftVar << " " << op << " " << rightVar << "\n"; - } - else { - try { - int value = std::stoi(rightSide); - state.variables[name] = value; - std::cout << " VAR " << name << " = " << value << "\n"; - } - catch (...) { - // Usunięto '❌' żeby uniknąć warningów o kodowaniu (C4566) - std::cout << " [X] BLAD: '" << rightSide << "'\n"; - } - } + // A. RETURN + if (line.substr(0, 6) == "return") { + std::string val = trim(line.substr(6)); + if (!val.empty() && val.back() == ';') val.pop_back(); + f.instructions.push_back({ OpType::RETURN, val, "", "" }); + std::cout << " [PARSER] Return: " << val << "\n"; + } + // B. PRINT + else if (line.substr(0, 5) == "print") { + size_t start = line.find('(') + 1; + size_t end = line.find(')'); + if (start != std::string::npos && end != std::string::npos) { + std::string var = trim(line.substr(start, end - start)); + f.instructions.push_back({ OpType::PRINT, var, "", "" }); } } - } - // BOOL - else if (!state.inFunction && line.length() > 4 && line.substr(0, 4) == "bool") { - size_t eqPos = line.find("=", 5); - if (eqPos != std::string::npos) { - size_t semiPos = line.find(";", eqPos); - if (semiPos != std::string::npos) { - std::string nameRaw = line.substr(5, eqPos - 5); - size_t nameStart = nameRaw.find_first_not_of(" \t"); - size_t nameEnd = nameRaw.find_last_not_of(" \t"); - std::string name = nameRaw.substr(nameStart, nameEnd - nameStart + 1); + // C. IF STATEMENT + else if (line.substr(0, 2) == "if") { + size_t openParen = line.find("("); + size_t closeParen = line.find(")"); + if (openParen != std::string::npos && closeParen > openParen) { + std::string condition = trim(line.substr(openParen + 1, closeParen - openParen - 1)); + std::string labelName = "L_" + std::to_string(state.labelCounter++); - std::string valueRaw = line.substr(eqPos + 1, semiPos - eqPos - 1); - size_t valStart = valueRaw.find_first_not_of(" \t"); - size_t valEnd = valueRaw.find_last_not_of(" \t"); - std::string valueStr = valueRaw.substr(valStart, valEnd - valStart + 1); + // Skok warunkowy + f.instructions.push_back({ OpType::JMP_FALSE, labelName, condition, "" }); + state.blockStack.push(labelName); - bool value = (valueStr == "true" || valueStr == "1"); - state.variables[name] = value ? 1 : 0; - std::cout << " BOOL '" << name << "' = " << (value ? "true" : "false") << "\n"; + std::cout << " [PARSER] IF (" << condition << ") -> Jump to " << labelName << "\n"; } } - } - // IF - else if (line.length() > 3 && line.substr(0, 2) == "if") { - size_t openParen = line.find("("); - size_t closeParen = line.find(")"); + // D. PRZYPISANIE ZMIENNEJ (LUB DEKLARACJA) + // np. "int a = 5;" LUB "a = b + c;" + else if (line.find("=") != std::string::npos) { + size_t eqPos = line.find('='); + std::string leftSide = trim(line.substr(0, eqPos)); + std::string rightSide = trim(line.substr(eqPos + 1)); + if (!rightSide.empty() && rightSide.back() == ';') rightSide.pop_back(); - if (openParen != std::string::npos && closeParen > openParen) { - std::string condition = trim(line.substr(openParen + 1, closeParen - openParen - 1)); + // Obsługa nazwy zmiennej (usuwanie "int ", "bool ") + std::string varName = leftSide; + if (leftSide.rfind("int ", 0) == 0) varName = trim(leftSide.substr(4)); + else if (leftSide.rfind("bool ", 0) == 0) varName = trim(leftSide.substr(5)); - IfBlock newIf; - newIf.conditionVar = condition; - state.ifBlocks.push_back(newIf); + // 1. Czy to wywołanie funkcji? int x = func(); + if (rightSide.find("(") != std::string::npos && rightSide.find(")") != std::string::npos) { + size_t open = rightSide.find('('); + std::string funcName = trim(rightSide.substr(0, open)); + std::string argsContent = rightSide.substr(open + 1, rightSide.find(')') - open - 1); - // 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)); + // CALL func + f.instructions.push_back({ OpType::CALL, funcName, argsContent, "" }); + // ASSIGN result (RAX) to variable + f.instructions.push_back({ OpType::ASSIGN, varName, "RAX", "" }); + std::cout << " [PARSER] Call & Assign: " << varName << " = " << funcName << "()\n"; } - - std::cout << " IF [" << condition << "] { <- blok #" << state.ifBlocks.size() - 1 << "\n"; - state.braceStack.push(false); // false oznacza, że to klamra IFa (a nie funkcji) - continue; - } - } - // PRINT - else if (line.length() > 5 && line.substr(0, 5) == "print") { - size_t openParen = line.find("(", 5); - size_t closeParen = line.rfind(")"); - if (openParen != std::string::npos && closeParen > openParen) { - 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()) { - // 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"; - } + // 2. Czy to dodawanie? a + b + else if (rightSide.find("+") != std::string::npos) { + size_t opPos = rightSide.find("+"); + std::string a = trim(rightSide.substr(0, opPos)); + std::string b = trim(rightSide.substr(opPos + 1)); + f.instructions.push_back({ OpType::ADD, varName, a, b }); + } + // 3. Czy to porównanie? a == b (Ważne: == może być w IFie, ale tu jesteśmy w linii z '=') + // UWAGA: To rzadkie w C++ (bool x = a == b), ale obsłużmy proste przypisanie wartości logicznej + else if (rightSide.find("==") != std::string::npos) { + size_t opPos = rightSide.find("=="); + std::string a = trim(rightSide.substr(0, opPos)); + std::string b = trim(rightSide.substr(opPos + 2)); + f.instructions.push_back({ OpType::EQ, varName, a, b }); + } + // 4. Zwykłe przypisanie: a = 5 + else { + f.instructions.push_back({ OpType::ASSIGN, varName, rightSide, "" }); } } - } - // WYWOLYWANIE FUNKCJI; - else if (line.length() > 3 && line.find("();") != std::string::npos) { - size_t openParen = line.find("("); - if (openParen != std::string::npos) { - std::string funcName = line.substr(0, openParen); - size_t nameStart = funcName.find_first_not_of(" \t"); - size_t nameEnd = funcName.find_last_not_of(" \t"); - funcName = funcName.substr(nameStart, nameEnd - nameStart + 1); + // E. SAMODZIELNE WYWOŁANIE FUNKCJI (bez =) + // np. func(); + else if (line.find("(") != std::string::npos && line.find(")") != std::string::npos) { + size_t open = line.find('('); + std::string funcName = trim(line.substr(0, open)); + std::string argsContent = line.substr(open + 1, line.find(')') - open - 1); - state.printCalls.push_back("CALL_" + funcName); // ZMIANA: state - std::cout << " CALL FUNC " << funcName << "\n"; + f.instructions.push_back({ OpType::CALL, funcName, argsContent, "" }); + std::cout << " [PARSER] Call void: " << funcName << "\n"; } } } } - -void calculateExpressions(CompilerState& state) { - for (const auto& expr : state.expressions) { - if (state.variables.count(expr.leftVar) && state.variables.count(expr.rightVar)) { - int left = state.variables[expr.leftVar]; - int right = state.variables[expr.rightVar]; - int result = 0; - if (expr.op == "+") result = left + right; - else if (expr.op == "==") result = (left == right); - state.variables[expr.resultVar] = result; - } - } -} +void calculateExpressions(CompilerState& state) {}