From 3895272a7f238c9aef0b584bd3b10b900445245d Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Tue, 15 Apr 2025 19:45:02 +0000
Subject: [PATCH] refactored

---
 src/Lexer/Token.hpp                    |   37 +
 src/Symbols/SymbolFactory.hpp          |   24 
 CMakeLists.txt                         |    6 
 src/Symbols/ConstantSymbol.hpp         |    0 
 src/Symbols/SymbolKind.hpp             |    0 
 src/Symbols/SymbolTypes.hpp            |    0 
 src/Symbols/ValueContainer.hpp         |   12 
 src/Symbols/Value.hpp                  |   77 ++
 src/Symbols/BaseSymbol.hpp             |    4 
 src/VoidScript.hpp                     |   89 +++
 src/Interpreter/OperationContainer.hpp |   12 
 src/Interpreter/Operation.hpp          |   31 +
 src/Parser/Parser.cpp                  |   37 +
 src/Symbols/VariableTypes.hpp          |   48 +
 src/Lexer/Lexer.hpp                    |  316 +++++++++++
 src/Parser/Parser.hpp                  |  536 +++++++++++++++++++
 src/Lexer/Lexer.cpp                    |   14 
 src/Interpreter/ExpressionNode.hpp     |   17 
 src/Interpreter/Interpreter.hpp        |   49 +
 src/Builtins/BaseFunction.hpp          |    0 
 cli/main.cpp                           |   25 
 /dev/null                              |  120 ----
 src/Symbols/FunctionSymbol.hpp         |   41 +
 src/Symbols/ParameterContainer.hpp     |   17 
 src/Symbols/VariableSymbol.hpp         |   45 +
 src/Lexer/TokenType.hpp                |   87 +++
 src/Symbols/SymbolTable.hpp            |    1 
 src/Symbols/SymbolContainer.hpp        |    0 
 28 files changed, 1,492 insertions(+), 153 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 013b4c9..b9e1780 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -113,13 +113,13 @@
 configure_file("test_scripts/test1.vs" "test_scripts/test1.vs" @ONLY)
 configure_file("test_scripts/test2.vs" "test_scripts/test2.vs" @ONLY)
 
-include_directories(${CMAKE_BINARY_DIR}/include ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/include)
+include_directories(${CMAKE_BINARY_DIR}/include ${CMAKE_SOURCE_DIR}/src)
 
 
 # LIBRARY TARGET
 add_library(voidscript
-            src/ScriptInterpreter.cpp
-            src/Lexer.cpp
+            src/Parser/Parser.cpp
+            src/Lexer/Lexer.cpp
 )
 
 install(TARGETS voidscript DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT "lib")
diff --git a/cli/main.cpp b/cli/main.cpp
index a20c2bc..ca6c810 100644
--- a/cli/main.cpp
+++ b/cli/main.cpp
@@ -1,9 +1,10 @@
 #include <filesystem>
 #include <fstream>
+#include <iostream>
+#include <unordered_map>
 
