ELSE update

This commit is contained in:
mmichlol
2026-02-09 20:46:14 +01:00
parent 0dff8628ac
commit 1eb29c430a
4 changed files with 199 additions and 112 deletions

View File

@@ -350,27 +350,24 @@ std::string generateAssembly(const CompilerState& state) {
case OpType::PRINT: { case OpType::PRINT: {
// Instrukcja PRINT zwyk³a (liczba) // Instrukcja PRINT zwyk³a (liczba)
std::string val = getVarLocation(instr.arg1, stackMap); std::string val = getVarLocation(instr.arg1, stackMap);
result += " mov edx, " + val + "\\n"; result += " mov edx, " + val + "\n";
result += " lea rcx, [rel fmt_int]\\n"; result += " lea rcx, [rel fmt_int]\n";
result += " xor eax, eax\\n"; // <-- DODAJ TO result += " xor eax, eax\n";
result += " call printf\\n"; result += " call printf\n";
break; break;
} }
case OpType::PRINT_STRING: { case OpType::PRINT_STRING: {
// Instrukcja PRINT_STRING (tekst)
std::string target = instr.arg1; std::string target = instr.arg1;
if (target.find("str_") == 0) { if (target.rfind("str_", 0) == 0) {
// Litera³: print("tekst") result += " lea rdx, [rel " + target + "]\n";
result += " lea rdx, [rel " + target + "]\\n";
} }
else { else {
// Zmienna: print(s) -> s trzyma adres
std::string val = getVarLocation(target, stackMap); std::string val = getVarLocation(target, stackMap);
result += " mov rdx, " + val + "\\n"; result += " mov rdx, " + val + "\n";
} }
result += " lea rcx, [rel fmt_str]\\n"; result += " lea rcx, [rel fmt_str]\n";
result += " xor eax, eax\\n"; // <-- DODAJ TO result += " xor eax, eax\n";
result += " call printf\\n"; result += " call printf\n";
break; break;
} }
case OpType::CALL: { case OpType::CALL: {

View File

@@ -40,12 +40,29 @@ std::string registerStringLiteral(CompilerState& state, std::string content) {
void processSource(const std::string& src, CompilerState& state) { void processSource(const std::string& src, CompilerState& state) {
std::istringstream iss(src); std::istringstream iss(src);
std::string line; std::vector<std::string> lines;
{
std::istringstream iss(src);
std::string t;
while (std::getline(iss, t)) lines.push_back(trim(t));
}
while (std::getline(iss, line)) { for (size_t i = 0; i < lines.size(); i++) {
line = trim(line); std::string line = trim(lines[i]);
if (line.empty() || line.substr(0, 2) == "//" || line[0] == '#') continue; if (line.empty() || line.substr(0, 2) == "//" || line[0] == '#') continue;
if (line.find("} else") != std::string::npos) {
// najpierw obsłuż zamknięcie bloku
std::string saved = line;
line = "}";
// ... uruchom kod obsługi "}" (najlepiej przenieś go do funkcji pomocniczej)
// potem obsłuż else:
line = "else";
// ... uruchom kod obsługi else
continue;
}
// ========================================================= // =========================================================
// 1. DEFINICJA FUNKCJI (np. void main() { ) // 1. DEFINICJA FUNKCJI (np. void main() { )
// ========================================================= // =========================================================
@@ -72,41 +89,78 @@ void processSource(const std::string& src, CompilerState& state) {
// ========================================================= // =========================================================
// 2. ZAMYKANIE BLOKU '}' (Koniec funkcji, IFa lub WHILEa) // 2. ZAMYKANIE BLOKU '}' (Koniec funkcji, IFa lub WHILEa)
// ========================================================= // =========================================================
if (!line.empty() && line.back() == '}') { if (line == "}") {
// lookahead: czy następna sensowna linia to "else" / "else {"
bool nextIsElse = false;
size_t j = i + 1;
while (j < lines.size()) {
std::string nl = trim(lines[j]);
if (nl.empty() || nl.rfind("//", 0) == 0) { j++; continue; }
if (nl.rfind("else", 0) == 0) nextIsElse = true;
break;
}
if (!state.blockStack.empty()) { if (!state.blockStack.empty()) {
std::string blockInfo = state.blockStack.top(); std::string blockInfo = state.blockStack.top();
// --- WHILE ---
if (blockInfo.rfind("WHILE|", 0) == 0) {
state.blockStack.pop(); state.blockStack.pop();
bool isWhile = (blockInfo.length() > 6 && blockInfo.substr(0, 6) == "WHILE|"); size_t p1 = blockInfo.find('|');
size_t p2 = blockInfo.rfind('|');
if (isWhile) { std::string labelStart = blockInfo.substr(p1 + 1, p2 - p1 - 1);
size_t firstPipe = blockInfo.find('|'); std::string labelEnd = blockInfo.substr(p2 + 1);
size_t secondPipe = blockInfo.rfind('|');
std::string labelStart = blockInfo.substr(firstPipe + 1, secondPipe - firstPipe - 1);
std::string labelEnd = blockInfo.substr(secondPipe + 1);
if (state.currentFunction) { if (state.currentFunction) {
state.currentFunction->instructions.push_back({ OpType::JMP, labelStart, "", "" }); state.currentFunction->instructions.push_back({ OpType::JMP, labelStart, "", "" });
state.currentFunction->instructions.push_back({ OpType::LABEL, labelEnd, "", "" }); state.currentFunction->instructions.push_back({ OpType::LABEL, labelEnd, "", "" });
} }
std::cout << " [PARSER] } End WHILE loop\n"; continue;
} }
else {
// To zwykły blok (if lub else) // --- IF (specjalny wpis IF|else|end) ---
if (blockInfo.rfind("IF|", 0) == 0) {
state.blockStack.pop();
size_t p1 = blockInfo.find('|');
size_t p2 = blockInfo.rfind('|');
std::string labelElse = blockInfo.substr(p1 + 1, p2 - p1 - 1);
std::string labelEnd = blockInfo.substr(p2 + 1);
if (nextIsElse) {
// zamykamy blok IF, ale zaraz będzie ELSE:
// 1) przeskocz ELSE po wykonaniu IF
// 2) wstaw początek ELSE
if (state.currentFunction) { if (state.currentFunction) {
state.currentFunction->instructions.push_back({ OpType::LABEL, blockInfo, "", "" }); state.currentFunction->instructions.push_back({ OpType::JMP, labelEnd, "", "" });
} state.currentFunction->instructions.push_back({ OpType::LABEL, labelElse, "", "" });
std::cout << " [PARSER] } End block -> " << blockInfo << "\n";
} }
// Teraz oczekujemy na '}' kończące ELSE -> ma wstawić LABEL labelEnd
state.blockStack.push(labelEnd);
} }
else { else {
// Koniec funkcji // if bez else: labelElse jest po prostu "koniec if"
state.currentFunction = nullptr; if (state.currentFunction) {
std::cout << " [PARSER] } End Function\n"; state.currentFunction->instructions.push_back({ OpType::LABEL, labelElse, "", "" });
}
} }
continue; continue;
} }
// --- zwykły LABEL na stosie (np. koniec ELSE: labelEnd) ---
state.blockStack.pop();
if (state.currentFunction) {
state.currentFunction->instructions.push_back({ OpType::LABEL, blockInfo, "", "" });
}
continue;
}
// jeśli stos pusty -> zamykamy funkcję
state.currentFunction = nullptr;
continue;
}
// ========================================================= // =========================================================
// JESTEŚMY W ŚRODKU FUNKCJI // JESTEŚMY W ŚRODKU FUNKCJI
@@ -193,29 +247,21 @@ void processSource(const std::string& src, CompilerState& state) {
} }
// E. IF STATEMENT (z ulepszoną obsługą else) // E. IF STATEMENT (z ulepszoną obsługą else)
else if (line.substr(0, 2) == "if") { else if (line.rfind("if", 0) == 0) {
size_t openParen = line.find("("); size_t openParen = line.find("(");
size_t closeParen = line.rfind(")"); size_t closeParen = line.rfind(")");
if (openParen != std::string::npos && closeParen > openParen) { if (openParen != std::string::npos && closeParen > openParen) {
std::string conditionRaw = trim(line.substr(openParen + 1, closeParen - openParen - 1)); std::string conditionRaw = trim(line.substr(openParen + 1, closeParen - openParen - 1));
std::string finalConditionVar = conditionRaw;
// Obsługa prostych operacji w warunku std::string labelElse = "L_" + std::to_string(state.labelCounter++);
if (conditionRaw.find("==") != std::string::npos) { std::string labelEnd = "L_" + std::to_string(state.labelCounter++);
size_t eq = conditionRaw.find("=="); f.instructions.push_back({ OpType::JMP_FALSE, labelElse, conditionRaw, "" });
std::string tempRes = "_tmp_eq_" + std::to_string(state.labelCounter++); state.blockStack.push("IF|" + labelElse + "|" + labelEnd);
f.instructions.push_back({ OpType::EQ, tempRes, trim(conditionRaw.substr(0, eq)), trim(conditionRaw.substr(eq + 2)) });
finalConditionVar = tempRes;
}
std::string labelFalse = "L_" + std::to_string(state.labelCounter++);
f.instructions.push_back({ OpType::JMP_FALSE, labelFalse, finalConditionVar, "" });
state.blockStack.push(labelFalse);
} }
continue; continue;
} }
// F. WHILE LOOP // F. WHILE LOOP
else if (line.substr(0, 5) == "while") { else if (line.substr(0, 5) == "while") {
size_t openParen = line.find("("); size_t openParen = line.find("(");
@@ -285,19 +331,7 @@ void processSource(const std::string& src, CompilerState& state) {
continue; continue;
} }
else if (line.substr(0, 4) == "else") { else if (line.rfind("else", 0) == 0) {
if (!state.blockStack.empty()) {
std::string labelFalse = state.blockStack.top();
state.blockStack.pop();
// Po bloku `if` skocz do końca `ifelse`:
std::string labelEnd = "L_" + std::to_string(state.labelCounter++);
f.instructions.push_back({ OpType::JMP, labelEnd, "", "" });
f.instructions.push_back({ OpType::LABEL, labelFalse, "", "" }); // początek ELSE
state.blockStack.push(labelEnd);
std::cout << " [PARSER] else block\n";
}
continue; continue;
} }

View File

@@ -3,13 +3,18 @@
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <filesystem> #include <filesystem>
#include <regex> #include <unordered_set>
namespace fs = std::filesystem; namespace fs = std::filesystem;
// Funkcja pomocnicza do wczytania pliku static std::string ltrim(std::string s) {
std::string loadFileContent(const std::string& path) { const size_t first = s.find_first_not_of(" \t");
std::ifstream in(path); if (first == std::string::npos) return "";
return s.substr(first);
}
static std::string loadFileContent(const std::string& path) {
std::ifstream in(path, std::ios::binary);
if (!in) { if (!in) {
std::cerr << "[PREPROCESSOR] Error: Could not open included file: " << path << "\n"; std::cerr << "[PREPROCESSOR] Error: Could not open included file: " << path << "\n";
return ""; return "";
@@ -17,63 +22,109 @@ std::string loadFileContent(const std::string& path) {
return std::string((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); return std::string((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
} }
std::string preprocessSource(const std::string& src, const std::string& projectDir, const std::string& compilerDir) { // Próbuje sparsowaæ #include "x" albo #include <x>
// Zwraca: true jeœli linia to include i uda³o siê wyci¹gn¹æ œcie¿kê.
static bool parseIncludeLine(const std::string& line, std::string& includePath, bool& isStdLib) {
includePath.clear();
isStdLib = false;
std::string t = ltrim(line);
if (t.rfind("#include", 0) != 0) return false;
const size_t openQuote = t.find('"');
const size_t closeQuote = t.rfind('"');
const size_t openAngle = t.find('<');
const size_t closeAngle = t.rfind('>');
if (openQuote != std::string::npos && closeQuote != std::string::npos && closeQuote > openQuote) {
includePath = t.substr(openQuote + 1, closeQuote - openQuote - 1);
isStdLib = false;
return true;
}
if (openAngle != std::string::npos && closeAngle != std::string::npos && closeAngle > openAngle) {
includePath = t.substr(openAngle + 1, closeAngle - openAngle - 1);
isStdLib = true;
return true;
}
// To jest #include ale w z³ym formacie (np. brak cudzys³owu / nawiasów)
return true;
}
// Wewnêtrzna funkcja z guardem na rekurencjê.
static std::string preprocessSourceImpl(
const std::string& src,
const std::string& projectDir,
const std::string& compilerDir,
std::unordered_set<std::string>& includeGuard
) {
std::istringstream iss(src); std::istringstream iss(src);
std::string line; std::string line;
std::stringstream output; std::stringstream output;
while (std::getline(iss, line)) { while (std::getline(iss, line)) {
// Szukamy: #include "..." lub #include <...>
// U¿ywamy prostego find, ¿eby by³o szybko
std::string trimLine = line;
// Usuwamy bia³e znaki z pocz¹tku
size_t first = trimLine.find_first_not_of(" \t");
if (first != std::string::npos) trimLine = trimLine.substr(first);
if (trimLine.rfind("#include", 0) == 0) {
// Mamy include!
size_t openQuote = trimLine.find('"');
size_t closeQuote = trimLine.rfind('"');
size_t openAngle = trimLine.find('<');
size_t closeAngle = trimLine.rfind('>');
std::string includePath; std::string includePath;
bool isStdLib = false; bool isStdLib = false;
// Wersja: #include "plik.pcc" const bool isIncludeLine = parseIncludeLine(line, includePath, isStdLib);
if (openQuote != std::string::npos && closeQuote > openQuote) {
includePath = trimLine.substr(openQuote + 1, closeQuote - openQuote - 1); if (!isIncludeLine) {
} output << line << "\n";
// Wersja: #include <plik.pcc> continue;
else if (openAngle != std::string::npos && closeAngle > openAngle) {
includePath = trimLine.substr(openAngle + 1, closeAngle - openAngle - 1);
isStdLib = true;
} }
if (!includePath.empty()) { if (includePath.empty()) {
std::string fullPath; output << "\n// [PREPROCESSOR] Invalid include (no path): " << line << "\n";
continue;
}
// Z³ó¿ fullPath
fs::path fullPath;
if (isStdLib) { if (isStdLib) {
fullPath = compilerDir + "/std/" + includePath; fullPath = fs::path(compilerDir) / "std" / includePath;
std::cout << "[PREPROCESSOR] Including STD lib: " << fullPath << "\n"; std::cout << "[PREPROCESSOR] Including STD lib: " << fullPath.string() << "\n";
} }
else { else {
// Plik lokalny: Szukamy w folderze projektu if (projectDir.empty()) fullPath = fs::path(includePath);
if (projectDir.empty()) fullPath = includePath; else fullPath = fs::path(projectDir) / includePath;
else fullPath = projectDir + "/" + includePath; std::cout << "[PREPROCESSOR] Including local file: " << fullPath.string() << "\n";
std::cout << "[PREPROCESSOR] Including local file: " << fullPath << "\n";
} }
std::string content = loadFileContent(fullPath);
std::string processedContent = preprocessSource(content, projectDir, compilerDir); // Normalizacja œcie¿ki (jeœli siê da)
std::string guardKey;
try {
guardKey = fs::weakly_canonical(fullPath).string();
}
catch (...) {
guardKey = fullPath.lexically_normal().string();
}
// Guard przeciw include-loop oraz wielokrotnemu includowaniu
if (includeGuard.find(guardKey) != includeGuard.end()) {
output << "\n// [PREPROCESSOR] Skipped include (already included): " << includePath << "\n";
continue;
}
includeGuard.insert(guardKey);
// Wczytaj + przetwórz rekurencyjnie
std::string content = loadFileContent(fullPath.string());
if (content.empty()) {
output << "\n// [PREPROCESSOR] FAILED INCLUDE: " << includePath << "\n";
continue;
}
std::string processedContent = preprocessSourceImpl(content, projectDir, compilerDir, includeGuard);
output << "\n// --- BEGIN INCLUDE: " << includePath << " ---\n"; output << "\n// --- BEGIN INCLUDE: " << includePath << " ---\n";
output << processedContent; output << processedContent;
output << "\n// --- END INCLUDE ---\n"; output << "\n// --- END INCLUDE ---\n";
} }
}
else {
output << line << "\n";
}
}
return output.str(); return output.str();
} }
std::string preprocessSource(const std::string& src, const std::string& projectDir, const std::string& compilerDir) {
std::unordered_set<std::string> includeGuard;
return preprocessSourceImpl(src, projectDir, compilerDir, includeGuard);
}

View File

@@ -2,7 +2,12 @@
#define PREPROCESSOR_H #define PREPROCESSOR_H
#include <string> #include <string>
std::string preprocessSource(const std::string& src, const std::string& projectDir, const std::string& compilerDir); std::string preprocessSource(
const std::string& src,
const std::string& projectDir,
const std::string& compilerDir
);
#endif #endif