-#include "Builtins/PrintModule.hpp"
-#include "Builtins/SleepModule.hpp"
-#include "ScriptInterpreter.hpp"
+#include "options.h"
+#include "VoidScript.hpp"
 
 const std::unordered_map<std::string, std::string> params = {
     { "--help",    "Print this help message"          },
@@ -55,22 +56,8 @@
 
     const std::string filename = std::filesystem::canonical(file).string();
 
-    try {
-        std::ifstream input(filename);
-        if (!input.is_open()) {
-            std::cerr << "Error: Could not open file " << filename << "\n";
-            return 1;
-        }
-
-        std::string       content((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
-        ScriptInterpreter interp;
-        interp.registerModule("print", std::make_shared<PrintFunction>());
-        interp.registerModule("sleep", std::make_shared<SleepFunction>());
-        interp.executeScript(content, filename, "DEFAULT", false);
-    } catch (const std::exception & e) {
-        std::cerr << "Parser error: " << e.what() << "\n";
-        return 1;
-    }
+    VoidScript voidscript(filename);
+    return voidscript.run();
 
     return 0;
 }
diff --git a/include/FunctionSymbol.hpp b/include/FunctionSymbol.hpp
deleted file mode 100644
index 97c23f8..0000000
--- a/include/FunctionSymbol.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// FunctionSymbol.hpp
-#ifndef FUNCTION_SYMBOL_HPP
-#define FUNCTION_SYMBOL_HPP
-
-#include <vector>
-
-#include "BaseSymbol.hpp"
-
-namespace Symbols {
-using ValueContainer = std::vector<Symbols::Value>;
-
-class FunctionSymbol : public Symbol {
-    std::vector<Symbols::Value> parameters_;
-    Symbols::Value              returnType_;
-    std::string                 plainBody_;
-
-  public:
-    FunctionSymbol(const std::string & name, const std::string & context, const ValueContainer & parameters,
-                   const std::string & plainbody = "") :
-        Symbol(name, {}, context, Symbols::Kind::Function),
-        parameters_(parameters),
-        plainBody_(plainbody) {}
-
-    Symbols::Kind kind() const override { return Symbols::Kind::Function; }
-
-    const ValueContainer & parameters() const { return parameters_; }
-};
-
-}  // namespace Symbols
-
-#endif
diff --git a/include/VariableSymbol.hpp b/include/VariableSymbol.hpp
deleted file mode 100644
index 652565e..0000000
--- a/include/VariableSymbol.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// VariableSymbol.hpp
-#ifndef VARIABLE_SYMBOL_HPP
-#define VARIABLE_SYMBOL_HPP
-
-#include "BaseSymbol.hpp"
-
-namespace Symbols {
-
-class VariableSymbol : public Symbol {
-  public:
-    VariableSymbol(const std::string & name, const Symbols::Value & value, const std::string & context,
-                   Symbols::Kind type) :
-        Symbol(name, value, context, type) {}
-
-    Symbols::Kind kind() const override { return Symbols::Kind::Variable; }
-};
-
-}  // namespace Symbols
-
-#endif
diff --git a/include/VariableTypes.hpp b/include/VariableTypes.hpp
deleted file mode 100644
index 8ac087d..0000000
--- a/include/VariableTypes.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef VARIABLE_TYPES_HPP
-#define VARIABLE_TYPES_HPP
-
-#include <cstdint>
-#include <string>
-#include <unordered_map>
-
-namespace Symbols::Variables {
-
-enum class Type : std::uint8_t { VT_INT, VT_DOUBLE, VT_STRING, VT_BOOLEAN, VT_NULL, VT_UNDEFINED };
-
-const std::unordered_map<std::string, Type> StringToTypeMap = {
-    { "int",       Type::VT_INT       },
-    { "double",    Type::VT_DOUBLE    },
-    { "string",    Type::VT_STRING    },
-    { "bool",      Type::VT_BOOLEAN   },
-    { "boolean",   Type::VT_BOOLEAN   },
-    { "null",      Type::VT_NULL      },
-
-    { "undefined", Type::VT_UNDEFINED },
-};
-const std::unordered_map<Type, std::string> StypeToStringMap = {
-    { Type::VT_INT,       "int"        },
-    { Type::VT_DOUBLE,    "double"     },
-    { Type::VT_STRING,    "string"     },
-    { Type::VT_BOOLEAN,   "bool"       },
-    { Type::VT_NULL,      "null"       },
-    { Type::VT_UNDEFINED, "undeffined" },
-};
-
-inline static std::string TypeToString(Type type) {
-    if (StypeToStringMap.find(type) != StypeToStringMap.end()) {
-        return StypeToStringMap.at(type);
-    }
-    return "null";
-};
-
-inline static Type StringToType(const std::string & type) {
-    if (StringToTypeMap.find(type) != StringToTypeMap.end()) {
-        return StringToTypeMap.at(type);
-    }
-    return Type::VT_NULL;
-};
-
-};  // namespace Symbols
-#endif  // VARIABLE_TYPES_HPP
diff --git a/include/BaseFunction.hpp b/src/Builtins/BaseFunction.hpp
similarity index 100%
rename from include/BaseFunction.hpp
rename to src/Builtins/BaseFunction.hpp
diff --git a/src/Interpreter/ExpressionNode.hpp b/src/Interpreter/ExpressionNode.hpp
new file mode 100644
index 0000000..b3853e3
--- /dev/null
+++ b/src/Interpreter/ExpressionNode.hpp
@@ -0,0 +1,17 @@
+#ifndef INTERPRETER_FUNCTION_EXECUTOR_HPP
+#define INTERPRETER_FUNCTION_EXECUTOR_HPP
+
+namespace Interpreter {
+struct StatementNode {
+    virtual ~StatementNode()                                      = default;
+    virtual void interpret(class Interpreter & interpreter) const = 0;
+};
+
+// Kifejezés (csak int literál most)
+struct ExpressionNode {
+    virtual ~ExpressionNode()                                   = default;
+    virtual int evaluate(class Interpreter & interpreter) const = 0;
+};
+
+}  // namespace Interpreter
+#endif  // INTERPRETER_FUNCTION_EXECUTOR_HPP
diff --git a/src/Interpreter/Interpreter.hpp b/src/Interpreter/Interpreter.hpp
new file mode 100644
index 0000000..84d725b
--- /dev/null
+++ b/src/Interpreter/Interpreter.hpp
@@ -0,0 +1,49 @@
+#ifndef INTERPRETER_HPP
+#define INTERPRETER_HPP
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "Interpreter/Operation.hpp"
+#include "Interpreter/OperationContainer.hpp"
+#include "Symbols/SymbolContainer.hpp"
+
+namespace Interpreter {
+
+class Interpreter {
+  private:
+    std::shared_ptr<Symbols::SymbolContainer> symbol_container_;
+    const OperationContainer &                operations_conatiner_;
+
+    void setVariable(const std::string & name, int value) {
+        //symbol_container_->setVariable(name, value);
+    }
+  public:
+    // Constructor takes the populated symbol container from the parser
+    Interpreter(std::shared_ptr<Symbols::SymbolContainer> symbols, const OperationContainer & operations) :
+        symbol_container_(std::move(symbols)),
+        operations_conatiner_(operations) {}
+
+    void run(const std::vector<Operation> & ops) {
+        for (const auto & op : ops) {
+            switch (op.type) {
+                case OperationType::Assignment:
+                    {
+                        int value = op.expression->evaluate(*this);
+                        setVariable(op.targetVariable, value);
+                        break;
+                    }
+
+                case OperationType::Expression:
+                    {
+                        op.expression->evaluate(*this);  // csak side effect miatt
+                        break;
+                    }
+            }
+        }
+    }
+
+};  // class Interpreter
+
+}  // namespace Interpreter
+#endif  // INTERPRETER_HPP
diff --git a/src/Interpreter/Operation.hpp b/src/Interpreter/Operation.hpp
new file mode 100644
index 0000000..ecbae0b
--- /dev/null
+++ b/src/Interpreter/Operation.hpp
@@ -0,0 +1,31 @@
+#ifndef INTERPRETER_OPERATION_HPP
+#define INTERPRETER_OPERATION_HPP
+
+#include <cstdint>
+
+#include <memory>
+#include <string>
+
+#include "ExpressionNode.hpp"
+
+namespace Interpreter {
+enum OperationType : std::uint8_t {
+    Assignment,
+    Expression,
+
+};
+
+struct Operation {
+    OperationType type;
+
+    // Általános mezők
+    std::string targetVariable;
+    std::unique_ptr<ExpressionNode> expression;
+
+    Operation(OperationType t, std::string var, std::unique_ptr<ExpressionNode> expr)
+        : type(t), targetVariable(std::move(var)), expression(std::move(expr)) {}
+};
+
+
+};  // namespace Interpreter
+#endif
diff --git a/src/Interpreter/OperationContainer.hpp b/src/Interpreter/OperationContainer.hpp
new file mode 100644
index 0000000..62b5c1d
--- /dev/null
+++ b/src/Interpreter/OperationContainer.hpp
@@ -0,0 +1,12 @@
+#ifndef INTERPRETER_OPERATION_CONTAINER_HPP
+#define INTERPRETER_OPERATION_CONTAINER_HPP
+
+#include <vector>
+
+#include "Interpreter/Operation.hpp"
+
+namespace Interpreter {
+using OperationContainer = std::vector<Operation>;
+};  // namespace Interpreter
+
+#endif  // INTERPRETER_OPERATION_CONTAINER_HPP
diff --git a/src/Lexer.cpp b/src/Lexer.cpp
deleted file mode 100644
index 362e4b8..0000000
--- a/src/Lexer.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-#include "Lexer.hpp"
-
-#include <cctype>
-
-#include "options.h"
-
-Lexer::Lexer(const std::string & source, const std::string & filename) :
-    src(source),
-    pos(0),
-    filename(filename),
-    lineNumber(1),
-    colNumber(1),
-    charNumber(0) {}
-
-/**
- * Peek at the current character without advancing the lexer's position.
- *
- * @return The current character, or '\0' if at the end of the source.
- */
-char Lexer::peek() const {
-    return pos < src.size() ? src[pos] : '\0';
-}
-
-char Lexer::advance() {
-    if (pos >= src.size()) {
-        return '\0';
-    }
-    char c = src[pos++];
-    if (c == '\n') {
-        this->lineNumber++;
-        this->colNumber = 1;
-    } else {
-        this->colNumber++;
-    }
-    this->charNumber++;
-    return c;
-}
-
-bool Lexer::isAtEnd() const {
-    return pos >= src.size();
-}
-
-Tokens::Token Lexer::createToken(Tokens::Type type, const std::string & lexeme) const {
-    size_t startChar = charNumber - lexeme.length();
-    return {
-        type, lexeme, filename, lineNumber, colNumber - lexeme.length(), { startChar, charNumber }
-    };
-}
-
-Tokens::Token Lexer::createSingleCharToken(Tokens::Type type, const std::string & lexeme) {
-    size_t startCol  = colNumber;
-    size_t startChar = charNumber;
-    advance();
-    return {
-        type, lexeme, filename, lineNumber, startCol, { startChar, charNumber }
-    };
-}
-
-Tokens::Token Lexer::createUnknownToken(const std::string & lexeme) const {
-    size_t startChar = charNumber - lexeme.length();
-    return {
-        Tokens::Type::Unknown, lexeme, filename, lineNumber, colNumber - lexeme.length(), { startChar, charNumber }
-    };
-}
-
-Tokens::Token Lexer::stringToken() {
-    std::string result;
-    size_t      startChar = charNumber;
-    size_t      startCol  = colNumber;
-    advance();  // Skip opening quote
-    while (!isAtEnd() && peek() != '"') {
-        result += advance();
-    }
-    if (isAtEnd() || peek() != '"') {
-        return {
-            Tokens::Type::Unknown, "Unterminated string", filename, lineNumber, startCol, { startChar, pos }
-        };
-    }
-    advance();  // Skip closing quote
-    return {
-        Tokens::Type::StringLiteral, result, filename, lineNumber, startCol, { startChar, pos }
-    };
-}
-
-Tokens::Token Lexer::numberToken() {
-    std::string  result;
-    std::string  found;
-    Tokens::Type type             = Tokens::Type::Unknown;
-    bool         decimalPointSeen = false;
-    size_t       startChar        = charNumber;
-    size_t       startCol         = colNumber;
-
-    while (std::isdigit(peek()) || peek() == '.') {
-        if (peek() == '.') {
-            if (decimalPointSeen) {
-                return {
-                    Tokens::Type::Unknown, "Invalid number format", filename, lineNumber, startCol, { startChar, pos }
-                };
-            }
-            decimalPointSeen = true;
-        }
-        found.append(1, advance());
-    }
-
-    if (!found.empty()) {
-        if (found.find('.') == std::string::npos) {
-            if (is_number<int>(found)) {
-                result = found;
-                type   = Tokens::Type::IntLiteral;
-            } else {
-                return {
-                    Tokens::Type::Unknown, "Invalid integer", filename, lineNumber, startCol, { startChar, pos }
-                };
-            }
-        } else {
-            if (is_number<double>(found)) {
-                result = found;
-                type   = Tokens::Type::DoubleLiteral;
-            } else {
-                return {
-                    Tokens::Type::Unknown, "Invalid double", filename, lineNumber, startCol, { startChar, pos }
-                };
-            }
-        }
-    } else {
-        return {
-            Tokens::Type::Unknown, "Expected number", filename, lineNumber, startCol, { startChar, pos }
-        };
-    }
-
-    return {
-        type, result, filename, lineNumber, startCol, { startChar, pos }
-    };
-}
-
-Tokens::Token Lexer::identifierToken() {
-    std::string result;
-    size_t      startChar = charNumber;
-    size_t      startCol  = colNumber;
-    while (isalnum(peek()) || peek() == '_') {
-        result += advance();
-    }
-    return {
-        Tokens::Type::Identifier, result, filename, lineNumber, startCol, { startChar, pos }
-    };
-}
-
-Tokens::Token Lexer::variableToken() {
-    size_t startChar = charNumber;
-    size_t startCol  = colNumber;
-    advance();  // Skip $
-    std::string varName;
-    if (isalpha(peek()) || peek() == '_') {
-        varName += advance();
-        while (isalnum(peek()) || peek() == '_') {
-            varName += advance();
-        }
-        return {
-            Tokens::Type::Variable, varName, filename, lineNumber, startCol, { startChar, pos }
-        };
-    }
-    return {
-        Tokens::Type::Unknown, "$ followed by invalid character", filename, lineNumber, startCol, { startChar, pos }
-    };
-}
-
-Tokens::Token Lexer::commentToken() {
-    size_t startChar = charNumber;
-    size_t startCol  = colNumber;
-    advance();  // Skip #
-    std::string commentText;
-    while (!isAtEnd() && peek() != '\n') {
-        commentText += advance();
-    }
-    return {
-        Tokens::Type::Comment, commentText, filename, lineNumber, startCol, { startChar, pos }
-    };
-}
-
-Tokens::Token Lexer::keywordOrIdentifierToken() {
-    std::string lexeme;
-    while (isalpha(peek())) {
-        lexeme += advance();
-    }
-    if (lexeme == IDENTIFIER_FUNCTION) {
-        return this->functionDeclarationToken();
-    }
-
-    if (lexeme == IDENTIFIER_RETURN) {
-        return createToken(Tokens::Type::Return, lexeme);
-    }
-    if (lexeme == IDENTIFIER_IF) {
-        return createToken(Tokens::Type::ParserIfStatement, lexeme);
-    }
-
-    if (peek() == '(') {  // Function call
-        return createToken(Tokens::Type::FunctionCall, lexeme);
-    }
-
-    auto it = Variables::StringToTypeMap.find(lexeme);
-    if (it != Variables::StringToTypeMap.end()) {
-        const auto & type = it->second;
-        while (isspace(peek())) {
-            advance();
-        }
-
-        if (peek() == IDENTIFIER_VARIABLE) {
-            return this->variableDeclarationToken(type);
-        }
-        return createToken(Tokens::Type::Identifier, lexeme);
-    }
-    return createToken(Tokens::Type::Identifier, lexeme);
-}
-
-Tokens::Token Lexer::functionDeclarationToken() {
-    advance();  // Skip function
-    std::string functionName;
-    if (isalpha(peek()) || peek() == '_') {
-        functionName += advance();
-        while (isalnum(peek()) || peek() == '_') {
-            functionName += advance();
-        }
-        return createToken(Tokens::Type::FunctionDeclaration, functionName);
-    }
-    return createUnknownToken("function followed by invalid character");
-}
-
-Tokens::Token Lexer::variableDeclarationToken(Variables::Type type) {
-    advance();  // Skip $
-    std::string varName;
-    if (isalpha(peek()) || peek() == '_') {
-        varName += advance();
-        while (isalnum(peek()) || peek() == '_') {
-            varName += advance();
-        }
-        for (auto it = Variables::StringToTypeMap.begin(); it != Variables::StringToTypeMap.end(); ++it) {
-            if (it->second == type) {
-                return createToken(getTokenTypeFromValueDeclaration(it->second), varName);
-            }
-        }
-        return createUnknownToken("Invalid variable type in declaration");
-    }
-    return createUnknownToken("$ followed by invalid character in declaration");
-}
-
-bool Lexer::matchSequence(const std::string & sequence, bool caseSensitive) const {
-    if (this->pos + sequence.size() > src.size()) {
-        return false;
-    }
-    for (size_t i = 0; i < sequence.size(); ++i) {
-        char srcChar = src[this->pos + i];
-        char seqChar = sequence[i];
-        if (!caseSensitive) {
-            srcChar = std::tolower(static_cast<unsigned char>(srcChar));
-            seqChar = std::tolower(static_cast<unsigned char>(seqChar));
-        }
-        if (srcChar != seqChar) {
-            return false;
-        }
-    }
-    return true;
-}
-
-void Lexer::matchAndConsume(const std::string & sequence, bool caseSensitive) {
-    if (matchSequence(sequence, caseSensitive)) {
-        for (size_t i = 0; i < sequence.length(); ++i) {
-            advance();
-        }
-    }
-}
-
-std::vector<Tokens::Token> Lexer::tokenize() {
-    std::vector<Tokens::Token> tokens;
-    tokens.reserve(src.size() / 4);
-
-    while (pos < src.size()) {
-        char c = src[pos];
-
-        if (isspace(c)) {
-            advance();
-            continue;
-        }
-        if (c == '\n') {
-            tokens.push_back(createSingleCharToken(Tokens::Type::EndOfLine, "\n"));
-            continue;
-        }
-        if (c == IDENTIFIER_COMMENT) {
-            tokens.push_back(commentToken());
-            advance();  // Skip newline after comment
-            continue;
-        }
-        if (matchSequence(PARSER_OPEN_TAG)) {
-            matchAndConsume(PARSER_OPEN_TAG);
-            tokens.push_back(createToken(Tokens::Type::ParserOpenTag, PARSER_OPEN_TAG));
-            continue;
-        }
-        if (matchSequence(PARSER_CLOSE_TAG)) {
-            matchAndConsume(PARSER_CLOSE_TAG);
-            tokens.push_back(createToken(Tokens::Type::ParserCloseTag, PARSER_CLOSE_TAG));
-            continue;
-        }
-        switch (c) {
-            case 'a' ... 'z':
-            case 'A' ... 'Z':
-                tokens.push_back(keywordOrIdentifierToken());
-                break;
-            case IDENTIFIER_VARIABLE:
-                tokens.push_back(variableToken());
-                break;
-            case '0' ... '9':
-                tokens.push_back(numberToken());
-                break;
-            case '"':
-            case '\'':
-                tokens.push_back(stringToken());
-                break;
-            case '(':
-                tokens.push_back(createSingleCharToken(Tokens::Type::LeftParenthesis, "("));
-                break;
-            case ')':
-                tokens.push_back(createSingleCharToken(Tokens::Type::RightParenthesis, ")"));
-                break;
-            case ',':
-                tokens.push_back(createSingleCharToken(Tokens::Type::Comma, ","));
-                break;
-            case ';':
-                tokens.push_back(createSingleCharToken(Tokens::Type::Semicolon, ";"));
-                break;
-            case '=':
-                tokens.push_back(createSingleCharToken(Tokens::Type::Equals, "="));
-                break;
-            case '+':
-                tokens.push_back(createSingleCharToken(Tokens::Type::Plus, "+"));
-                break;
-            case '{':
-                tokens.push_back(createSingleCharToken(Tokens::Type::LeftCurlyBracket, "{"));
-                break;
-            case '}':
-                tokens.push_back(createSingleCharToken(Tokens::Type::RightCurlyBracket, "}"));
-                break;
-            default:
-                tokens.push_back(createUnknownToken(std::string(1, c)));
-                advance();
-                break;
-        }
-    }
-
-    tokens.push_back({
-        Tokens::Type::EndOfFile, "", filename, lineNumber, colNumber, { charNumber, charNumber }
-    });
-    return tokens;
-}
diff --git a/src/Lexer.hpp b/src/Lexer.hpp
deleted file mode 100644
index 7274e47..0000000
--- a/src/Lexer.hpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef LEXER_HPP
-#define LEXER_HPP
-
-#include <algorithm>
-#include <istream>
-#include <sstream>
-#include <vector>
-
-#include "StringHelpers.hpp"
-#include "Token.hpp"
-#include "VariableTypes.hpp"
-
-class Lexer {
-  public:
-    Lexer(const std::string & source, const std::string & filename);
-    std::vector<Token> tokenize();
-
-  private:
-    const std::string & src;
-    const std::string & filename;
-    size_t              pos;
-    int                 lineNumber = 1;
-    size_t              colNumber  = 1;
-    size_t              charNumber = 1;
-
-    char peek() const;
-    char advance();
-    bool isAtEnd() const;
-
-    Token string();
-    Token number();
-    Token identifier();
-    Token variable();
-    Token comment();
-    Token keywordOrIdentifier();
-    Token boolean();
-    Token singleCharToken(TokenType type, const std::string & lexeme);
-    bool  matchSequence(const std::string & sequence, bool caseSensitive = true) const;
-    Token variableDeclaration(Variables::Type type);
-    void  matchAndConsume(const std::string & sequence, bool caseSensitive = true);
-
-    // create token methods
-    Token createToken(TokenType type, const std::string & lexeme) const;
-    Token createSingleCharToken(TokenType type, const std::string & lexeme);
-    Token createUnknownToken(const std::string & lexeme) const;
-    Token createErrorToken(const std::string & lexeme) const;
-    Token stringToken();
-    Token numberToken();
-    Token identifierToken();
-    Token variableToken();
-    Token commentToken();
-    Token keywordOrIdentifierToken();
-    Token functionDeclarationToken();
-    Token variableDeclarationToken(Variables::Type type);
-
-    // validate number types from string
-    template <typename Numeric> static bool is_number(const std::string & s) {
-        Numeric n;
-        return ((std::istringstream(s) >> n >> std::ws).eof());
-    }
-
-    bool matchSequence(const std::string & sequence, bool caseSensitive = true) {
-        if (caseSensitive) {
-            return src.substr(pos, sequence.length()) == sequence;
-        }
-
-        std::string srcSubstr = src.substr(pos, sequence.length());
-        std::string seqLower  = sequence;
-
-        StringHelpers::strtolower(srcSubstr);
-        StringHelpers::strtolower(seqLower);
-
-        return srcSubstr == seqLower;
-    }
-};
-
-#endif  // LEXER_HPP
diff --git a/src/Lexer/Lexer.cpp b/src/Lexer/Lexer.cpp
new file mode 100644
index 0000000..6f6cc35
--- /dev/null
+++ b/src/Lexer/Lexer.cpp
@@ -0,0 +1,14 @@
+#include "Lexer/Lexer.hpp"
+
+namespace Lexer {
+const std::vector<std::string> Lexer::Lexer::OPERATOR_RELATIONAL = { "==", "!=", "<", ">", "<=", ">=" };
+const std::vector<std::string> Lexer::Lexer::OPERATOR_INCREMENT  = { "++", "--" };
+const std::vector<std::string> Lexer::Lexer::OPERATOR_ASSIGNMENT = { "=", "+=", "-=", "*=", "/=", "%=" };
+const std::vector<std::string> Lexer::Lexer::OPERATOR_LOGICAL    = { "&&", "||" };
+
+const std::vector<std::string> Lexer::Lexer::OPERATOR_ARITHMETIC = { "+", "-", "*", "/", "%" };
+const std::vector<std::string> Lexer::Lexer::PUNCTUATION         = { "(", ")", "{", "}", "[", "]", ",", ";" };
+
+
+
+};  // namespace Lexer
diff --git a/src/Lexer/Lexer.hpp b/src/Lexer/Lexer.hpp
new file mode 100644
index 0000000..737ec1d
--- /dev/null
+++ b/src/Lexer/Lexer.hpp
@@ -0,0 +1,316 @@
+#ifndef LEXER_HPP
+#define LEXER_HPP
+
+#include <algorithm>    // std::find_if
+#include <cctype>       // <<< Hozzáadva
+#include <string>
+#include <string_view>  // <<< Hozzáadva
+#include <unordered_map>
+#include <vector>
+
+#include "Token.hpp"  // Feltételezzük, hogy ez a fenti Token.hpp
+
+namespace Lexer {
+class Lexer {
+  public:
+    Lexer() {
+        for (const auto & vecRef :
+             { std::cref(OPERATOR_ARITHMETIC), std::cref(OPERATOR_RELATIONAL), std::cref(OPERATOR_INCREMENT),
+               std::cref(OPERATOR_ASSIGNMENT), std::cref(OPERATOR_LOGICAL), std::cref(PUNCTUATION) }) {
+            for (const auto & str : vecRef.get()) {
+                operators_ += str;
+            }
+        }
+
+        operators_ += "$";
+    }
+
+    void addNamespaceInput(const std::string & ns, const std::string & input) {
+        inputs_[ns]         = input;
+        positions_[ns]      = 0;
+        line_numbers_[ns]   = 1;
+        column_numbers_[ns] = 1;
+    }
+
+    void setNamespace(const std::string & ns) { current_namespace_ = ns; }
+
+    std::vector<Tokens::Token> tokenizeNamespace(const std::string & ns) {
+        if (inputs_.find(ns) == inputs_.end()) {
+            return {};
+        }
+
+        setNamespace(ns);
+        std::vector<Tokens::Token> tokens;
+        Tokens::Token              token;
+        do {
+            token = nextToken();
+            tokens.push_back(token);
+        } while (token.type != Tokens::Type::END_OF_FILE);
+
+        tokens_[ns] = tokens;
+        return tokens;
+    }
+
+    std::vector<Tokens::Token> getTokens(const std::string & ns) const {
+        auto it = tokens_.find(ns);
+        if (it != tokens_.end()) {
+            return it->second;
+        }
+        return {};
+    }
+
+    void setKeyWords(const std::unordered_map<std::string, Tokens::Type> & new_keywords) { keywords = new_keywords; }
+
+    Tokens::Token nextToken() {
+        skipWhitespaceAndComments();
+        size_t start = pos();
+
+        if (isAtEnd()) {
+            return createToken(Tokens::Type::END_OF_FILE, start, start);
+        }
+
+        char c = peek();
+        if (isalpha(c) || c == '_') {
+            return matchIdentifierOrKeyword(start);
+        }
+        if (isdigit(c) || (isdigit(c) && peek(1) == '.')|| (c == '.' && isdigit(peek(1)))) {
+            return matchNumber(start);
+        }
+        if (c == '"' || c == '\'') {
+            return matchStringLiteral(start);
+        }
+        if (operators_.find(c) != std::string_view::npos) {
+            return matchOperatorOrPunctuation(start);
+        }
+
+        advance();
+        return createToken(Tokens::Type::UNKNOWN, start, pos());
+    }
+
+
+  private:
+    std::unordered_map<std::string, std::string>                inputs_;
+    std::unordered_map<std::string, std::vector<Tokens::Token>> tokens_;
+    std::unordered_map<std::string, size_t>                     positions_;
+    std::unordered_map<std::string, int>                        line_numbers_;
+    std::unordered_map<std::string, int>                        column_numbers_;
+
+    std::string                                   operators_;
+    std::string                                   current_namespace_;
+    std::unordered_map<std::string, Tokens::Type> keywords;
+
+    // two chars
+    static const std::vector<std::string> OPERATOR_RELATIONAL;
+    static const std::vector<std::string> OPERATOR_INCREMENT;
+    static const std::vector<std::string> OPERATOR_ASSIGNMENT;
+    static const std::vector<std::string> OPERATOR_LOGICAL;
+
+    // one char
+    static const std::vector<std::string> OPERATOR_ARITHMETIC;
+    static const std::vector<std::string> PUNCTUATION;
+
+    const std::string & input() const { return inputs_.at(current_namespace_); }
+
+    size_t & pos() { return positions_[current_namespace_]; }
+
+    int & line() { return line_numbers_[current_namespace_]; }
+
+    int & col() { return column_numbers_[current_namespace_]; }
+
+    Tokens::Token createToken(Tokens::Type type, size_t start, size_t end, const std::string & value = "") {
+        Tokens::Token token;
+        token.type          = type;
+        token.start_pos     = start;
+        token.end_pos       = end;
+        token.line_number   = line();
+        token.column_number = col();
+        if (start <= end && end <= input().length()) {
+            token.lexeme = std::string_view(input()).substr(start, end - start);
+            token.value  = value.empty() ? std::string(token.lexeme) : value;
+        }
+        return token;
+    }
+
+    // --------------------------------------
+
+    char peek(size_t offset = 0) const {
+        const auto & in = inputs_.at(current_namespace_);
+        size_t       cp = positions_.at(current_namespace_);
+        if (cp + offset >= in.length()) {
+            return '\0';
+        }
+        return in[cp + offset];
+    }
+
+    char advance() {
+        char c = peek();
+        pos()++;
+        if (c == '\n') {
+            line()++;
+            col() = 1;
+        } else {
+            col()++;
+        }
+        return c;
+    }
+
+    bool isAtEnd() const { return positions_.at(current_namespace_) >= inputs_.at(current_namespace_).length(); }
+
+    bool isComment(const char current_char) const {
+        return (current_char == '/' && peek(1) == '/' || current_char == '#');
+    }
+
+    void skipWhitespaceAndComments() {
+        while (!isAtEnd()) {
+            char c = peek();
+            if (isspace(c)) {
+                advance();
+            } else if ((c == '/' && peek(1) == '/') || c == '#') {
+                while (!isAtEnd() && peek() != '\n') {
+                    advance();
+                }
+            } else {
+                break;
+            }
+        }
+    }
+
+    Tokens::Token matchIdentifierOrKeyword(size_t start_pos, Tokens::Type type = Tokens::Type::IDENTIFIER) {
+        while (!isAtEnd() && (isalnum(peek()) || peek() == '_')) {
+            advance();
+        }
+        size_t      end   = pos();
+        std::string value = input().substr(start_pos, end - start_pos);
+        if (value.empty()) {
+            return createToken(Tokens::Type::UNKNOWN, start_pos, end);
+        }
+
+        if (type == Tokens::Type::IDENTIFIER) {
+            auto it = keywords.find(value);
+            if (it != keywords.end()) {
+                return createToken(it->second, start_pos, end);
+            }
+        }
+        return createToken(type, start_pos, end);
+    }
+
+    Tokens::Token matchNumber(size_t start_pos) {
+        bool has_dot = false;
+
+        while (!isAtEnd()) {
+            if (isdigit(peek())) {
+                advance();
+            } else if (!has_dot && peek() == '.' && isdigit(peek(1))) {
+                has_dot = true;
+                advance();  // a pont
+                advance();  // az első számjegy a pont után
+            } else {
+                break;
+            }
+        }
+
+        size_t end = pos();
+        return createToken(Tokens::Type::NUMBER, start_pos, end);
+    }
+
+    Tokens::Token matchStringLiteral(size_t start_pos) {
+        char opening_quote = peek();
+        advance();  // Skip opening quote
+        std::string value;
+        bool        unterminated = false;
+
+        while (!isAtEnd()) {
+            char c = peek();
+            if (c == opening_quote) {
+                advance();
+                break;
+            }
+            if (c == '\\') {
+                advance();
+                char e = advance();
+                switch (e) {
+                    case 'n':
+                        value += '\n';
+                        break;
+                    case 't':
+                        value += '\t';
+                        break;
+                    case '"':
+                        value += opening_quote;
+                        break;
+                    case '\\':
+                        value += '\\';
+                        break;
+                    default:
+                        value += e;
+                        break;
+                }
+            } else {
+                value += advance();
+            }
+        }
+
+        size_t end = pos();
+        if (unterminated) {
+            return createToken(Tokens::Type::UNKNOWN, start_pos, end, input().substr(start_pos, end - start_pos));
+        }
+        return createToken(Tokens::Type::STRING_LITERAL, start_pos, end, value);
+    }
+
+    Tokens::Token matchOperatorOrPunctuation(size_t start_pos) {
+        char first_char = advance();  // Első karakter elfogyasztása
+
+        if (!isAtEnd()) {
+            char        second_char = peek(0);  // Következő karakter megnézése
+            std::string two_chars_str{ first_char, second_char };
+
+            const std::vector<std::pair<const std::vector<std::string> *, Tokens::Type>> two_char_op_types = {
+                { &OPERATOR_RELATIONAL, Tokens::Type::OPERATOR_RELATIONAL },
+                { &OPERATOR_INCREMENT,  Tokens::Type::OPERATOR_INCREMENT  },
+                { &OPERATOR_ASSIGNMENT, Tokens::Type::OPERATOR_ASSIGNMENT },
+                { &OPERATOR_LOGICAL,    Tokens::Type::OPERATOR_LOGICAL    }
+            };
+
+            for (const auto & [vec_ptr, type] : two_char_op_types) {
+                if (matchFromVector(*vec_ptr, two_chars_str)) {
+                    advance();  // Második karakter elfogyasztása
+                    size_t end_pos = pos();
+                    return createToken(type, start_pos, end_pos);
+                }
+            }
+        }
+
+        // Egykarakteres operátor vagy írásjel
+        std::string single_char_str(1, first_char);
+
+        if (single_char_str == "$") {
+            if (isalpha(peek(0)) || peek(0) == '_') {
+                return matchIdentifierOrKeyword(start_pos, Tokens::Type::VARIABLE_IDENTIFIER);
+            }
+        }
+
+        const std::vector<std::pair<const std::vector<std::string> *, Tokens::Type>> one_char_op_types = {
+            { &OPERATOR_ARITHMETIC, Tokens::Type::OPERATOR_ARITHMETIC },
+            { &OPERATOR_ASSIGNMENT, Tokens::Type::OPERATOR_ASSIGNMENT }, // "=" itt van!
+            { &PUNCTUATION,         Tokens::Type::PUNCTUATION         }
+        };
+
+        for (const auto & [vec_ptr, type] : one_char_op_types) {
+            if (matchFromVector(*vec_ptr, single_char_str)) {
+                size_t end_pos = pos();
+                return createToken(type, start_pos, end_pos);
+            }
+        }
+
+        size_t end_pos = pos();
+        return createToken(Tokens::Type::UNKNOWN, start_pos, end_pos);
+    }
+
+    static bool matchFromVector(const std::vector<std::string> & vec, const std::string & value) {
+        return std::find(vec.begin(), vec.end(), value) != vec.end();
+    }
+
+};  // class Lexer
+
+};  // namespace Lexer
+#endif  // LEXER_HPP
diff --git a/src/Lexer/Token.hpp b/src/Lexer/Token.hpp
new file mode 100644
index 0000000..ac2ac9f
--- /dev/null
+++ b/src/Lexer/Token.hpp
@@ -0,0 +1,37 @@
+#ifndef TOKEN_HPP
+#define TOKEN_HPP
+
+#include <iostream>
+#include <string>               // <<< Hozzáadva
+#include <string_view>          // <<< Hozzáadva
+
+#include "Lexer/TokenType.hpp"  // Feltételezzük, hogy ez definiálja Type-ot és TypeToString-ot
+
+namespace Lexer::Tokens {
+
+struct Token {
+    Lexer::Tokens::Type type;
+    std::string         value;      // A token feldolgozott értéke
+    std::string_view    lexeme;     // A nyers szövegrész az eredeti stringből
+    size_t              start_pos;  // Kezdő index
+    size_t              end_pos;    // Vég index (exclusive)
+    int                 line_number;
+    int                 column_number;
+
+    // Módosított print metódus a lexeme kiírásával
+    void print() const {
+        std::cout << "Token { Type: " << Lexer::Tokens::TypeToString(type) << ", Value: \"" << value << "\""
+                  << ", Pos: [" << start_pos << ", " << end_pos
+                  << ")"
+                  // Lexeme kiírása (stringgé konvertálva a biztonság kedvéért, ha pl. null lenne)
+                  << ", Lexeme: \"" << std::string(lexeme) << "\""
+                  << " }" << '\n';
+    }
+};
+
+inline bool operator==(const Token & lhs, const Token & rhs) {
+    return lhs.type == rhs.type && lhs.value == rhs.value && lhs.start_pos == rhs.start_pos &&
+           lhs.end_pos == rhs.end_pos;
+}
+};  // namespace Lexer::Tokens
+#endif  // TOKEN_HPP
diff --git a/src/Lexer/TokenType.hpp b/src/Lexer/TokenType.hpp
new file mode 100644
index 0000000..2dd49ca
--- /dev/null
+++ b/src/Lexer/TokenType.hpp
@@ -0,0 +1,87 @@
+#ifndef TOKEN_TYPE_HPP
+#define TOKEN_TYPE_HPP
+
+#include <cstdint>
+#include <string>
+
+namespace Lexer::Tokens {
+
+enum class Type : std::uint8_t {
+    IDENTIFIER,           // Pl. változónév: myVar
+    VARIABLE_IDENTIFIER,  // Pl. $
+    KEYWORD,              // Pl. if, else, while
+    NUMBER,               // Pl. 123, 42
+    STRING_LITERAL,       // Pl. "hello world"
+    OPERATOR_RELATIONAL,  // Pl. +, -, *, /, =, ==, <, >
+    OPERATOR_LOGICAL,     // Pl. &&, ||
+    OPERATOR_ASSIGNMENT,  // Pl. +=, -=, *=, /=
+    OPERATOR_INCREMENT,   // Pl. ++, --
+    OPERATOR_ARITHMETIC,  // Pl. +, -, *, /
+    PUNCTUATION,          // Pl. (, ), {, }, ;, ,
+    COMMENT,              // Általában kihagyjuk
+    END_OF_FILE,          // A string végét jelzi
+    KEYWORD_STRING,
+    KEYWORD_INT,
+    KEYWORD_DOUBLE,
+    KEYWORD_FLOAT,
+    KEYWORD_BOOLEAN,
+    KEYWORD_FUNCTION,
+    KEYWORD_RETURN,
+    KEYWORD_NULL,
+    UNKNOWN  // Ismeretlen karakter/szekvencia
+};
+
+inline std::string TypeToString(Lexer::Tokens::Type type) {
+    switch (type) {
+        case Lexer::Tokens::Type::IDENTIFIER:
+            return "IDENTIFIER";
+        case Lexer::Tokens::Type::VARIABLE_IDENTIFIER:
+            return "VARIABLE_IDENTIFIER";
+        case Lexer::Tokens::Type::KEYWORD:
+            return "KEYWORD";
+        case Lexer::Tokens::Type::NUMBER:
+            return "NUMBER";
+        case Lexer::Tokens::Type::STRING_LITERAL:
+            return "STRING_LITERAL";
+        case Lexer::Tokens::Type::OPERATOR_RELATIONAL:
+            return "OPERATOR_RELATIONAL";
+        case Lexer::Tokens::Type::OPERATOR_LOGICAL:
+            return "OPERATOR_LOGICAL";
+        case Lexer::Tokens::Type::OPERATOR_ASSIGNMENT:
+            return "OPERATOR_ASSIGNMENT";
+        case Lexer::Tokens::Type::OPERATOR_INCREMENT:
+            return "OPERATOR_INCREMENT";
+        case Lexer::Tokens::Type::OPERATOR_ARITHMETIC:
+            return "OPERATOR_ARITHMETIC";
+        case Lexer::Tokens::Type::PUNCTUATION:
+            return "PUNCTUATION";
+        case Lexer::Tokens::Type::COMMENT:
+            return "COMMENT";
+        case Lexer::Tokens::Type::END_OF_FILE:
+            return "END_OF_FILE";
+        case Lexer::Tokens::Type::KEYWORD_STRING:
+            return "KEYWORD_STRING";
+        case Lexer::Tokens::Type::KEYWORD_INT:
+            return "KEYWORD_INT";
+        case Lexer::Tokens::Type::KEYWORD_DOUBLE:
+            return "KEYWORD_DOUBLE";
+        case Lexer::Tokens::Type::KEYWORD_FLOAT:
+            return "KEYWORD_FLOAT";
+        case Lexer::Tokens::Type::KEYWORD_BOOLEAN:
+            return "KEYWORD_BOOLEAN";
+        case Lexer::Tokens::Type::KEYWORD_FUNCTION:
+            return "KEYWORD_FUNCTION";
+        case Lexer::Tokens::Type::KEYWORD_RETURN:
+            return "KEYWORD_RETURN";
+        case Lexer::Tokens::Type::KEYWORD_NULL:
+            return "KEYWORD_NULL";
+        case Lexer::Tokens::Type::UNKNOWN:
+            return "UNKNOWN";
+        default:
+            return "INVALID_TYPE";
+    }
+}
+
+};  // namespace Lexer::Tokens
+
+#endif  // TOKEN_TYPE_HPP
diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp
new file mode 100644
index 0000000..fbd0e73
--- /dev/null
+++ b/src/Parser/Parser.cpp
@@ -0,0 +1,37 @@
+#include "Parser/Parser.hpp"
+
+// Más szükséges include-ok, ha kellenek
+namespace Parser {
+
+const std::unordered_map<std::string, Lexer::Tokens::Type> Parser::keywords = {
+    { "if",       Lexer::Tokens::Type::KEYWORD          },
+    { "else",     Lexer::Tokens::Type::KEYWORD          },
+    { "while",    Lexer::Tokens::Type::KEYWORD          },
+    { "for",      Lexer::Tokens::Type::KEYWORD          },
+    { "return",   Lexer::Tokens::Type::KEYWORD_RETURN   },
+    { "function", Lexer::Tokens::Type::KEYWORD_FUNCTION },
+    // Régebbiek:
+    { "const",    Lexer::Tokens::Type::KEYWORD          },
+    { "true",     Lexer::Tokens::Type::KEYWORD          },
+    { "false",    Lexer::Tokens::Type::KEYWORD          },
+    // változó típusok
+    { "null",     Lexer::Tokens::Type::KEYWORD_NULL     },
+    { "int",      Lexer::Tokens::Type::KEYWORD_INT      },
+    { "double",   Lexer::Tokens::Type::KEYWORD_DOUBLE   },
+    { "float",    Lexer::Tokens::Type::KEYWORD_FLOAT    },
+    { "string",   Lexer::Tokens::Type::KEYWORD_STRING   },
+    { "boolean",  Lexer::Tokens::Type::KEYWORD_BOOLEAN  },
+    { "bool",     Lexer::Tokens::Type::KEYWORD_BOOLEAN  },
+    // ... egyéb kulcsszavak ...
+};
+
+const std::unordered_map<Lexer::Tokens::Type, Symbols::Variables::Type> Parser::variable_types = {
+    { Lexer::Tokens::Type::KEYWORD_INT,     Symbols::Variables::Type::INTEGER   },
+    { Lexer::Tokens::Type::KEYWORD_DOUBLE,  Symbols::Variables::Type::DOUBLE    },
+    { Lexer::Tokens::Type::KEYWORD_FLOAT,   Symbols::Variables::Type::FLOAT     },
+    { Lexer::Tokens::Type::KEYWORD_STRING,  Symbols::Variables::Type::STRING    },
+    { Lexer::Tokens::Type::KEYWORD_NULL,    Symbols::Variables::Type::NULL_TYPE },
+    { Lexer::Tokens::Type::KEYWORD_BOOLEAN, Symbols::Variables::Type::BOOLEAN   },
+};
+
+}  // namespace Parser
diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp
new file mode 100644
index 0000000..b40397e
--- /dev/null
+++ b/src/Parser/Parser.hpp
@@ -0,0 +1,536 @@
+#ifndef PARSER_HPP
+#define PARSER_HPP
+
+#include <algorithm>
+#include <memory>
+#include <sstream>  // Hibaüzenetekhez
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+// Szükséges header-ök a Lexer és Symbol komponensekből
+#include "Lexer/Token.hpp"
+#include "Lexer/TokenType.hpp"  // Enum és TypeToString
+#include "Symbols/SymbolContainer.hpp"
+#include "Symbols/SymbolFactory.hpp"
+#include "Symbols/Value.hpp"  // Symbols::Value miatt
+
+namespace Parser {
+
+class SyntaxError : public std::runtime_error {
+  public:
+    SyntaxError(const std::string & message, const int line, const int col) :
+        std::runtime_error(message + " at line " + std::to_string(line) + ", column " + std::to_string(col)) {}
+
+    SyntaxError(const std::string & message, const Lexer::Tokens::Token & token) :
+        SyntaxError(
+            message + " (found token: '" + token.value + "' type: " + Lexer::Tokens::TypeToString(token.type) + ")",
+            token.line_number, token.column_number) {}
+};
+
+class Parser {
+  public:
+    Parser() {}
+
+    void parseProgram(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string) {
+        tokens_              = tokens;
+        input_str_view_      = input_string;
+        current_token_index_ = 0;
+        symbol_container_    = std::make_unique<Symbols::SymbolContainer>();
+        try {
+            while (!isAtEnd() && currentToken().type != Lexer::Tokens::Type::END_OF_FILE) {
+                parseStatement();
+            }
+            if (!isAtEnd() && currentToken().type != Lexer::Tokens::Type::END_OF_FILE) {
+                reportError("Unexpected tokens after program end");
+            }
+        } catch (const SyntaxError & e) {
+            std::cerr << "Syntax Error: " << e.what() << '\n';
+        } catch (const std::exception & e) {
+            std::cerr << "Error during parsing: " << e.what() << '\n';
+            throw;
+        }
+    }
+
+    const std::shared_ptr<Symbols::SymbolContainer> & getSymbolContainer() const {
+        if (!symbol_container_) {
+            throw std::runtime_error("Symbol container is not initialized.");
+        }
+        return symbol_container_;
+    }
+
+    static const std::unordered_map<std::string, Lexer::Tokens::Type>              keywords;
+    static const std::unordered_map<Lexer::Tokens::Type, Symbols::Variables::Type> variable_types;
+
+  private:
+    std::vector<Lexer::Tokens::Token>         tokens_;
+    std::string_view                          input_str_view_;
+    size_t                                    current_token_index_;
+    std::shared_ptr<Symbols::SymbolContainer> symbol_container_;
+
+    // Token Stream Kezelő és Hibakezelő segédfüggvények (változatlanok)
+    const Lexer::Tokens::Token & currentToken() const {
+        if (isAtEnd()) {
+            // Technikailag itt már nem kellene lennünk, ha a parseProgram ciklus jól van megírva
+            // De biztonsági ellenőrzésként jó lehet
+            if (!tokens_.empty() && tokens_.back().type == Lexer::Tokens::Type::END_OF_FILE) {
+                return tokens_.back();  // Visszaadjuk az EOF tokent
+            }
+            throw std::runtime_error("Unexpected end of token stream reached.");
+        }
+        return tokens_[current_token_index_];
+    }
+
+    // Előre néz a token stream-ben
+    const Lexer::Tokens::Token & peekToken(size_t offset = 1) const {
+        if (current_token_index_ + offset >= tokens_.size()) {
+            // EOF vagy azon túl vagyunk, adjuk vissza az utolsó tokent (ami EOF kell legyen)
+            if (!tokens_.empty()) {
+                return tokens_.back();
+            }
+            throw std::runtime_error("Cannot peek beyond end of token stream.");
+        }
+        return tokens_[current_token_index_ + offset];
+    }
+
+    // Elfogyasztja (lépteti az indexet) az aktuális tokent és visszaadja azt
+    Lexer::Tokens::Token consumeToken() {
+        if (isAtEnd()) {
+            throw std::runtime_error("Cannot consume token at end of stream.");
+        }
+        return tokens_[current_token_index_++];
+    }
+
+    // Ellenőrzi, hogy az aktuális token típusa megegyezik-e a várttal.
+    // Ha igen, elfogyasztja és true-t ad vissza. Ha nem, false-t ad vissza.
+    bool match(Lexer::Tokens::Type expected_type) {
+        if (isAtEnd()) {
+            return false;
+        }
+        if (currentToken().type == expected_type) {
+            consumeToken();
+            return true;
+        }
+        return false;
+    }
+
+    // Ellenőrzi, hogy az aktuális token típusa és értéke megegyezik-e a várttal.
+    // Csak OPERATOR és PUNCTUATION esetén érdemes használni az érték ellenőrzést.
+    bool match(Lexer::Tokens::Type expected_type, const std::string & expected_value) {
+        if (isAtEnd()) {
+            return false;
+        }
+        const auto & token = currentToken();
+        if (token.type == expected_type && token.value == expected_value) {
+            consumeToken();
+            return true;
+        }
+        return false;
+    }
+
+    Lexer::Tokens::Token expect(Lexer::Tokens::Type expected_type) {
+        if (isAtEnd()) {
+            reportError("Unexpected end of file, expected token type: " + Lexer::Tokens::TypeToString(expected_type));
+        }
+        const auto & token = currentToken();
+        if (token.type == expected_type) {
+            return consumeToken();
+        }
+        reportError("Expected token type " + Lexer::Tokens::TypeToString(expected_type));
+        // A reportError dob, ez a return sosem fut le, de a fordító kedvéért kellhet:
+        return token;  // Vagy dobjon a reportError
+    }
+
+    // Mint az expect, de az értékét is ellenőrzi.
+    Lexer::Tokens::Token expect(Lexer::Tokens::Type expected_type, const std::string & expected_value) {
+        if (isAtEnd()) {
+            reportError("Unexpected end of file, expected token: " + Lexer::Tokens::TypeToString(expected_type) +
+                        " with value '" + expected_value + "'");
+        }
+        const auto & token = currentToken();
+        if (token.type == expected_type && token.value == expected_value) {
+            return consumeToken();
+        }
+        reportError("Expected token " + Lexer::Tokens::TypeToString(expected_type) + " with value '" + expected_value +
+                    "'");
+        return token;  // reportError dob
+    }
+
+    // Ellenőrzi, hogy a releváns tokenek végére értünk-e (az EOF előtti utolsó tokenen vagyunk-e)
+    bool isAtEnd() const {
+        // Akkor vagyunk a végén, ha az index a tokenek méretével egyenlő,
+        // vagy ha már csak az EOF token van hátra (ha az a lista utolsó eleme).
+        return current_token_index_ >= tokens_.size() ||
+               (current_token_index_ == tokens_.size() - 1 && tokens_.back().type == Lexer::Tokens::Type::END_OF_FILE);
+    }
+
+    // --- Hibakezelés ---
+    // Hiba jelentése és kivétel dobása
+    [[noreturn]] void reportError(const std::string & message) {
+        // Használjuk az aktuális token pozícióját, ha még nem értünk a végére
+        if (current_token_index_ < tokens_.size()) {
+            throw SyntaxError(message, tokens_[current_token_index_]);
+        }  // Ha már a végén vagyunk, az utolsó ismert pozíciót használjuk
+        int line = tokens_.empty() ? 0 : tokens_.back().line_number;
+        int col  = tokens_.empty() ? 0 : tokens_.back().column_number;
+        throw SyntaxError(message, line, col);
+    }
+
+    // --- Elemzési Módszerek (Moduláris részek) ---
+
+    // parseStatement (változatlan)
+    void parseStatement() {
+        const auto & token_type = currentToken().type;
+
+        if (token_type == Lexer::Tokens::Type::KEYWORD_FUNCTION) {
+            parseFunctionDefinition();
+            return;
+        }
+
+        for (const auto & _type : Parser::Parser::variable_types) {
+            if (token_type == _type.first) {
+                parseVariableDefinition();
+                return;
+            }
+        }
+
+        reportError("Unexpected token at beginning of statement");
+    }
+
+    // parseVariableDefinition (SymbolFactory használata már korrekt volt)
+    void parseVariableDefinition() {
+        Symbols::Variables::Type var_type_enum = parseType();
+        // A típus stringjének tárolása csak a debug kiíráshoz kell
+        //std::string              var_type_str  = tokens_[current_token_index_ - 1].value;
+        std::cout << "var_name: " << currentToken().lexeme << std::endl;
+        Lexer::Tokens::Token id_token = expect(Lexer::Tokens::Type::VARIABLE_IDENTIFIER);
+        std::string          var_name = id_token.value;
+        // Levágjuk a '$' jelet, ha a lexer mégis benne hagyta
+        if (!var_name.empty() && var_name[0] == '$') {
+            var_name = var_name.substr(1);
+        }
+
+        expect(Lexer::Tokens::Type::OPERATOR_ASSIGNMENT, "=");
+        Symbols::Value initial_value = parseValue(var_type_enum);
+        expect(Lexer::Tokens::Type::PUNCTUATION, ";");
+
+        std::string context  = "global";  // Globális változó
+        // SymbolFactory használata a létrehozáshoz
+        auto variable_symbol = Symbols::SymbolFactory::createVariable(var_name, initial_value, context, var_type_enum);
+
+        // Ellenőrzés és definíció az *aktuális* scope-ban (ami itt a globális)
+        if (symbol_container_->exists("variables", var_name)) {
+            reportError("Variable '" + var_name + "' already defined in this scope");
+        }
+        symbol_container_->define("variables", variable_symbol);
+
+        // Debugging kiírás (változatlan)
+        // std::cout << "Parsed variable: " << var_type_str << " " << id_token.value << " = ... ;\n";
+    }
+
+    // *** MÓDOSÍTOTT parseFunctionDefinition ***
+    void parseFunctionDefinition() {
+        expect(Lexer::Tokens::Type::KEYWORD_FUNCTION);
+        Lexer::Tokens::Token     id_token         = expect(Lexer::Tokens::Type::IDENTIFIER);
+        std::string              func_name        = id_token.value;
+        Symbols::Variables::Type func_return_type = Symbols::Variables::Type::NULL_TYPE;
+        expect(Lexer::Tokens::Type::OPERATOR_ASSIGNMENT, "=");
+        expect(Lexer::Tokens::Type::PUNCTUATION, "(");
+
+        Symbols::FunctionParameterInfo param_infos;
+
+        if (currentToken().type != Lexer::Tokens::Type::PUNCTUATION || currentToken().value != ")") {
+            while (true) {
+                // Paraméter típusa
+                //size_t                   type_token_index = current_token_index_;  // Elmentjük a típus token indexét
+                Symbols::Variables::Type param_type = parseType();  // Ez elfogyasztja a type tokent
+
+                // Paraméter név ($variable)
+                Lexer::Tokens::Token param_id_token = expect(Lexer::Tokens::Type::VARIABLE_IDENTIFIER);
+                std::string          param_name     = param_id_token.value;
+                if (!param_name.empty() && param_name[0] == '$') {  // '$' eltávolítása
+                    param_name = param_name.substr(1);
+                }
+
+                param_infos.push_back({ param_name, param_type });
+
+                // Vessző vagy zárójel következik?
+                if (match(Lexer::Tokens::Type::PUNCTUATION, ",")) {
+                    continue;
+                }
+                if (currentToken().type == Lexer::Tokens::Type::PUNCTUATION && currentToken().value == ")") {
+                    break;  // Lista vége
+                }
+                reportError("Expected ',' or ')' in parameter list");
+            }
+        }
+        // Most a ')' következik
+        expect(Lexer::Tokens::Type::PUNCTUATION, ")");
+
+        // check if we have a option return type: function name() type { ... }
+        for (const auto & _type : Parser::variable_types) {
+            if (match(_type.first)) {
+                func_return_type = _type.second;
+                break;
+            }
+        }
+
+        auto function_symbol =
+            Symbols::SymbolFactory::createFunction(func_name, "global", param_infos, "", func_return_type);
+        if (symbol_container_->exists("functions", func_name)) {
+            reportError("Function '" + func_name + "' already defined in this scope");
+        }
+
+        Lexer::Tokens::Token opening_brace = expect(Lexer::Tokens::Type::PUNCTUATION, "{");
+
+        symbol_container_->define("functions", function_symbol);
+
+        // only parse the body if we checked out if not exists the function and created the symbol
+        Symbols::SymbolContainer func_symbols =
+            parseFunctionBody(opening_brace, func_return_type != Symbols::Variables::Type::NULL_TYPE);
+
+        // create new container for the function
+
+        std::cout << "Defined function symbol: " << func_name << " in global scope.\n";
+
+        // 3. Új scope nyitása a függvény paraméterei (és később lokális változói) számára
+        symbol_container_->enterScope();
+        //std::cout << "Entered scope for function: " << func_name << "\n";
+
+        // 4. Paraméterek definiálása mint változók az *új* (függvény) scope-ban
+        const std::string & param_context = func_name;  // Paraméter kontextusa a függvény neve
+        for (const auto & p_info : param_infos) {
+            auto param_symbol = Symbols::SymbolFactory::createVariable(p_info.name,       // Név '$' nélkül
+                                                                       Symbols::Value(),  // Alapértelmezett/üres érték
+                                                                       param_context,     // Kontextus
+                                                                       p_info.type        // Típus
+            );
+
+            if (symbol_container_->exists("variables", p_info.name)) {
+                reportError("Parameter name '" + p_info.name + "' conflicts with another symbol in function '" +
+                            func_name + "'");
+            }
+            symbol_container_->define("variables", param_symbol);
+        }
+
+        // 5. Függvény scope elhagyása
+        symbol_container_->leaveScope();
+        //std::cout << "Left scope for function: " << func_name << "\n";
+
+        // Debugging kiírás (változatlan)
+        // std::cout << "Parsed function: " << func_name << " (...) { ... } scope handled.\n";
+    }
+
+    // --- Elemzési Segédfüggvények ---
+
+    // type : KEYWORD_STRING | KEYWORD_INT | KEYWORD_DOUBLE
+    // Visszaadja a megfelelő Symbols::Variables::Type enum értéket és elfogyasztja a tokent.
+    Symbols::Variables::Type parseType() {
+        const auto & token = currentToken();
+        for (const auto & _type : Parser::variable_types) {
+            if (token.type == _type.first) {
+                consumeToken();
+                return _type.second;
+            }
+        }
+
+        reportError("Expected type keyword (string, int, double, float)");
+    }
+
+    // value : STRING_LITERAL | NUMBER
+    // Feldolgozza az értéket a várt típus alapján.
+    Symbols::Value parseValue(Symbols::Variables::Type expected_var_type) {
+        Lexer::Tokens::Token token = currentToken();
+
+        /// find if this is a function call
+        if (token.type == Lexer::Tokens::Type::IDENTIFIER && peekToken().lexeme == "(") {
+            for (const auto & symbol_ptr : this->symbol_container_->listNamespace("functions")) {
+                if (auto func_symbol = std::dynamic_pointer_cast<Symbols::FunctionSymbol>(symbol_ptr)) {
+                    // TODO: A függvény hívását kellene feldolgozni, a func_symbol-ból kellene lekérni a paramétereket, func_symbol->plainBody() tartalmazza a függvény törzsét
+                    // A függvény hívásának feldolgozása
+                    std::cout << "Function call: " << token.value << "\n";
+                    while (consumeToken().lexeme != ")") {
+                        // Feltételezzük, hogy a függvény hívását a lexer már feldolgozta
+                    }
+                    return Symbols::Value("");  // TODO: Implementálni a függvény hívását
+                }
+            }
+        }
+
+        bool is_negative = false;
+        std::cout << "Peek: " << peekToken().lexeme << "\n";
+        if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC && peekToken().type == Lexer::Tokens::Type::NUMBER) {
+            is_negative = true;
+            token       = peekToken();
+            consumeToken();
+        }
+
+        if (expected_var_type == Symbols::Variables::Type::STRING) {
+            if (token.type == Lexer::Tokens::Type::STRING_LITERAL) {
+                consumeToken();
+                return Symbols::Value(token.value);  // A lexer value-ja már a feldolgozott string
+            }
+            reportError("Expected string literal value");
+        } else if (expected_var_type == Symbols::Variables::Type::INTEGER) {
+            if (token.type == Lexer::Tokens::Type::NUMBER) {
+                // Konvertálás int-re, hibakezeléssel
+                try {
+                    // TODO: Ellenőrizni, hogy a szám valóban egész-e (nincs benne '.')
+                    // Most egyszerűen std::stoi-t használunk.
+                    int int_value = std::stoi(token.value);
+                    if (is_negative) {
+                        int_value = -int_value;
+                    }
+                    consumeToken();
+                    return Symbols::Value(int_value);
+                } catch (const std::invalid_argument & e) {
+                    reportError("Invalid integer literal: " + token.value);
+                } catch (const std::out_of_range & e) {
+                    reportError("Integer literal out of range: " + token.value);
+                }
+            }
+            reportError("Expected integer literal value");
+        } else if (expected_var_type == Symbols::Variables::Type::DOUBLE) {
+            if (token.type == Lexer::Tokens::Type::NUMBER) {
+                // Konvertálás double-re, hibakezeléssel
+                try {
+                    double double_value = std::stod(token.value);
+                    if (is_negative) {
+                        double_value = -double_value;
+                    }
+                    consumeToken();
+                    return Symbols::Value(double_value);
+                } catch (const std::invalid_argument & e) {
+                    reportError("Invalid double literal: " + token.value);
+                } catch (const std::out_of_range & e) {
+                    reportError("Double literal out of range: " + token.value);
+                }
+            }
+            reportError("Expected numeric literal value for double");
+        } else if (expected_var_type == Symbols::Variables::Type::FLOAT) {
+            if (token.type == Lexer::Tokens::Type::NUMBER) {
+                // Konvertálás double-re, hibakezeléssel
+                try {
+
+                    float float_value = std::atof(token.value.data());
+                    if (is_negative) {
+                        float_value = -float_value;
+                    }
+                    consumeToken();
+                    return Symbols::Value(float_value);
+                } catch (const std::invalid_argument & e) {
+                    reportError("Invalid float literal: " + token.value);
+                } catch (const std::out_of_range & e) {
+                    reportError("Float literal out of range: " + token.value);
+                }
+            }
+            reportError("Expected numeric literal value for double");
+        } else if (expected_var_type == Symbols::Variables::Type::BOOLEAN) {
+            if (token.type == Lexer::Tokens::Type::KEYWORD) {
+                consumeToken();
+                return Symbols::Value(token.value == "true");  // A lexer value-ja már a feldolgozott string
+            }
+            reportError("Expected boolean literal value");
+        } else {
+            // Más típusok (pl. boolean) itt kezelendők, ha lennének
+            reportError("Unsupported variable type encountered during value parsing");
+        }
+        // Should not reach here due to reportError throwing
+        return Symbols::Value();  // Default return to satisfy compiler
+    }
+
+    Symbols::SymbolContainer parseFunctionBody(const Lexer::Tokens::Token & opening_brace,
+                                               bool                         return_required = false) {
+        size_t               braceDepth = 0;
+        int                  tokenIndex = current_token_index_;
+        Lexer::Tokens::Token currentToken_;
+        Lexer::Tokens::Token closing_brace;
+
+        while (tokenIndex < tokens_.size()) {
+            currentToken_ = peekToken();
+
+            if (currentToken_.type == Lexer::Tokens::Type::PUNCTUATION) {
+                if (currentToken_.value == "{") {
+                    ++braceDepth;
+                } else if (currentToken_.value == "}") {
+                    if (braceDepth == 0) {
+                        closing_brace = currentToken_;
+                        break;
+                    }
+                    --braceDepth;
+                }
+            }
+        }
+        if (braceDepth != 0) {
+            reportError("Unmatched braces in function body");
+        }
+        std::vector<Lexer::Tokens::Token> filtered_tokens;
+        auto                              startIt = std::find(tokens_.begin(), tokens_.end(), opening_brace);
+        auto                              endIt   = std::find(tokens_.begin(), tokens_.end(), closing_brace);
+
+        // Ellenőrzés: mindkét token megtalálva és start_token megelőzi az end_token-t
+        if (startIt != tokens_.end() && endIt != tokens_.end() && startIt < endIt) {
+            filtered_tokens = std::vector<Lexer::Tokens::Token>(startIt + 1, endIt);
+        }
+        std::string_view input_string = input_str_view_.substr(opening_brace.end_pos, closing_brace.end_pos);
+        auto             parser       = Parser();
+        parser.parseProgram(filtered_tokens, input_string);
+
+        return *parser.getSymbolContainer();
+    }
+
+    std::string parseFunctionBodyOld(size_t body_start_pos, bool return_required = false) {
+        std::stringstream body_ss;
+        int               brace_level        = 1;
+        size_t            last_token_end_pos = body_start_pos;
+        bool              has_return         = false;
+
+        while (true) {
+            if (isAtEnd()) {
+                reportError("Unexpected end of file inside function body (missing '}')");
+            }
+            const auto & token = currentToken();
+
+            // Whitespace visszaállítása (ha volt) az 'input_str_view_' alapján
+            if (token.start_pos > last_token_end_pos) {
+                if (last_token_end_pos < input_str_view_.length() && token.start_pos <= input_str_view_.length()) {
+                    body_ss << input_str_view_.substr(last_token_end_pos, token.start_pos - last_token_end_pos);
+                } else {
+                    reportError("Invalid position range in body reconstruction");
+                }
+            }
+
+            if (token.type == Lexer::Tokens::Type::KEYWORD_RETURN) {
+                has_return = true;
+            }
+
+            if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.value == "{") {
+                brace_level++;
+                body_ss << token.lexeme;
+            } else if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.value == "}") {
+                brace_level--;
+                if (brace_level == 0) {
+                    consumeToken();  // Záró '}' elfogyasztása
+                    break;
+                }
+                body_ss << token.lexeme;
+            } else {
+                body_ss << token.lexeme;
+            }
+
+            last_token_end_pos = token.end_pos;
+            consumeToken();
+        }
+
+        if (return_required && !has_return) {
+            return "";
+        }
+
+        return body_ss.str();
+    }
+
+};  // class Parser
+
+}  // namespace Parser
+
+#endif  // PARSER_HPP
diff --git a/src/ScriptException.hpp b/src/ScriptException.hpp
deleted file mode 100644
index d1f88c2..0000000
--- a/src/ScriptException.hpp
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef SCRIPTEXCEPTION_HPP
-#define SCRIPTEXCEPTION_HPP
-
-#include <stdexcept>
-#include <string>
-
-#include "options.h"
-#include "Token.hpp"
-
-enum class ScriptErrorType : std::uint8_t {
-    UnexpectedToken,
-    UndefinedVariable,
-    UndefinedFunction,
-    VariableTypeMismatch,
-    VariableRedefinition,
-    Custom
-};
-
-class ScriptException : public std::runtime_error {
-  public:
-    ScriptException(ScriptErrorType type, const std::string & message, const std::string & file = "", int line = 0,
-                    const Token & token = Token()) :
-        std::runtime_error(message),
-        type_(type),
-        file_(file),
-        line_(line),
-        token_(token),
-        fullMessage_(formatMessage(message)) {}
-
-    const char * what() const noexcept override { return fullMessage_.c_str(); }
-
-    ScriptErrorType type() const { return type_; }
-
-    const std::string & file() const { return file_; }
-
-    int line() const { return line_; }
-
-    const Token & token() const { return token_; }
-
-    static ScriptException makeUnexpectedEndOfFileError(const Token & token, const std::string & file = "",
-                                                        int line = 0) {
-        std::string msg = "unexpected end of file";
-        if (!token.lexeme.empty()) {
-            msg += " near '" + token.lexeme + "'";
-        }
-        return ScriptException(ScriptErrorType::UnexpectedToken, msg, file, line, token);
-    }
-
-    static ScriptException makeUnexpectedTokenError(const Token & token, const std::string & expected = "",
-                                                    const std::string & file = "", int line = 0) {
-        std::string msg = "unexpected token: '" + token.lexeme + "'";
-
-#if DEBUG_BUILD == 1
-        msg.append(" token type: " + tokenTypeNames.at(token.type));
-#endif
-
-        if (!expected.empty()) {
-            msg += ", expected " + expected;
-        }
-        return ScriptException(ScriptErrorType::UnexpectedToken, msg, file, line, token);
-    }
-
-    static ScriptException makeUndefinedVariableError(const std::string & name, const Token & token,
-                                                      const std::string & file = "", int line = 0) {
-        std::string msg = "undefined variable: '$" + name + "'";
-        return ScriptException(ScriptErrorType::UndefinedVariable, msg, file, line, token);
-    }
-
-    static ScriptException makeUndefinedFunctionError(const std::string & name, const Token & token,
-                                                      const std::string & file = "", int line = 0) {
-        std::string msg = "undefined function: '" + name + "'";
-#if DEBUG_BUILD == 1
-        msg.append(", type: " + getTokenTypeAsString(token.type));
-#endif
-        return ScriptException(ScriptErrorType::UndefinedFunction, msg, file, line, token);
-    }
-
-    static ScriptException makeVariableRedefinitionError(const std::string & name, const Token & token,
-                                                         const std::string & file = "", int line = 0) {
-        std::string msg = "variable already defined: '" + name + "'";
-        return ScriptException(ScriptErrorType::VariableRedefinition, msg, file, line, token);
-    }
-
-    static ScriptException makeVariableTypeMismatchError(const std::string & targetVar, const std::string & targetType,
-                                                         const std::string & sourceVar, const std::string & sourceType,
-                                                         const Token & token, const std::string & file = "",
-                                                         int line = 0) {
-        std::string msg = "variable type mismatch: '$" + targetVar + "' declared type: '" + targetType + "'";
-        if (!sourceVar.empty()) {
-            msg += ", source variable: '" + sourceVar + "'";
-        }
-        if (!sourceType.empty()) {
-            msg += ", assigned type: '" + sourceType + "'";
-        }
-        return ScriptException(ScriptErrorType::VariableTypeMismatch, msg, file, line, token);
-    }
-
-    static ScriptException makeFunctionRedefinitionError(const std::string & name, const Token & token,
-                                                         const std::string & file = "", int line = 0) {
-        std::string msg = "variable already defined: '" + name + "'";
-        return ScriptException(ScriptErrorType::VariableRedefinition, msg, file, line, token);
-    }
-
-    static ScriptException makeFunctionInvalidArgumentError(const std::string & functionName,
-                                                            const std::string & argName, const Token & token,
-                                                            const std::string & file = "", int line = 0) {
-        std::string msg = "invalid argument for function '" + functionName + "': '" + argName + "'";
-        return ScriptException(ScriptErrorType::Custom, msg, file, line, token);
-    }
-
-    static ScriptException makeFunctionArgumentCountMismatchError(const std::string & functionName,
-                                                                  const size_t & expected, size_t actual,
-                                                                  const Token & token, const std::string & file = "",
-                                                                  int line = 0) {
-        std::string msg = "invalid argument count for function '" + functionName + "', expected " +
-                          std::to_string(expected) + ", got " + std::to_string(actual);
-        return ScriptException(ScriptErrorType::Custom, msg, file, line, token);
-    }
-
-    static ScriptException makeFunctionBodyEmptyError(const std::string & functionName, const Token & token,
-                                                      const std::string & file = "", int line = 0) {
-        std::string msg = "function '" + functionName + "' has no body";
-        return ScriptException(ScriptErrorType::Custom, msg, file, line, token);
-    }
-
-  private:
-    ScriptErrorType type_;
-    std::string     file_;
-    int             line_;
-    Token           token_;
-    std::string     fullMessage_;
-
-    std::string formatMessage(const std::string & base) const {
-        std::string formatted = base;
-        if (!token_.file.empty()) {
-            formatted += " in file: " + token_.file + ":" + std::to_string(token_.lineNumber) + ":" +
-                         std::to_string(token_.columnNumber);
-        }
-#if DEBUG_BUILD == 1
-        if (!file_.empty()) {
-            formatted = file_ + ":" + std::to_string(line_) + "\n" + formatted;
-        }
-#endif
-        return formatted;
-    }
-};
-
-#endif  // SCRIPTEXCEPTION_HPP
diff --git a/src/ScriptExceptionMacros.h b/src/ScriptExceptionMacros.h
deleted file mode 100644
index d0263ed..0000000
--- a/src/ScriptExceptionMacros.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef SCRIPT_EXCEPTION_MACROS_H
-#define SCRIPT_EXCEPTION_MACROS_H
-
-#include "ScriptException.hpp"
-
-//
-// Purpose of macros: unified exception handling with extended error information (source file and line number)
-//
-#define THROW_UNEXPECTED_END_OF_FILE_ERROR(token) \
-    throw ScriptException::makeUnexpectedEndOfFileError(token, __FILE__, __LINE__)
-
-// Invalid token type - expected different type
-#define THROW_UNEXPECTED_TOKEN_ERROR(token, expected) \
-    throw ScriptException::makeUnexpectedTokenError(token, expected, __FILE__, __LINE__)
-
-#define THROW_UNEXPECTED_TOKEN_ERROR_HELPER(token, expected, file, line) \
-    throw ScriptException::makeUnexpectedTokenError(token, expected, file, line)
-
-// Accessing unknown (undefined) variable
-#define THROW_UNDEFINED_VARIABLE_ERROR(name, token) \
-    throw ScriptException::makeUndefinedVariableError(name, token, __FILE__, __LINE__)
-
-#define THROW_UNDEFINED_VARIABLE_ERROR_HELPER(name, token, file, line) \
-    throw ScriptException::makeUndefinedVariableError(name, token, file, line)
-
-// Unknown (undefined) function call
-#define THROW_UNDEFINED_FUNCTION_ERROR(name, token) \
-    throw ScriptException::makeUndefinedFunctionError(name, token, __FILE__, __LINE__)
-
-// Variable type mismatch - e.g. string instead of number
-#define THROW_VARIABLE_TYPE_MISSMATCH_ERROR(target_variable_name, target_variable_type, source_variable_name,         \
-                                            source_variable_type, token)                                              \
-    throw ScriptException::makeVariableTypeMismatchError(target_variable_name, target_variable_type,                  \
-                                                         source_variable_name, source_variable_type, token, __FILE__, \
-                                                         __LINE__)
-
-// Redefining a variable with the same name is not allowed
-#define THROW_VARIABLE_REDEFINITION_ERROR(name, token) \
-    throw ScriptException::makeVariableRedefinitionError(name, token, __FILE__, __LINE__)
-
-#define THROW_FUNCTION_REDEFINITION_ERROR(name, token) \
-    throw ScriptException::makeFunctionRedefinitionError(name, token, __FILE__, __LINE__)
-
-// Invalid or incorrect function argument
-#define THROW_INVALID_FUNCTION_ARGUMENT_ERROR(functionName, argName, token) \
-    throw ScriptException::makeFunctionInvalidArgumentError(functionName, argName, token, __FILE__, __LINE__)
-
-#define THROW_FUNCTION_ARG_COUNT_MISMATCH_ERROR(functionName, expected, actual, token)                             \
-    throw ScriptException::makeFunctionArgumentCountMismatchError(functionName, expected, actual, token, __FILE__, \
-                                                                  __LINE__)
-
-#define THROW_FUNCTION_BODY_EMPTY(funcName, token) \
-    throw ScriptException::makeFunctionBodyEmptyError(funcName, token, __FILE__, __LINE__)
-
-#endif  // SCRIPT_EXCEPTION_MACROS_H
diff --git a/src/ScriptInterpreter.cpp b/src/ScriptInterpreter.cpp
deleted file mode 100644
index 8af8d43..0000000
--- a/src/ScriptInterpreter.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-#include "ScriptInterpreter.hpp"
-
-#include <iostream>
-#include <stdexcept>
-#include <unordered_map>
-#include <utility>
-
-#include "Lexer.hpp"
-#include "ScriptExceptionMacros.h"
-#include "Value.hpp"
-
-void ScriptInterpreter::registerModule(const std::string & name, std::shared_ptr<BaseFunction> fn) {
-    functionObjects[name] = std::move(fn);
-}
-
-Value ScriptInterpreter::evaluateExpression(const Token & token) const {
-    switch (token.type) {
-        case TokenType::StringLiteral:
-            return Value::fromString(token);
-
-        case TokenType::IntLiteral:
-            try {
-                return Value::fromInt(token);
-            } catch (const std::invalid_argument & e) {
-                throw std::runtime_error("Invalid integer literal: " + token.lexeme);
-            } catch (const std::out_of_range & e) {
-                throw std::runtime_error("Integer literal out of range: " + token.lexeme);
-            }
-
-        case TokenType::DoubleLiteral:
-            try {
-                return Value::fromDouble(token);
-            } catch (const std::invalid_argument & e) {
-                throw std::runtime_error("Invalid double literal: " + token.lexeme);
-            } catch (const std::out_of_range & e) {
-                throw std::runtime_error("Double literal out of range: " + token.lexeme);
-            }
-
-        case TokenType::BooleanLiteral:
-        case TokenType::Identifier:
-            {
-                return Value::fromBoolean(token);
-            }
-
-        case TokenType::Variable:
-            return this->getVariable(token, this->contextPrefix, __FILE__, __LINE__);
-
-        default:
-            THROW_UNEXPECTED_TOKEN_ERROR(token, "string, integer, double, or variable");
-    }
-
-    return Value();
-}
-
-std::vector<Value> ScriptInterpreter::parseFunctionArguments(const std::vector<Token> & tokens,
-                                                             std::size_t &              index) const {
-    std::vector<Value> args;
-    size_t             current_index = index;
-
-    if (current_index >= tokens.size() || tokens[current_index].type != TokenType::LeftParenthesis) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[current_index], tokenTypeNames.at(TokenType::LeftParenthesis));
-    }
-    current_index++;  // Skip '('
-
-    while (current_index < tokens.size() && tokens[current_index].type != TokenType::RightParenthesis) {
-        args.push_back(evaluateExpression(tokens[current_index]));
-        current_index++;
-        if (current_index < tokens.size() && tokens[current_index].type == TokenType::Comma) {
-            current_index++;  // Skip ','
-            if (current_index >= tokens.size() || tokens[current_index].type == TokenType::RightParenthesis) {
-                THROW_UNEXPECTED_TOKEN_ERROR(tokens[current_index], "expression after comma");
-            }
-        } else if (tokens[current_index].type != TokenType::RightParenthesis && current_index < tokens.size()) {
-            THROW_UNEXPECTED_TOKEN_ERROR(tokens[current_index], "',' or ')'");
-        }
-    }
-
-    if (current_index >= tokens.size() || tokens[current_index].type != TokenType::RightParenthesis) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[current_index], "')'");
-    }
-    current_index++;  // Skip ')'
-    index = current_index;
-
-    return args;
-}
-
-void ScriptInterpreter::handleBooleanDeclaration(const std::vector<Token> & tokens, size_t & i) {
-    if (tokens.size() <= i || tokens[i].type != TokenType::Identifier) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "variable name");
-    }
-
-    const Token & varToken = tokens[i++];
-    if (i >= tokens.size()) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i + 1], "semicolon or assignment after variable name");
-    }
-
-    if (tokens[i].type == TokenType::Semicolon) {
-        auto val = Value::fromBoolean(tokens[i]);
-        this->setVariable(varToken.lexeme, val, this->contextPrefix, true);
-        i++;
-    } else if (tokens[i].type == TokenType::Equal) {
-        i++;
-        if (i >= tokens.size()) {
-            //throw InterpreterException("Expected value after assignment.", tokens[i - 1]);
-            THROW_UNEXPECTED_TOKEN_ERROR(tokens[i - 1], "value after assignment");
-        }
-
-        auto value = evaluateExpression(tokens[i]);
-        if (value.type != Variables::Type::VT_BOOLEAN) {
-            THROW_VARIABLE_TYPE_MISSMATCH_ERROR(varToken.lexeme, Variables::TypeToString(Variables::Type::VT_BOOLEAN),
-                                                tokens[i].lexeme, value.TypeToString(), tokens[i]);
-        }
-        this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
-        i++;
-        EXPECT_SEMICOLON(tokens, i, "after bool declaration");
-    } else {
-        EXPECT_SEMICOLON(tokens, i, "after bool declaration");
-    }
-}
-
-void ScriptInterpreter::handleStringDeclaration(const std::vector<Token> & tokens, std::size_t & i) {
-    const auto & varToken = tokens[i];
-
-    i++;      // Skip variable name
-    if (i < tokens.size() && tokens[i].type == TokenType::Equals) {
-        i++;  // Skip '='
-
-        if (i < tokens.size() && tokens[i].type == TokenType::Variable) {
-            const auto variable = this->getVariable(tokens[i], this->contextPrefix, __FILE__, __LINE__);
-
-            if (variable.type != Variables::Type::VT_STRING) {
-                THROW_VARIABLE_TYPE_MISSMATCH_ERROR(varToken.lexeme,
-                                                    Variables::TypeToString(Variables::Type::VT_STRING),
-                                                    tokens[i].lexeme, variable.TypeToString(), tokens[i]);
-            }
-            auto value = variable;
-            this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
-            i++;  // Skip variable name
-            EXPECT_SEMICOLON(tokens, i, "after string variable declaration");
-
-        } else if (i < tokens.size() && tokens[i].type == TokenType::StringLiteral) {
-            auto value = Value::fromString(tokens[i]);
-            this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
-            i++;  // Skip string literal
-            EXPECT_SEMICOLON(tokens, i, "after string declaration");
-        } else {
-            THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "string literal after '='");
-        }
-    } else {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "= after string declaration");
-    }
-}
-
-void ScriptInterpreter::handleNumberDeclaration(const std::vector<Token> & tokens, std::size_t & i, TokenType type) {
-    const auto & varToken = tokens[i];
-
-    i++;      // Skip variable name
-    if (i < tokens.size() && tokens[i].type == TokenType::Equals) {
-        i++;  // Skip '='
-        if (i < tokens.size()) {
-            if (type == TokenType::IntDeclaration && tokens[i].type == TokenType::IntLiteral) {
-                try {
-                    auto value = Value::fromInt(tokens[i]);
-                    this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
-                    i++;  // Skip int literal
-                } catch (const std::invalid_argument & e) {
-                    throw std::runtime_error("Invalid integer literal in declaration: " + tokens[i].lexeme);
-                } catch (const std::out_of_range & e) {
-                    throw std::runtime_error("Integer literal out of range in declaration: " + tokens[i].lexeme);
-                }
-            } else if (type == TokenType::DoubleDeclaration && tokens[i].type == TokenType::DoubleLiteral) {
-                try {
-                    auto value = Value::fromDouble(tokens[i]);
-                    this->setVariable(varToken.lexeme, value, this->contextPrefix, true);
-                    i++;  // Skip double literal
-                } catch (const std::invalid_argument & e) {
-                    throw std::runtime_error("Invalid double literal in declaration: " + tokens[i].lexeme);
-                } catch (const std::out_of_range & e) {
-                    throw std::runtime_error("Double literal out of range in declaration: " + tokens[i].lexeme);
-                }
-            } else {
-                const std::string expectedType = type == TokenType::IntDeclaration ? "int" : "double";
-                THROW_VARIABLE_TYPE_MISSMATCH_ERROR(varToken.lexeme, expectedType, "",
-                                                    getVariableTypeFromTokenTypeAsString(tokens[i].type), tokens[i]);
-            }
-            EXPECT_SEMICOLON(tokens, i, "after variable declaration");
-        } else {
-            THROW_UNEXPECTED_TOKEN_ERROR(tokens[i - 1], "literal after '='");
-        }
-    } else {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "= after variable declaration, variable name: " + varToken.lexeme);
-    }
-}
-
-void ScriptInterpreter::handleFunctionDeclaration(const std::vector<Token> & tokens, std::size_t & i) {
-    const auto & funcToken = tokens[i];
-
-    i++;  // skip funct name
-
-    if (i < tokens.size() && tokens[i].type != TokenType::Equals) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "= after function declaration");
-    }
-    i++;  // skip '='
-
-    if (this->functionBodies.find(funcToken.lexeme) != this->functionBodies.end()) {
-        THROW_FUNCTION_REDEFINITION_ERROR(funcToken.lexeme, tokens[i]);
-    }
-
-    if (i < tokens.size() && tokens[i].type != TokenType::LeftParenthesis) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i - 1], "");
-    }
-    i++;
-    // parse arg definitions
-    const std::string context_name = this->getContextName(funcToken.lexeme);
-    const auto        args = ScriptInterpreterHelpers::parseFunctionDeclarationArguments(tokens, i, __FILE__, __LINE__);
-    for (const auto & arg : args) {
-        auto value = arg;
-        this->setVariable(arg.GetToken().lexeme, value, context_name, true);
-    }
-
-    size_t start;
-    size_t end;
-    ScriptInterpreterHelpers::getFunctionBody(tokens, i, start, end);
-
-    const std::string function_body = StringHelpers::extractSubstring(this->source, start, end);
-    if (function_body.empty()) {
-        std::cout << this->source << '\n';
-        THROW_FUNCTION_BODY_EMPTY(funcToken.lexeme, tokens[i - 1]);
-    }
-    this->functionBodies[funcToken.lexeme] = function_body;
-    // recheck the close curly brace
-    if (i >= tokens.size() || tokens[i].type != TokenType::RightCurlyBracket) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "}");
-    }
-    i++;
-}
-
-void ScriptInterpreter::handleFunctionCall(const std::vector<Token> & tokens, std::size_t & i) {
-    const auto & functiontoken = tokens[i];
-
-    i++;  // skip funct name
-    if (i < tokens.size() && tokens[i].type != TokenType::LeftParenthesis) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i - 1], "");
-    }
-
-    std::vector<Value> args = parseFunctionArguments(tokens, i);
-
-    auto it1 = functionObjects.find(functiontoken.lexeme);
-    if (it1 != functionObjects.end()) {
-        it1->second->call(args);
-    } else {
-        auto it2 = functionBodies.find(functiontoken.lexeme);
-        if (it2 == functionBodies.end()) {
-            THROW_UNDEFINED_FUNCTION_ERROR(functiontoken.lexeme, tokens[i]);
-        }
-
-        if (args.size() > 0) {
-            auto varList = this->getcontextVariables(this->getContextName(functiontoken.lexeme));
-            if (varList.size() != args.size()) {
-                THROW_FUNCTION_ARG_COUNT_MISMATCH_ERROR(functiontoken.lexeme, varList.size(), args.size(), tokens[i]);
-            }
-            size_t counter = 0;
-            for (auto & var : varList) {
-                this->setVariable(var.first, args[counter], var.second.context, false, true);
-                counter++;
-            }
-        }
-
-        this->executeScript(it2->second, this->filename, functiontoken.lexeme, true);
-    }
-
-    //i++;
-
-    EXPECT_SEMICOLON(tokens, i, "after function call");
-}
-
-void ScriptInterpreter::handleVariableReference(const std::vector<Token> & tokens, std::size_t & i) {
-    const auto & varToken = tokens[i];
-    i++;      // Skip variable token to avoid infinite loop
-    if (i < tokens.size() && tokens[i].type == TokenType::Equals) {
-        i++;  // Skip '='
-        if (i < tokens.size()) {
-            const auto variable = this->getVariable(varToken, this->contextPrefix, __FILE__, __LINE__);
-            auto       value    = evaluateExpression(tokens[i]);
-            this->setVariable(varToken.lexeme, value, this->contextPrefix, false);
-            i++;  // Skip value
-            EXPECT_SEMICOLON(tokens, i, "after variable assignment");
-        } else {
-            THROW_UNEXPECTED_TOKEN_ERROR(tokens[i - 1], "value after '='");
-        }
-    } else {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i - 1], "'=' for assignment");
-    }
-}
-
-void ScriptInterpreter::executeScript(const std::string & source, const std::string & filename,
-                                      const std::string & _namespace, bool ignore_tags) {
-    std::string oldContext;
-    std::string oldSource;
-
-    this->filename = filename;
-    if (!this->source.empty()) {
-        oldSource = this->source;
-    }
-    this->source = source;
-
-    if (!this->contextPrefix.empty()) {
-        oldContext = this->contextPrefix;
-    }
-    this->contextPrefix = this->getContextName(_namespace);
-    Lexer lexer(source, filename);
-    auto  tokens = lexer.tokenize();
-
-    bool insideScript = false;
-
-    for (std::size_t i = 0; i < tokens.size();) {
-        const auto & token = tokens[i];
-
-        if (token.type == TokenType::EndOfFile) {
-            break;
-        }
-
-        if (token.type == TokenType::ParserOpenTag) {
-            insideScript = true;
-            i++;  // Skip the open tag
-            continue;
-        }
-
-        if (token.type == TokenType::ParserCloseTag) {
-            insideScript = false;
-            i++;  // Skip the close tag
-            continue;
-        }
-
-        if (insideScript == false && ignore_tags == false) {
-            //std::cout << token.lexeme;
-            i++;
-            continue;
-        }
-
-        switch (token.type) {
-            case TokenType::StringDeclaration:
-                handleStringDeclaration(tokens, i);
-                break;
-            case TokenType::BooleanDeclaration:
-                handleBooleanDeclaration(tokens, i);
-                break;
-            case TokenType::FunctionDeclaration:
-                handleFunctionDeclaration(tokens, i);
-                break;
-            case TokenType::IntDeclaration:
-            case TokenType::DoubleDeclaration:
-                handleNumberDeclaration(tokens, i, token.type);
-                break;
-            case TokenType::FunctionCall:
-                handleFunctionCall(tokens, i);
-                break;
-            case TokenType::Variable:
-                handleVariableReference(tokens, i);
-                break;
-            case TokenType::Comment:
-                handleComment(i);
-                break;
-            case TokenType::Semicolon:
-                handleSemicolon(i);
-                break;
-            default:
-                THROW_UNEXPECTED_TOKEN_ERROR(token, "");
-        }
-    }
-    if (!oldContext.empty()) {
-        this->contextPrefix = oldContext;
-        oldContext.clear();
-    }
-    if (!oldSource.empty()) {
-        this->source = oldSource;
-        oldSource.clear();
-    }
-}
diff --git a/src/ScriptInterpreter.hpp b/src/ScriptInterpreter.hpp
deleted file mode 100644
index b8077bd..0000000
--- a/src/ScriptInterpreter.hpp
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef SSCRIPTINTERPRETER_HPP
-#define SSCRIPTINTERPRETER_HPP
-#include <functional>
-#include <map>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "BaseFunction.hpp"
-#include "Token.hpp"
-#include "Value.hpp"
-
-using FunctionValidator =
-    std::function<void(const std::vector<Token> &, size_t &, const std::unordered_map<std::string, Value> &)>;
-using VariableContext = std::map<std::string, Value>;
-
-class ScriptInterpreter {
-  public:
-    void registerModule(const std::string & name, std::shared_ptr<BaseFunction> fn);
-    void executeScript(const std::string & source, const std::string & filename,
-                       const std::string & _namespace = "DEFAULT", bool ignore_tags = false);
-
-  private:
-    std::unordered_map<std::string, FunctionValidator>             functionValidators;
-    std::unordered_map<std::string, std::shared_ptr<BaseFunction>> functionObjects;
-    // store the current script's variables
-    std::unordered_map<std::string, VariableContext>               variables;
-    // store the current script's function arguments
-    std::unordered_map<std::string, std::vector<Value>>            functionParameters;
-    std::unordered_map<std::string, std::string>                   functionBodies;
-    std::string                                                    filename;
-    std::string                                                    source;
-    std::string                                                    contextPrefix;
-
-    [[nodiscard]] std::vector<Value> parseFunctionArguments(const std::vector<Token> & tokens,
-                                                            std::size_t &              index) const;
-    [[nodiscard]] Value              evaluateExpression(const Token & token) const;
-
-    // type handlers
-    void setVariable(const std::string & name, Value & value, const std::string & context = "default",
-                     bool exception_if_exists = false, bool exception_if_not_exists = false) {
-        if (exception_if_exists && variables[context].find(name) != variables[context].end()) {
-            THROW_VARIABLE_REDEFINITION_ERROR(name, value.token);
-        }
-        if (exception_if_not_exists && variables[context].find(name) == variables[context].end()) {
-            THROW_UNDEFINED_VARIABLE_ERROR(name, value.token);
-        }
-        value.name                     = name;
-        value.context                  = context;
-        this->variables[context][name] = value;
-    }
-
-    [[nodiscard]] Value getVariable(const std::string & name, const std::string & context = "default") const {
-        for (auto it = variables.begin(); it != variables.end(); ++it) {
-            if (it->first == context) {
-                const auto & innerMap = it->second.find(name);
-                if (innerMap != it->second.end()) {
-                    return it->second.at(name);
-                }
-            }
-        }
-        throw std::runtime_error("Variable not found: " + name);
-    };
-
-    [[nodiscard]] Value getVariable(const Token & token, const std::string & context = "default",
-                                    const std::string & file = __FILE__, const int & line = __LINE__) const {
-        for (auto it = variables.begin(); it != variables.end(); ++it) {
-            if (it->first == context) {
-                const auto & innerMap = it->second.find(token.lexeme);
-                if (innerMap != it->second.end()) {
-                    return it->second.at(token.lexeme);
-                }
-            }
-        }
-        THROW_UNDEFINED_VARIABLE_ERROR_HELPER(token.lexeme, token, file, line);
-    };
-
-    [[nodiscard]] std::map<std::string, Value> getcontextVariables(const std::string & context) const {
-        auto it = variables.find(context);
-        if (it != variables.end()) {
-            return it->second;
-        }
-        throw std::runtime_error("Context not found: " + context);
-    }
-
-    /**
-         * Checks if a variable exists within the specified context.
-         *
-         * @param name The name of the variable to check.
-         * @param context The context in which to search for the variable (defaults to "default").
-         * @param file The source file where the check is performed (for error reporting).
-         * @param line The line number where the check is performed (for error reporting).
-         * @return True if the variable exists in the specified context.
-         * @throws Throws an undefined variable error if the variable is not found.
-         */
-    [[nodiscard]] bool variableExists(const std::string & name, const std::string & context = "default",
-                                      const std::string & file = __FILE__, const int & line = __LINE__) const {
-        for (auto it = variables.begin(); it != variables.end(); ++it) {
-            if (it->first == context) {
-                const auto & innerMap = it->second.find(name);
-                if (innerMap != it->second.end()) {
-                    return true;
-                }
-            }
-        }
-        THROW_UNDEFINED_VARIABLE_ERROR_HELPER(name, Token(TokenType::Variable, name, name, 0, 0), file, line);
-    }
-
-    /**
-     * Checks if a variable exists within the specified context using a Token.
-     *
-     * @param token The token representing the variable to check.
-     * @param context The context in which to search for the variable (defaults to "default").
-     * @param file The source file where the check is performed (for error reporting).
-     * @param line The line number where the check is performed (for error reporting).
-     * @return True if the variable exists in the specified context.
-     * @throws Throws an undefined variable error if the variable is not found.
-     */
-    [[nodiscard]] bool variableExists(const Token & token, const std::string & context = "default",
-                                      const std::string & file = __FILE__, const int & line = __LINE__) const {
-        return this->variableExists(token.lexeme, context, file, line);
-    }
-
-    void handleFunctionCall(const std::vector<Token> & tokens, std::size_t & i);
-    void handleVariableReference(const std::vector<Token> & tokens, std::size_t & i);
-
-    static void handleComment(std::size_t & i) { i++; }
-
-    static void handleSemicolon(std::size_t & i) { i++; };
-
-    void handleStringDeclaration(const std::vector<Token> & tokens, std::size_t & i);
-    void handleBooleanDeclaration(const std::vector<Token> & tokens, std::size_t & i);
-    void handleNumberDeclaration(const std::vector<Token> & tokens, std::size_t & i, TokenType type);
-    void handleFunctionDeclaration(const std::vector<Token> & tokens, std::size_t & i);
-
-    std::string getContextName(const std::string & suffix) const { return this->filename + "::" + suffix; }
-};
-
-#endif  // SSCRIPTINTERPRETER_HPP
diff --git a/src/ScriptInterpreterHelpers.hpp b/src/ScriptInterpreterHelpers.hpp
deleted file mode 100644
index a8567fc..0000000
--- a/src/ScriptInterpreterHelpers.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-#ifndef SCRIPTINTERPRETERHELPERS_HPP
-#define SCRIPTINTERPRETERHELPERS_HPP
-
-#include <algorithm>
-#include <vector>
-
-#include "ScriptExceptionMacros.h"
-#include "Token.hpp"
-#include "Value.hpp"
-
-#define EXPECT_SEMICOLON(tokens, i, message) \
-    ScriptInterpreterHelpers::expectSemicolon(tokens, i, message, __FILE__, __LINE__)
-
-namespace ScriptInterpreterHelpers {
-
-
-
-static void expectSemicolon(const std::vector<Token> & tokens, std::size_t & i, const std::string & message,
-                            const std::string & file = __FILE__, int line = __LINE__) {
-    if (i >= tokens.size() || tokens[i].type != TokenType::Semicolon) {
-        THROW_UNEXPECTED_TOKEN_ERROR_HELPER(tokens[i - 1], "; " + message, file, line);
-    }
-    i++;  // Skip ';'
-}
-
-[[nodiscard]] static std::vector<Value> parseFunctionDeclarationArguments(const std::vector<Token> & tokens,
-                                                                          std::size_t &              i,
-                                                                          const std::string &        file = __FILE__,
-                                                                          int                        line = __LINE__) {
-    std::vector<Value> arguments;
-
-    // check the arguments types
-    if (tokens[i].type != TokenType::StringDeclaration && tokens[i].type != TokenType::BooleanDeclaration &&
-        tokens[i].type != TokenType::IntDeclaration && tokens[i].type != TokenType::DoubleDeclaration &&
-        tokens[i].type != TokenType::RightParenthesis) {
-        THROW_UNEXPECTED_TOKEN_ERROR_HELPER(tokens[i], "variable declaration: 'type $" + tokens[i].lexeme + "'", file,
-                                            line);
-    }
-    if (tokens[i].type != TokenType::RightParenthesis) {
-        const auto parameter_type = getVariableTypeFromTokenTypeDeclaration(tokens[i].type);
-        if (parameter_type == Variables::Type::VT_NOT_DEFINED) {
-            THROW_UNEXPECTED_TOKEN_ERROR_HELPER(tokens[i], "valid type identifier", file, line);
-        }
-
-        //   if (parameter_type == Variables::Type::VT_FUNCTION) {
-        //       THROW_UNEXPECTED_TOKEN_ERROR_HELPER(tokens[i], "valid type identifier", file, line);
-        //   }
-
-        if (parameter_type == Variables::Type::VT_NULL) {
-            THROW_UNEXPECTED_TOKEN_ERROR_HELPER(tokens[i], "valid type identifier", file, line);
-        }
-
-        Value val;
-        val.type  = parameter_type;
-        val.token = tokens[i];
-
-        arguments.emplace_back(std::move(val));
-        i++;  // Skip variable declaration
-    }
-
-    if (tokens[i].type != TokenType::RightParenthesis) {
-        THROW_UNEXPECTED_TOKEN_ERROR_HELPER(tokens[i], ") - Only one argument is allowed", file, line);
-    }
-    i++;  // Skip ')'
-
-    return arguments;
-}
-
-static void getFunctionBody(const std::vector<Token> & tokens, std::size_t & i, std::size_t & start,
-                            std::size_t & end) {
-    start = tokens[i].pos.end;
-    if (i >= tokens.size() || tokens[i].type != TokenType::LeftCurlyBracket) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "{");
-    }
-    i++;  // Skip '{'
-
-    while (i < tokens.size() && tokens[i].type != TokenType::RightCurlyBracket) {
-        if (tokens[i].type == TokenType::EndOfLine) {
-            i++;
-            continue;
-        }
-        if (tokens[i].type == TokenType::EndOfFile) {
-            THROW_UNEXPECTED_END_OF_FILE_ERROR(tokens[i]);
-            break;
-        }
-        i++;
-    }
-    end = tokens[i].pos.start - 1;
-
-    if (i >= tokens.size() || tokens[i].type != TokenType::RightCurlyBracket) {
-        THROW_UNEXPECTED_TOKEN_ERROR(tokens[i], "}");
-    }
-};
-
-
-};  // namespace ScriptInterpreterHelpers
-
-#endif  // SCRIPTINTERPRETERHELPERS_HPP
diff --git a/src/StringHelpers.hpp b/src/StringHelpers.hpp
deleted file mode 100644
index 937959f..0000000
--- a/src/StringHelpers.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef STRINGHELPERS_HPP
-#define STRINGHELPERS_HPP
-#include <algorithm>
-#include <string>
-
-namespace StringHelpers {
-
-static std::string extractSubstring(const std::string & str, const size_t & start, const size_t & end) {
-    if (start >= 0 && start < str.length() && end >= start && end < str.length()) {
-        return str.substr(start, end - start + 1);
-    }
-    return "";
-}
-
-static void strtolower(std::string & data) {
-    std::transform(data.begin(), data.end(), data.begin(), [](unsigned char c) { return std::tolower(c); });
-}
-
-};  // namespace StringHelpers
-#endif  // STRINGHELPERS_HPP
diff --git a/include/BaseSymbol.hpp b/src/Symbols/BaseSymbol.hpp
similarity index 92%
rename from include/BaseSymbol.hpp
rename to src/Symbols/BaseSymbol.hpp
index b326e4b..2d3cdb2 100644
--- a/include/BaseSymbol.hpp
+++ b/src/Symbols/BaseSymbol.hpp
@@ -3,13 +3,11 @@
 #define BASE_SYMBOL_HPP
 
 #include <string>
-#include <variant>
 
 #include "SymbolKind.hpp"
+#include "Value.hpp"
 
 namespace Symbols {
-
-using Value = std::variant<int, double, std::string, bool>;
 
 class Symbol {
   protected:
diff --git a/include/ConstantSymbol.hpp b/src/Symbols/ConstantSymbol.hpp
similarity index 100%
rename from include/ConstantSymbol.hpp
rename to src/Symbols/ConstantSymbol.hpp
diff --git a/src/Symbols/FunctionSymbol.hpp b/src/Symbols/FunctionSymbol.hpp
new file mode 100644
index 0000000..255b0af
--- /dev/null
+++ b/src/Symbols/FunctionSymbol.hpp
@@ -0,0 +1,41 @@
+// FunctionSymbol.hpp
+#ifndef FUNCTION_SYMBOL_HPP
+#define FUNCTION_SYMBOL_HPP
+
+#include <vector>
+
+#include "BaseSymbol.hpp"
+#include "Lexer/Token.hpp"
+#include "Symbols/ParameterContainer.hpp"
+#include "Symbols/VariableTypes.hpp"
+
+namespace Symbols {
+
+class FunctionSymbol : public Symbol {
+    // store the variables name and type
+    FunctionParameterInfo             parameters_;
+    Symbols::Variables::Type          returnType_;
+    std::string                       plainBody_;
+    std::vector<Lexer::Tokens::Token> tokens_;
+
+  public:
+    FunctionSymbol(const std::string & name, const std::string & context, const FunctionParameterInfo & parameters,
+                   const std::string &      plainbody  = "",
+                   Symbols::Variables::Type returnType = Symbols::Variables::Type::NULL_TYPE) :
+        Symbol(name, {}, context, Symbols::Kind::Function),
+        parameters_(parameters),
+        plainBody_(plainbody),
+        returnType_(returnType) {}
+
+    Symbols::Kind kind() const override { return Symbols::Kind::Function; }
+
+    Symbols::Variables::Type returnType() const { return returnType_; }
+
+    const FunctionParameterInfo & parameters() const { return parameters_; }
+
+    const std::string & plainBody() const { return plainBody_; }
+};
+
+}  // namespace Symbols
+
+#endif
diff --git a/src/Symbols/ParameterContainer.hpp b/src/Symbols/ParameterContainer.hpp
new file mode 100644
index 0000000..65f05f7
--- /dev/null
+++ b/src/Symbols/ParameterContainer.hpp
@@ -0,0 +1,17 @@
+#ifndef SYMBOLS_PARAMETER_CONTAINER_HPP
+#define SYMBOLS_PARAMETER_CONTAINER_HPP
+
+#include <string>
+#include <vector>
+
+#include "Symbols/VariableTypes.hpp"
+
+namespace Symbols {
+struct functionParameterType {
+    std::string              name;
+    Symbols::Variables::Type type;
+};
+
+using FunctionParameterInfo = std::vector<Symbols::functionParameterType>;
+}  // namespace Symbols
+#endif
diff --git a/include/SymbolContainer.hpp b/src/Symbols/SymbolContainer.hpp
similarity index 100%
rename from include/SymbolContainer.hpp
rename to src/Symbols/SymbolContainer.hpp
diff --git a/include/SymbolFactory.hpp b/src/Symbols/SymbolFactory.hpp
similarity index 70%
rename from include/SymbolFactory.hpp
rename to src/Symbols/SymbolFactory.hpp
index da37e15..5b7a168 100644
--- a/include/SymbolFactory.hpp
+++ b/src/Symbols/SymbolFactory.hpp
@@ -24,32 +24,42 @@
     }
 
     static std::shared_ptr<Symbol> createFunction(const std::string & name, const std::string & context,
-                                                  const Symbols::ValueContainer & parameters = {}) {
+                                                  const Symbols::FunctionParameterInfo & parameters = {}) {
         return std::make_shared<FunctionSymbol>(name, context, parameters);
     }
 
     static std::shared_ptr<Symbol> createFunction(const std::string & name, const std::string & context,
-                                                  const Symbols::ValueContainer & parameters,
-                                                  const std::string &             plainBody) {
+                                                  const Symbols::FunctionParameterInfo & parameters,
+                                                  const std::string &                    plainBody) {
         return std::make_shared<FunctionSymbol>(name, context, parameters, plainBody);
+    }
+
+    static std::shared_ptr<Symbol> createFunction(const std::string & name, const std::string & context,
+                                                  const Symbols::FunctionParameterInfo & parameters,
+                                                  const std::string & plainBody, Symbols::Variables::Type returnType) {
+        return std::make_shared<FunctionSymbol>(name, context, parameters, plainBody, returnType);
     }
 
     // Overloadok
     static std::shared_ptr<Symbol> createVariable(const std::string & name, int value, const std::string & context) {
-        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::VT_INT);
+        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::INTEGER);
     }
 
     static std::shared_ptr<Symbol> createVariable(const std::string & name, double value, const std::string & context) {
-        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::VT_DOUBLE);
+        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::DOUBLE);
+    }
+
+    static std::shared_ptr<Symbol> createVariable(const std::string & name, float value, const std::string & context) {
+        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::FLOAT);
     }
 
     static std::shared_ptr<Symbol> createVariable(const std::string & name, const std::string & value,
                                                   const std::string & context) {
-        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::VT_STRING);
+        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::STRING);
     }
 
     static std::shared_ptr<Symbol> createVariable(const std::string & name, bool value, const std::string & context) {
-        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::VT_BOOLEAN);
+        return createVariable(name, Symbols::Value(value), context, Symbols::Variables::Type::BOOLEAN);
     }
 };
 
diff --git a/include/SymbolKind.hpp b/src/Symbols/SymbolKind.hpp
similarity index 100%
rename from include/SymbolKind.hpp
rename to src/Symbols/SymbolKind.hpp
diff --git a/include/SymbolTable.hpp b/src/Symbols/SymbolTable.hpp
similarity index 98%
rename from include/SymbolTable.hpp
rename to src/Symbols/SymbolTable.hpp
index db23889..0c4c7da 100644
--- a/include/SymbolTable.hpp
+++ b/src/Symbols/SymbolTable.hpp
@@ -3,7 +3,6 @@
 #define SYMBOL_TABLE_HPP
 
 #include <memory>
-#include <optional>
 #include <vector>
 
 #include "SymbolTypes.hpp"
diff --git a/include/SymbolTypes.hpp b/src/Symbols/SymbolTypes.hpp
similarity index 100%
rename from include/SymbolTypes.hpp
rename to src/Symbols/SymbolTypes.hpp
diff --git a/src/Symbols/Value.hpp b/src/Symbols/Value.hpp
new file mode 100644
index 0000000..4c52b04
--- /dev/null
+++ b/src/Symbols/Value.hpp
@@ -0,0 +1,77 @@
+#ifndef SYMBOL_VALUE_HPP
+#define SYMBOL_VALUE_HPP
+
+#include <iostream>
+#include <stdexcept>
+#include <string>
+#include <variant>
+
+namespace Symbols {
+
+class Value {
+  public:
+    using Variant = std::variant<int, double, float, std::string, bool>;
+
+    Value() = default;
+
+    Value(int v) : value_(v) {}
+
+    Value(double v) : value_(v) {}
+
+    Value(float v) : value_(v) {}
+
+    Value(const std::string & v) : value_(v) {}
+
+    Value(const char * v) : value_(std::string(v)) {}
+
+    Value(bool v) : value_(v) {}
+
+    const Variant & get() const { return value_; }
+
+    Variant & get() { return value_; }
+
+    template <typename T> T get() const { return std::get<T>(value_); }
+
+    // operator+
+    friend Value operator+(const Value & lhs, const Value & rhs) {
+        return std::visit(
+            [](auto && a, auto && b) -> Value {
+                using A = std::decay_t<decltype(a)>;
+                using B = std::decay_t<decltype(b)>;
+                if constexpr ((std::is_arithmetic_v<A> && std::is_arithmetic_v<B>) ) {
+                    return Value{ a + b };
+                } else {
+                    throw std::runtime_error("Invalid types for operator+");
+                }
+            },
+            lhs.value_, rhs.value_);
+    }
+
+    // operator==
+    friend bool operator==(const Value & lhs, const Value & rhs) { return lhs.value_ == rhs.value_; }
+
+    // to_string helper (needed for string + int, etc.)
+    static std::string to_string(const Variant & v) {
+        return std::visit(
+            [](auto && val) -> std::string {
+                using T = std::decay_t<decltype(val)>;
+                if constexpr (std::is_same_v<T, bool>) {
+                    return val ? "true" : "false";
+                } else if constexpr (std::is_same_v<T, std::string>) {
+                    return val;
+                } else {
+                    return std::to_string(val);
+                }
+            },
+            v);
+    }
+
+    static std::string to_string(const Value & val) { return to_string(val.value_); }
+
+  private:
+    Variant value_;
+};
+
+}  // namespace Symbols
+
+#endif  // SYMBOL_VALUE_HPP
diff --git a/src/Symbols/ValueContainer.hpp b/src/Symbols/ValueContainer.hpp
new file mode 100644
index 0000000..fbc6fed
--- /dev/null
+++ b/src/Symbols/ValueContainer.hpp
@@ -0,0 +1,12 @@
+#ifndef SYMBOLS_VALUE_CONTAINER_HPP
+#define SYMBOLS_VALUE_CONTAINER_HPP
+
+#include <vector>
+
+#include "Symbols/Value.hpp"
+
+namespace Symbols {
+using ValueContainer = std::vector<Symbols::Value>;
+};  // namespace Symbols
+
+#endif  // SYMBOLS_VALUE_CONTAINER_HPP
diff --git a/src/Symbols/VariableSymbol.hpp b/src/Symbols/VariableSymbol.hpp
new file mode 100644
index 0000000..325b920
--- /dev/null
+++ b/src/Symbols/VariableSymbol.hpp
@@ -0,0 +1,45 @@
+// VariableSymbol.hpp
+#ifndef VARIABLE_SYMBOL_HPP
+#define VARIABLE_SYMBOL_HPP
+
+#include "BaseSymbol.hpp"
+#include "Symbols/VariableTypes.hpp"
+
+namespace Symbols {
+
+class VariableSymbol : public Symbol {
+  protected:
+    Symbols::Variables::Type type_;
+  public:
+    VariableSymbol(const std::string & name, const Symbols::Value & value, const std::string & context,
+                   Variables::Type type) :
+        Symbol(name, value, context, Symbols::Kind::Variable),
+        type_(type) {}
+
+    Symbols::Kind kind() const override { return Symbols::Kind::Variable; }
+
+    Variables::Type type() const { return type_; }
+
+    std::string toString() const {
+        std::string r = "VariableSymbol: " + name_ + " Type: " + Symbols::Variables::TypeToString(type_);
+        if (type_ == Symbols::Variables::Type::INTEGER) {
+            r += " Value: " + std::to_string(value_.get<int>());
+        } else if (type_ == Symbols::Variables::Type::DOUBLE) {
+            r += " Value: " + std::to_string(value_.get<double>());
+        } else if (type_ == Symbols::Variables::Type::FLOAT) {
+            r += " Value: " + std::to_string(value_.get<float>());
+        } else if (type_ == Symbols::Variables::Type::STRING) {
+            r += " Value: " + value_.get<std::string>();
+        } else if (type_ == Symbols::Variables::Type::BOOLEAN) {
+            r += " Value: " + std::to_string(value_.get<bool>());
+        } else if (type_ == Symbols::Variables::Type::NULL_TYPE) {
+            r += " Value: null";
+        }
+
+        return r;
+    }
+};
+
+}  // namespace Symbols
+
+#endif
diff --git a/src/Symbols/VariableTypes.hpp b/src/Symbols/VariableTypes.hpp
new file mode 100644
index 0000000..99c4802
--- /dev/null
+++ b/src/Symbols/VariableTypes.hpp
@@ -0,0 +1,48 @@
+#ifndef VARIABLE_TYPES_HPP
+#define VARIABLE_TYPES_HPP
+
+#include <cstdint>
+#include <string>
+#include <unordered_map>
+
+namespace Symbols::Variables {
+
+enum class Type : std::uint8_t { INTEGER, DOUBLE, FLOAT, STRING, BOOLEAN, NULL_TYPE, UNDEFINED_TYPE };
+
+const std::unordered_map<std::string, Type> StringToTypeMap = {
+    { "int",       Type::INTEGER        },
+    { "double",    Type::DOUBLE         },
+    { "float",     Type::FLOAT          },
+    { "string",    Type::STRING         },
+    { "bool",      Type::BOOLEAN        },
+    { "boolean",   Type::BOOLEAN        },
+    { "null",      Type::NULL_TYPE      },
+
+    { "undefined", Type::UNDEFINED_TYPE },
+};
+const std::unordered_map<Type, std::string> StypeToStringMap = {
+    { Type::INTEGER,        "int"        },
+    { Type::DOUBLE,         "double"     },
+    { Type::FLOAT,          "float"      },
+    { Type::STRING,         "string"     },
+    { Type::BOOLEAN,        "bool"       },
+    { Type::NULL_TYPE,      "null"       },
+    { Type::UNDEFINED_TYPE, "undeffined" },
+};
+
+inline static std::string TypeToString(Symbols::Variables::Type type) {
+    if (StypeToStringMap.find(type) != StypeToStringMap.end()) {
+        return StypeToStringMap.at(type);
+    }
+    return "null";
+};
+
+inline static Type StringToType(const std::string & type) {
+    if (StringToTypeMap.find(type) != StringToTypeMap.end()) {
+        return StringToTypeMap.at(type);
+    }
+    return Type::NULL_TYPE;
+};
+
+};  // namespace Symbols::Variables
+#endif  // VARIABLE_TYPES_HPP
diff --git a/src/Token.hpp b/src/Token.hpp
deleted file mode 100644
index 564356a..0000000
--- a/src/Token.hpp
+++ /dev/null
@@ -1,120 +0,0 @@
-#ifndef TOKEN_HPP
-#define TOKEN_HPP
-#include <cstdint>
-#include <string>
-#include <unordered_map>
-
-namespace Tokens {
-enum class Type : std::uint8_t {
-    ParserOpenTag,
-    ParserCloseTag,
-    ParserIfStatement,  // if
-    FileClose,
-    Identifier,
-    StringLiteral,
-    IntLiteral,
-    DoubleLiteral,
-    BooleanLiteral,
-    LeftParenthesis,      // (
-    RightParenthesis,     // )
-    Comma,                // ,
-    Semicolon,            // ;
-    Variable,             // $variable
-    VariableSign,         // $ variable start sign
-    StringDeclaration,    // string $variable
-    IntDeclaration,       // int $variable
-    DoubleDeclaration,    // double $variable
-    BooleanDeclaration,   // bool $variable
-    FunctionDeclaration,  // function fn_name
-    FunctionCall,         // fn_name(args)
-    Return,               // return
-    Equals,               // =
-    Plus,                 // +
-    Minus,                // -
-    Multiply,             // *
-    Divide,               // /
-    Modulo,               // %
-    GreaterThan,          // >
-    LessThan,             // <
-    GreaterThanOrEqual,   // >=
-    LessThanOrEqual,      // <=
-    NotEqual,             // !=
-    Equal,                // ==
-    Not,                  // !
-    And,                  // &&
-    Or,                   // ||
-    LeftBracket,          // [
-    RightBracket,         // ]
-    LeftCurlyBracket,     // {
-    RightCurlyBracket,    // }
-    EndOfFile,            // \0
-    EndOfLine,            // \n
-    Comment,              // #
-    Unknown               // Unknown
-};
-
-const static std::unordered_map<Tokens::Type, std::string> tokenTypeNames = {
-    { Tokens::Type::ParserOpenTag,       "ParserOpenTag"       },
-    { Tokens::Type::ParserCloseTag,      "ParserCloseTag"      },
-    { Tokens::Type::ParserIfStatement,   "ParserIfStatement"   },
-    { Tokens::Type::FileClose,           "FileClose"           },
-    { Tokens::Type::Identifier,          "Identifier"          },
-    { Tokens::Type::StringLiteral,       "StringLiteral"       },
-    { Tokens::Type::IntLiteral,          "IntLiteral"          },
-    { Tokens::Type::DoubleLiteral,       "DoubleLiteral"       },
-    { Tokens::Type::BooleanLiteral,      "BooleanLiteral"      },
-    { Tokens::Type::LeftParenthesis,     "LeftParenthesis"     },
-    { Tokens::Type::RightParenthesis,    "RightParenthesis"    },
-    { Tokens::Type::Comma,               "Comma"               },
-    { Tokens::Type::Semicolon,           "Semicolon"           },
-    { Tokens::Type::Variable,            "Variable"            },
-    { Tokens::Type::VariableSign,        "VariableSign"        },
-    { Tokens::Type::StringDeclaration,   "StringDeclaration"   },
-    { Tokens::Type::IntDeclaration,      "IntDeclaration"      },
-    { Tokens::Type::DoubleDeclaration,   "DoubleDeclaration"   },
-    { Tokens::Type::BooleanDeclaration,  "BooleanDeclaration"  },
-    { Tokens::Type::FunctionDeclaration, "FunctionDeclaration" },
-    { Tokens::Type::FunctionCall,        "FunctionCall"        },
-    { Tokens::Type::Return,              "Return"              },
-    { Tokens::Type::Equals,              "Equals"              },
-    { Tokens::Type::Plus,                "Plus"                },
-    { Tokens::Type::Minus,               "Minus"               },
-    { Tokens::Type::Multiply,            "Multiply"            },
-    { Tokens::Type::Divide,              "Divide"              },
-    { Tokens::Type::Modulo,              "Modulo"              },
-    { Tokens::Type::GreaterThan,         "GreaterThan"         },
-    { Tokens::Type::LessThan,            "LessThan"            },
-    { Tokens::Type::GreaterThanOrEqual,  "GreaterThanOrEqual"  },
-    { Tokens::Type::LessThanOrEqual,     "LessThanOrEqual"     },
-    { Tokens::Type::NotEqual,            "NotEqual"            },
-    { Tokens::Type::Equal,               "Equal"               },
-    { Tokens::Type::Not,                 "Not"                 },
-    { Tokens::Type::And,                 "And"                 },
-    { Tokens::Type::Or,                  "Or"                  },
-    { Tokens::Type::LeftBracket,         "LeftBracket"         },
-    { Tokens::Type::RightBracket,        "RightBracket"        },
-    { Tokens::Type::LeftCurlyBracket,    "LeftCurlyBracket"    },
-    { Tokens::Type::RightCurlyBracket,   "RightCurlyBracket"   },
-    { Tokens::Type::EndOfFile,           "EndOfFile"           },
-    { Tokens::Type::EndOfLine,           "EndOfLine"           },
-    { Tokens::Type::Comment,             "Comment"             },
-    { Tokens::Type::Unknown,             "Unknown"             }
-};
-
-struct TokenPos {
-    size_t start;
-    size_t end;
-};
-
-struct Token {
-    Tokens::Type type;
-    std::string  lexeme;
-    std::string  file;
-    int          lineNumber;
-    size_t       columnNumber;
-    TokenPos     pos;
-
-    [[nodiscard]] std::string getTokenName() const { return tokenTypeNames.at(type); }
-};
-}  // namespace Tokens
-#endif  // TOKEN_HPP
diff --git a/src/VoidScript.hpp b/src/VoidScript.hpp
new file mode 100644
index 0000000..d1188b5
--- /dev/null
+++ b/src/VoidScript.hpp
@@ -0,0 +1,89 @@
+#ifndef VOIDSCRIPT_HPP
+#define VOIDSCRIPT_HPP
+
+#include <filesystem>
+#include <fstream>
+#include <string>
+
+#include "Lexer/Lexer.hpp"
+#include "Parser/Parser.hpp"
+
+class VoidScript {
+  private:
+    std::string                     file;
+    std::shared_ptr<Lexer::Lexer>   lexer  = nullptr;
+    std::shared_ptr<Parser::Parser> parser = nullptr;
+    std::string                     file_content;
+
+  public:
+    VoidScript(const std::string & file) : file(file) {
+        if (!std::filesystem::exists(file)) {
+            throw std::runtime_error("File " + file + " does not exits");
+        }
+        lexer  = std::make_shared<Lexer::Lexer>();
+        parser = std::make_shared<Parser::Parser>();
+
+        lexer->setKeyWords(Parser::Parser::keywords);
+
+        // read in the file
+        std::ifstream input(file, std::ios::in);
+        if (!input.is_open()) {
+            throw std::runtime_error("Could not open file " + file);
+        }
+        file_content = std::string((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
+        input.close();
+    }
+
+    int run() {
+        try {
+            this->lexer->addNamespaceInput(this->file, this->file_content);
+            const auto tokens = this->lexer->tokenizeNamespace(this->file);
+
+            std::cout << "--- Tokens ---" << '\n';
+            for (const auto & token : tokens) {
+                if (token.type != Lexer::Tokens::Type::END_OF_FILE) {
+                    //token.print();
+                }
+            }
+            std::cout << "--------------" << '\n';
+
+            parser->parseProgram(tokens, this->file_content);
+            const std::shared_ptr<Symbols::SymbolContainer> & symbol_container = parser->getSymbolContainer();
+
+            std::cout << "\n--- Defined Variables ---" << '\n';
+            for (const auto & symbol_ptr : symbol_container->listNamespace("variables")) {
+                // Itt lehetne a szimbólumokat kiírni vagy tovább feldolgozni
+                // Szükséges lehet dynamic_cast<> a konkrét típushoz (VariableSymbol)
+                if (auto var_symbol = std::dynamic_pointer_cast<Symbols::VariableSymbol>(symbol_ptr)) {
+                    std::cout << var_symbol->toString() << '\n';
+                }
+            }
+
+            std::cout << "\n--- Defined Functions ---" << '\n';
+            for (const auto & symbol_ptr : symbol_container->listNamespace("functions")) {
+                if (auto func_symbol = std::dynamic_pointer_cast<Symbols::FunctionSymbol>(symbol_ptr)) {
+                    std::cout << "Func Name: " << func_symbol->name()
+                              << " return type: " << Symbols::Variables::TypeToString(func_symbol->returnType())
+                              << '\n';
+                    for (const auto & func_param : func_symbol->parameters()) {
+                        std::cout << "  Param: " << func_param.name
+                                  << " Type: " << Symbols::Variables::TypeToString(func_param.type) << '\n';
+                    }
+                    std::cout << "  Context name: " << func_symbol->context() << '\n';
+                    std::cout << "  Plain body: " << func_symbol->plainBody() << '\n';
+                }
+            }
+
+            return 0;
+        } catch (const Parser::SyntaxError & e) {
+            std::cerr << "Syntax Error during parsing: " << e.what() << '\n';
+            return 1;
+        } catch (const std::exception & e) {
+            std::cerr << "An error occurred: " << e.what() << '\n';
+            return 1;
+        }
+        return 1;
+    }
+};  // class VoidScript
+
+#endif  // VOIDSCRIPT_HPP

--
Gitblit v1.9.3