From ba9a9199d01b0fdd4bf9a54914f8058bf71f30c5 Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Thu, 17 Apr 2025 16:03:01 +0000
Subject: [PATCH] unary and binary operations

---
 src/Interpreter/ExpressionBuilder.hpp            |   42 +
 src/Interpreter/VariableReferenceNode.hpp        |   37 +
 src/Interpreter/BinaryExpressionNode.hpp         |   68 ++
 src/Interpreter/OperationsFactory.hpp            |   59 +
 src/Interpreter/IdentifierExpressionNode.hpp     |   29 
 src/Symbols/SymbolKind.hpp                       |   17 
 .clangd                                          |    2 
 src/Symbols/Value.hpp                            |  105 ++
 src/Symbols/BaseSymbol.hpp                       |   11 
 src/VoidScript.hpp                               |   82 +-
 src/Parser/ParsedExpression.hpp                  |   66 ++
 src/Interpreter/OperationContainer.hpp           |  129 +++
 src/!NameSpaceManager.hpp                        |  144 ++++
 src/Interpreter/Operation.hpp                    |   68 +
 src/Parser/Parser.cpp                            |    2 
 src/Lexer/Lexer.hpp                              |   65 +
 src/Interpreter/UnaryExpressionNode.hpp          |   64 +
 src/Parser/Parser.hpp                            |  484 ++++++++------
 src/Interpreter/LiteralExpressionNode.hpp        |   25 
 src/Interpreter/ExpressionNode.hpp               |   13 
 src/Interpreter/Interpreter.hpp                  |   74 +
 cli/main.cpp                                     |    3 
 src/Interpreter/DeclareFunctionStatementNode.hpp |   55 +
 src/Lexer/TokenType.hpp                          |    4 
 src/Symbols/SymbolTable.hpp                      |   31 
 src/Symbols/SymbolContainer.hpp                  |  136 +++
 src/Interpreter/DeclareVariableStatementNode.hpp |   52 +
 src/Interpreter/StatementNode.hpp                |   26 
 src/Interpreter/VariableExpressionNode.hpp       |   36 +
 29 files changed, 1,543 insertions(+), 386 deletions(-)

diff --git a/.clangd b/.clangd
index 1843e4d..a267584 100644
--- a/.clangd
+++ b/.clangd
@@ -1,5 +1,5 @@
 CompileFlags:
-  Add: [-Wunused]
+  Add: [-xc++, -Wall]
 
 Index:
   StandardLibrary: No
\ No newline at end of file
diff --git a/cli/main.cpp b/cli/main.cpp
index ca6c810..65dca3a 100644
--- a/cli/main.cpp
+++ b/cli/main.cpp
@@ -1,5 +1,4 @@
 #include <filesystem>
-#include <fstream>
 #include <iostream>
 #include <unordered_map>
 
@@ -58,6 +57,4 @@
 
     VoidScript voidscript(filename);
     return voidscript.run();
-
-    return 0;
 }
diff --git "a/src/\041NameSpaceManager.hpp" "b/src/\041NameSpaceManager.hpp"
new file mode 100644
index 0000000..fa249e9
--- /dev/null
+++ "b/src/\041NameSpaceManager.hpp"
@@ -0,0 +1,144 @@
+#ifndef NAMESPACE_MANAGER_H
+#define NAMESPACE_MANAGER_H
+#include <functional>
+#include <map>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+class Namespace {
+  public:
+    Namespace(const std::string & name = "", Namespace * parent = nullptr) : name_(name), parent_(parent) {}
+
+    /**
+    * @brief Add a child namespace to the current namespace.
+    * @param name Name of the child namespace.
+    */
+    Namespace * addChild(const std::string & name) {
+        auto it = children_.find(name);
+        if (it == children_.end()) {
+            children_[name] = std::make_unique<Namespace>(name, this);
+        }
+        return children_[name].get();
+    }
+
+    /**
+    * @brief Get the child namespace by name.
+    * @param name Name of the child namespace.
+    * @return The child namespace
+    */
+    Namespace * getChild(const std::string & name) const {
+        auto it = children_.find(name);
+        return it != children_.end() ? it->second.get() : nullptr;
+    }
+
+    /**
+    * @brief Get the child namespace by name.
+    * @param name Name of the child namespace.
+    * @return The child namespace
+    */
+    Namespace * getOrCreate(const std::string & fullName) {
+        auto        parts   = split(fullName, '.');
+        Namespace * current = this;
+        for (const auto & part : parts) {
+            current = current->addChild(part);
+        }
+        return current;
+    }
+
+    /**
+    * @brief Get the parent namespace.
+    * @return The parent namespace.
+    */
+    Namespace * getParent() const { return parent_; }
+
+    std::string toString() const {
+        if (!parent_ || name_.empty()) {
+            return name_;
+        }
+        return parent_->toString() + "." + name_;
+    }
+
+    void traverse(const std::function<void(const Namespace &)>& visitor) const {
+        visitor(*this);
+        for (const auto & [_, child] : children_) {
+            child->traverse(visitor);
+        }
+    }
+
+    const std::string & getName() const { return name_; }
+
+  private:
+    std::string                                       name_;
+    Namespace *                                       parent_;
+    std::map<std::string, std::unique_ptr<Namespace>> children_;
+
+    static std::vector<std::string> split(const std::string & str, char delimiter) {
+        std::stringstream        ss(str);
+        std::string              part;
+        std::vector<std::string> result;
+        while (std::getline(ss, part, delimiter)) {
+            result.push_back(part);
+        }
+        return result;
+    }
+};
+
+class NamespaceManager {
+  public:
+    static NamespaceManager & instance() {
+        static NamespaceManager instance_;
+        return instance_;
+    }
+
+    /**
+     * @brief Constructor for NamespaceManager.
+     * @param name Name of the namespace.
+     * @param parent Parent namespace.
+     */
+    NamespaceManager() : root_(""), currentNamespace_(&root_) {}
+
+    /**
+    * @brief Get or create a namespace by full name.
+    * @param fullName Full name of the namespace.
+    * @return The namespace object.
+    */
+    Namespace * getOrCreate(const std::string & fullName) { return root_.getOrCreate(fullName); }
+
+    /**
+    * @brief Set the current namespace.
+    * @param fullName Full name of the namespace.
+    */
+    void setCurrent(const std::string & fullName) {
+        Namespace * ns = root_.getOrCreate(fullName);
+        if (ns) {
+            currentNamespace_ = ns;
+        } else {
+            currentNamespace_ = &root_;  // fallback
+        }
+    }
+
+    /**
+    * @brief Get the current namespace.
+    * @return The current namespace object.
+    */
+    Namespace * getCurrent() const { return currentNamespace_; }
+
+    /**
+    * @brief Reset the current namespace.
+    */
+    void resetCurrent() { currentNamespace_ = &root_; }
+
+    /**
+    * @brief Traverse the namespace tree.
+    * @param visitor A function to visit each namespace.
+    */
+    void traverse(const std::function<void(const Namespace &)>& visitor) const { root_.traverse(visitor); }
+
+  private:
+    Namespace   root_;
+    Namespace * currentNamespace_;
+};
+
+#endif  // NAMESPACE_MANAGER_H
diff --git a/src/Interpreter/BinaryExpressionNode.hpp b/src/Interpreter/BinaryExpressionNode.hpp
new file mode 100644
index 0000000..f741d3f
--- /dev/null
+++ b/src/Interpreter/BinaryExpressionNode.hpp
@@ -0,0 +1,68 @@
+#include <memory>
+#include <string>
+
+#include "ExpressionNode.hpp"
+
+namespace Interpreter {
+class BinaryExpressionNode : public ExpressionNode {
+    std::unique_ptr<ExpressionNode> lhs_;
+    std::unique_ptr<ExpressionNode> rhs_;
+    std::string                     op_;
+
+  public:
+    BinaryExpressionNode(std::unique_ptr<ExpressionNode> lhs, std::string op, std::unique_ptr<ExpressionNode> rhs) :
+        lhs_(std::move(lhs)),
+        rhs_(std::move(rhs)),
+        op_(std::move(op)) {}
+
+    Symbols::Value evaluate(Interpreter & interpreter) const override {
+        auto leftVal  = lhs_->evaluate(interpreter);
+        auto rightVal = rhs_->evaluate(interpreter);
+        if (leftVal.getType() != rightVal.getType()) {
+            throw std::runtime_error(
+                "Unsupported types in binary expression: " + Symbols::Variables::TypeToString(leftVal.getType()) +
+                " and " + Symbols::Variables::TypeToString(rightVal.getType()) + " " + toString());
+        }
+
+        if (leftVal.getType() == Symbols::Variables::Type::INTEGER &&
+            rightVal.getType() == Symbols::Variables::Type::INTEGER) {
+            int l = leftVal.get<int>();
+            int r = rightVal.get<int>();
+
+            if (op_ == "+") {
+                return Symbols::Value(l + r);
+            }
+            if (op_ == "-") {
+                return Symbols::Value(l - r);
+            }
+            if (op_ == "*") {
+                return Symbols::Value(l * r);
+            }
+            if (op_ == "/") {
+                return Symbols::Value(l / r);  // TODO: 0 div
+            }
+
+            throw std::runtime_error("Unknown operator: " + op_);
+        }
+
+        if (leftVal.getType() == Symbols::Variables::Type::STRING &&
+            rightVal.getType() == Symbols::Variables::Type::STRING) {
+            auto l = leftVal.get<std::string>();
+            auto r = rightVal.get<std::string>();
+
+            if (op_ == "+") {
+                return Symbols::Value(l + r);
+            }
+
+            throw std::runtime_error("Unknown operator: " + op_);
+        }
+
+        throw std::runtime_error(
+            "Unsupported types in binary expression: " + Symbols::Variables::TypeToString(leftVal.getType()) + " and " +
+            Symbols::Variables::TypeToString(rightVal.getType()) + " " + toString());
+    }
+
+    std::string toString() const override { return "(" + lhs_->toString() + " " + op_ + " " + rhs_->toString() + ")"; }
+};
+
+};  // namespace Interpreter
diff --git a/src/Interpreter/DeclareFunctionStatementNode.hpp b/src/Interpreter/DeclareFunctionStatementNode.hpp
new file mode 100644
index 0000000..bb3eea7
--- /dev/null
+++ b/src/Interpreter/DeclareFunctionStatementNode.hpp
@@ -0,0 +1,55 @@
+#ifndef INTERPRETER_DEFINE_FUNCTION_STATEMENT_NODE_HPP
+#define INTERPRETER_DEFINE_FUNCTION_STATEMENT_NODE_HPP
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "ExpressionNode.hpp"
+#include "Interpreter.hpp"
+#include "Interpreter/StatementNode.hpp"
+#include "Symbols/ParameterContainer.hpp"
+#include "Symbols/SymbolContainer.hpp"
+#include "Symbols/SymbolFactory.hpp"
+
+namespace Interpreter {
+
+class DeclareFunctionStatementNode : public StatementNode {
+    std::string                     functionName_;
+    Symbols::Variables::Type        returnType_;
+    Symbols::FunctionParameterInfo  params_;
+    std::unique_ptr<ExpressionNode> expression_;
+    std::string                     ns;
+
+
+  public:
+    DeclareFunctionStatementNode(const std::string & function_name, const std::string & ns,
+                                 const Symbols::FunctionParameterInfo & params, Symbols::Variables::Type return_type,
+                                 std::unique_ptr<ExpressionNode> expr, const std::string & file_name, int file_line,
+                                 size_t line_column) :
+        StatementNode(file_name, file_line, line_column),
+        functionName_(function_name),
+        returnType_(return_type),
+        params_(params),
+        expression_(std::move(expr)),
+        ns(ns) {}
+
+    void interpret(Interpreter & /*interpreter*/) const override {
+        //Symbols::Value value = expression_->evaluate(interpreter);
+        if (Symbols::SymbolContainer::instance()->exists(functionName_)) {
+            throw std::runtime_error("Function already declared: " + functionName_ + " file: " + filename_ +
+                                     ", line: " + std::to_string(line_) + ", column: " + std::to_string(column_));
+        }
+        const auto func = Symbols::SymbolFactory::createFunction(functionName_, ns, params_, "", returnType_);
+        Symbols::SymbolContainer::instance()->add(func);
+    }
+
+    std::string toString() const override {
+        return std::string( " FunctioName: " + functionName_ + " return type: " + Symbols::Variables::TypeToString(returnType_) +
+               " params size: " + std::to_string(params_.size()));
+    }
+};
+
+}  // namespace Interpreter
+
+#endif  // INTERPRETER_DEFINE_FUNCTION_STATEMENT_NODE_HPP
diff --git a/src/Interpreter/DeclareVariableStatementNode.hpp b/src/Interpreter/DeclareVariableStatementNode.hpp
new file mode 100644
index 0000000..875c87b
--- /dev/null
+++ b/src/Interpreter/DeclareVariableStatementNode.hpp
@@ -0,0 +1,52 @@
+#ifndef INTERPRETER_DEFINE_VARIABLE_STATEMENT_NODE_HPP
+#define INTERPRETER_DEFINE_VARIABLE_STATEMENT_NODE_HPP
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "ExpressionNode.hpp"
+#include "Interpreter.hpp"
+#include "Interpreter/StatementNode.hpp"
+#include "Symbols/SymbolContainer.hpp"
+#include "Symbols/SymbolFactory.hpp"
+
+namespace Interpreter {
+
+class DeclareVariableStatementNode : public StatementNode {
+    std::string                     variableName_;
+    Symbols::Variables::Type        variableType_;
+    std::unique_ptr<ExpressionNode> expression_;
+    std::string                     ns;
+
+
+  public:
+    DeclareVariableStatementNode(std::string name, const std::string & ns, Symbols::Variables::Type type,
+                                 std::unique_ptr<ExpressionNode> expr, const std::string & file_name, int file_line,
+                                 size_t line_column) :
+        StatementNode(file_name, file_line, line_column),
+        variableName_(std::move(name)),
+        variableType_(type),
+        expression_(std::move(expr)),
+        ns(ns) {}
+
+    void interpret(Interpreter & interpreter) const override {
+        Symbols::Value value = expression_->evaluate(interpreter);
+        if (Symbols::SymbolContainer::instance()->exists(variableName_)) {
+            throw std::runtime_error("Variable already declared: " + variableName_ + " File: " + filename_ +
+                                     ", Line: " + std::to_string(line_) + ", Column: " + std::to_string(column_));
+        }
+        const auto variable = Symbols::SymbolFactory::createVariable(variableName_, value, ns, variableType_);
+
+        Symbols::SymbolContainer::instance()->add(variable);
+    }
+
+    std::string toString() const override {
+        return std::string("variable name: " + variableName_ +
+                           " type: " + Symbols::Variables::TypeToString(variableType_));
+    }
+};
+
+}  // namespace Interpreter
+
+#endif  // INTERPRETER_DEFINE_VARIABLE_STATEMENT_NODE_HPP
diff --git a/src/Interpreter/ExpressionBuilder.hpp b/src/Interpreter/ExpressionBuilder.hpp
new file mode 100644
index 0000000..32b2e9b
--- /dev/null
+++ b/src/Interpreter/ExpressionBuilder.hpp
@@ -0,0 +1,42 @@
+#ifndef PARSEREXPRESSION_BUILDER_HPP
+#define PARSEREXPRESSION_BUILDER_HPP
+
+#include <memory>
+#include <stdexcept>
+
+#include "Interpreter/BinaryExpressionNode.hpp"
+#include "Interpreter/ExpressionNode.hpp"
+#include "Interpreter/IdentifierExpressionNode.hpp"
+#include "Interpreter/LiteralExpressionNode.hpp"
+#include "Interpreter/UnaryExpressionNode.hpp" // <-- új include
+#include "Parser/ParsedExpression.hpp"
+
+namespace Parser {
+static std::unique_ptr<Interpreter::ExpressionNode> buildExpressionFromParsed(
+    const Parser::ParsedExpressionPtr & expr) {
+    using Kind = Parser::ParsedExpression::Kind;
+
+    switch (expr->kind) {
+        case Kind::Literal:
+            return std::make_unique<Interpreter::LiteralExpressionNode>(expr->value);
+
+        case Kind::Variable:
+            return std::make_unique<Interpreter::IdentifierExpressionNode>(expr->name);
+
+        case Kind::Binary: {
+            auto lhs = buildExpressionFromParsed(expr->lhs);
+            auto rhs = buildExpressionFromParsed(expr->rhs);
+            return std::make_unique<Interpreter::BinaryExpressionNode>(std::move(lhs), expr->op, std::move(rhs));
+        }
+
+        case Kind::Unary: {
+            auto operand = buildExpressionFromParsed(expr->rhs);  // rhs az operandus
+            return std::make_unique<Interpreter::UnaryExpressionNode>(expr->op, std::move(operand));
+        }
+    }
+
+    throw std::runtime_error("Unknown ParsedExpression kind");
+}
+}  // namespace Parser
+
+#endif  // PARSEREXPRESSION_BUILDER_HPP
diff --git a/src/Interpreter/ExpressionNode.hpp b/src/Interpreter/ExpressionNode.hpp
index b3853e3..a969015 100644
--- a/src/Interpreter/ExpressionNode.hpp
+++ b/src/Interpreter/ExpressionNode.hpp
@@ -1,16 +1,13 @@
 #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;
-};
+#include "Symbols/Value.hpp"
 
-// Kifejezés (csak int literál most)
+namespace Interpreter {
 struct ExpressionNode {
-    virtual ~ExpressionNode()                                   = default;
-    virtual int evaluate(class Interpreter & interpreter) const = 0;
+    virtual ~ExpressionNode()                                              = default;
+    virtual Symbols::Value evaluate(class Interpreter & interpreter) const = 0;
+    virtual std::string    toString() const                                = 0;
 };
 
 }  // namespace Interpreter
diff --git a/src/Interpreter/IdentifierExpressionNode.hpp b/src/Interpreter/IdentifierExpressionNode.hpp
new file mode 100644
index 0000000..c610f77
--- /dev/null
+++ b/src/Interpreter/IdentifierExpressionNode.hpp
@@ -0,0 +1,29 @@
+#ifndef IDENTIFIER_EXPRESSION_NODE_HPP
+#define IDENTIFIER_EXPRESSION_NODE_HPP
+
+#include "ExpressionNode.hpp"
+#include "Symbols/SymbolContainer.hpp"
+#include "Symbols/Value.hpp"
+
+namespace Interpreter {
+
+class IdentifierExpressionNode : public ExpressionNode {
+    std::string name_;
+
+  public:
+    explicit IdentifierExpressionNode(std::string name) : name_(std::move(name)) {}
+
+    Symbols::Value evaluate(Interpreter & /*interpreter*/) const override {
+        const auto ns = Symbols::SymbolContainer::instance()->currentScopeName() + ".variables";
+        if (Symbols::SymbolContainer::instance()->exists(name_, ns)) {
+            return Symbols::SymbolContainer::instance()->get(ns, name_)->getValue();
+        }
+        throw std::runtime_error("Variable " + name_ + " does not exist in ns: " + ns);
+    }
+
+    std::string toString() const override { return name_; }
+};
+
+}  // namespace Interpreter
+
+#endif  // IDENTIFIER_EXPRESSION_NODE_HPP
diff --git a/src/Interpreter/Interpreter.hpp b/src/Interpreter/Interpreter.hpp
index 84d725b..cb617c8 100644
--- a/src/Interpreter/Interpreter.hpp
+++ b/src/Interpreter/Interpreter.hpp
@@ -1,45 +1,65 @@
 #ifndef INTERPRETER_HPP
 #define INTERPRETER_HPP
+#include <iostream>
 #include <memory>
-#include <utility>
-#include <vector>
+#include <stdexcept>
 
 #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 runOperation(const Operations::Operation & op) {
+        std::cout << "Operation: " << op.toString() << "\n";
 
-    void setVariable(const std::string & name, int value) {
-        //symbol_container_->setVariable(name, value);
+        switch (op.type) {
+            case Operations::Type::Declaration:
+                if (op.statement) {
+                    op.statement->interpret(*this);
+                }
+                break;
+            case Operations::Type::FuncDeclaration:
+                {
+                    op.statement->interpret(*this);
+                }
+                break;
+
+            case Operations::Type::Assignment:
+                {
+                    op.statement->interpret(*this);
+                    break;
+                }
+
+            case Operations::Type::Expression:
+                {
+                    op.statement->interpret(*this);  // csak side effect miatt
+                    break;
+                }
+
+            case Operations::Type::FunctionCall:
+            case Operations::Type::Return:
+            case Operations::Type::Loop:
+            case Operations::Type::Break:
+            case Operations::Type::Continue:
+            case Operations::Type::Block:
+            case Operations::Type::Import:
+            case Operations::Type::Error:
+            case Operations::Type::Conditional:
+                // TODO: implementálható később
+                break;
+            default:
+                throw std::runtime_error("Not implemented operation type");
+        }
     }
+
   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) {}
+    Interpreter() {}
 
-    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;
-                    }
-            }
+    void run() {
+        for (const auto & operation : Operations::Container::instance()->getAll()) {
+            runOperation(*operation);
         }
     }
 
diff --git a/src/Interpreter/LiteralExpressionNode.hpp b/src/Interpreter/LiteralExpressionNode.hpp
new file mode 100644
index 0000000..efe7c0a
--- /dev/null
+++ b/src/Interpreter/LiteralExpressionNode.hpp
@@ -0,0 +1,25 @@
+#ifndef LITERAL_EXPRESSION_NODE_HPP
+#define LITERAL_EXPRESSION_NODE_HPP
+
+#include "ExpressionNode.hpp"
+#include "Symbols/Value.hpp"
+
+namespace Interpreter {
+
+class LiteralExpressionNode : public ExpressionNode {
+    Symbols::Value value_;
+
+  public:
+    explicit LiteralExpressionNode(Symbols::Value value) : value_(std::move(value)) {}
+
+    Symbols::Value evaluate(class Interpreter & /*interpreter*/) const override { return value_; }
+
+    const Symbols::Value & value() const { return value_; }
+
+    // to string
+    std::string toString() const override { return Symbols::Value::to_string(value_); }
+};
+
+}  // namespace Interpreter
+
+#endif  // LITERAL_EXPRESSION_NODE_HPP
diff --git a/src/Interpreter/Operation.hpp b/src/Interpreter/Operation.hpp
index ecbae0b..8804075 100644
--- a/src/Interpreter/Operation.hpp
+++ b/src/Interpreter/Operation.hpp
@@ -2,30 +2,68 @@
 #define INTERPRETER_OPERATION_HPP
 
 #include <cstdint>
-
 #include <memory>
 #include <string>
+#include <unordered_map>
 
-#include "ExpressionNode.hpp"
+#include "Interpreter/StatementNode.hpp"
 
-namespace Interpreter {
-enum OperationType : std::uint8_t {
-    Assignment,
-    Expression,
-
+namespace Operations {
+enum class Type : std::uint8_t {
+    Assignment,       // Variable assignment, e.g., $x = 5
+    Expression,       // Evaluation of an expression (can be evaluated without side effects)
+    FunctionCall,     // Call to a function, e.g., print(x)
+    FuncDeclaration,  // declaration of new function
+    Return,           // return statement
+    Conditional,      // if/else structure
+    Loop,             // while/for loop
+    Break,            // break out of a loop
+    Continue,         // continue with the next iteration of a loop
+    Block,            // block of statements, e.g. { ... }
+    Declaration,      // declaration of new variable (if different from assignment) int $x = 1
+    Import,           // import of another script or module
+    Error,            // error or non-interpretable operation (error handling)
 };
 
 struct Operation {
-    OperationType type;
+    Operation() = default;
+    Operations::Type type;
 
     // Általános mezők
-    std::string targetVariable;
-    std::unique_ptr<ExpressionNode> expression;
+    std::string                                 targetName;
+    std::unique_ptr<Interpreter::StatementNode> statement;
 
-    Operation(OperationType t, std::string var, std::unique_ptr<ExpressionNode> expr)
-        : type(t), targetVariable(std::move(var)), expression(std::move(expr)) {}
+    Operation(Operations::Type t, std::string target_variable, std::unique_ptr<Interpreter::StatementNode> stmt) :
+        type(t),
+        targetName(std::move(target_variable)),
+        statement(std::move(stmt)) {}
+
+    std::string typeToString() const {
+        std::unordered_map<Operations::Type, std::string> types = {
+            { Operations::Type::Assignment,      "Assignment"      },
+            { Operations::Type::Expression,      "Expression"      },
+            { Operations::Type::FunctionCall,    "FunctionCall"    },
+            { Operations::Type::FuncDeclaration, "FuncDeclaration" },
+            { Operations::Type::Return,          "Return"          },
+            { Operations::Type::Conditional,     "Conditional"     },
+            { Operations::Type::Loop,            "Loop"            },
+            { Operations::Type::Break,           "Break"           },
+            { Operations::Type::Continue,        "Continue"        },
+            { Operations::Type::Block,           "Block"           },
+            { Operations::Type::Declaration,     "Declaration"     },
+            { Operations::Type::Import,          "Import"          },
+            { Operations::Type::Error,           "Error"           }
+        };
+        auto it = types.find(type);
+        if (it != types.end()) {
+            return it->second;
+        }
+        return "Unknown type";
+    }
+
+    std::string toString() const {
+        return "Target: " + targetName + " Type: " + this->typeToString() + " Statement: " + statement->toString();
+     }
 };
-
-
-};  // namespace Interpreter
+};  // namespace Operations
 #endif
diff --git a/src/Interpreter/OperationContainer.hpp b/src/Interpreter/OperationContainer.hpp
index 62b5c1d..20f9e2c 100644
--- a/src/Interpreter/OperationContainer.hpp
+++ b/src/Interpreter/OperationContainer.hpp
@@ -1,12 +1,135 @@
 #ifndef INTERPRETER_OPERATION_CONTAINER_HPP
 #define INTERPRETER_OPERATION_CONTAINER_HPP
 
+#include <map>
+#include <string>
 #include <vector>
 
 #include "Interpreter/Operation.hpp"
 
-namespace Interpreter {
-using OperationContainer = std::vector<Operation>;
-};  // namespace Interpreter
+namespace Operations {
+
+class Container {
+
+  public:
+    /**
+     * @brief Get the Operations::Container instance.
+     * @return The Operations::Container instance.
+     */
+    static Operations::Container * instance() {
+        static Operations::Container instance_;
+        return &instance_;
+    }
+
+    Container() = default;
+
+    void add(const std::string & ns, Operations::Operation operation) {
+        this->_operations[ns].emplace_back(std::make_shared<Operations::Operation>(std::move(operation)));
+    }
+
+    /**
+    * @brief Returns the first operation in the namespace.
+    * @param ns Namespace from which to get the operation.
+    * @return The first operation in the namespace.
+    */
+    std::shared_ptr<Operations::Operation> getFirst(const std::string & ns) {
+        auto it = _operations.find(ns);
+        if (it != _operations.end()) {
+            return it->second.front();
+        }
+        return nullptr;
+    }
+
+    /**
+     * @brief Removes the first operation from the namespace.
+     * @param ns Namespace from which to remove the operation.
+     * @return The removed operation.
+     */
+    std::shared_ptr<Operations::Operation> pullFirst(const std::string & ns) {
+        auto it = _operations.find(ns);
+        if (it != _operations.end()) {
+            auto operation = it->second.front();
+            it->second.erase(it->second.begin());
+            return operation;
+        }
+        return nullptr;
+    }
+
+    /**
+     * @brief Removes the last operation from the namespace.
+     * @param ns Namespace from which to remove the operation.
+     * @return The removed operation.
+     */
+    std::shared_ptr<Operations::Operation> pullLast(const std::string & ns) {
+        auto it = _operations.find(ns);
+        if (it != _operations.end()) {
+            auto operation = it->second.back();
+            it->second.pop_back();
+            return operation;
+        }
+        return nullptr;
+    }
+
+    /**
+    * @brief Returns the last operation in the namespace.
+    * @param ns Namespace from which to get the operation.
+    * @return The last operation in the namespace.
+    */
+    std::shared_ptr<Operations::Operation> getLast(const std::string & ns) {
+        auto it = _operations.find(ns);
+        if (it != _operations.end()) {
+            return it->second.back();
+        }
+        return nullptr;
+    }
+
+    /**
+     * @brief Returns all operations in the namespace.
+     * @param ns Namespace from which to get the operations.
+     * @return All operations in the namespace.
+     */
+    std::vector<std::shared_ptr<Operations::Operation>> getAll(const std::string & ns) {
+        auto it = _operations.find(ns);
+        if (it != _operations.end()) {
+            return it->second;
+        }
+        return {};
+    }
+
+    /**
+     * @brief Returns all operations from all namespaces
+     * @return All operations in the namespace.
+     */
+    std::vector<std::shared_ptr<Operations::Operation>> getAll() {
+        std::vector<std::shared_ptr<Operations::Operation>> result;
+        for (const auto & [_, table] : _operations) {
+            result.insert(result.end(), table.begin(), table.end());
+        }
+        return result;
+    }
+
+    auto begin() { return _operations.begin(); }
+
+    auto end() { return _operations.end(); }
+
+    auto begin() const { return _operations.begin(); }
+
+    auto end() const { return _operations.end(); }
+
+    static std::string dump()  {
+        std::string result = "";
+        for (const auto & [_, table] : Operations::Container::instance()->_operations) {
+            result += "Namespace: " + _ + "\n";
+            for (const auto & operation : table) {
+                result += "  Operation: " + operation->toString() + "\n";
+            }
+        }
+        return result;
+    }
+
+  private:
+    std::map<std::string, std::vector<std::shared_ptr<Operations::Operation>>> _operations;
+};  // class Container
+};  // namespace Operations
 
 #endif  // INTERPRETER_OPERATION_CONTAINER_HPP
diff --git a/src/Interpreter/OperationsFactory.hpp b/src/Interpreter/OperationsFactory.hpp
new file mode 100644
index 0000000..5adbaf7
--- /dev/null
+++ b/src/Interpreter/OperationsFactory.hpp
@@ -0,0 +1,59 @@
+#ifndef OPERATIONSFACTORY_HPP
+#define OPERATIONSFACTORY_HPP
+
+#include <memory>
+#include <string>
+
+#include "Interpreter/DeclareFunctionStatementNode.hpp"
+#include "Interpreter/DeclareVariableStatementNode.hpp"
+#include "Interpreter/ExpressionBuilder.hpp"
+#include "Interpreter/LiteralExpressionNode.hpp"
+#include "Interpreter/Operation.hpp"
+#include "Interpreter/OperationContainer.hpp"
+#include "Parser/ParsedExpression.hpp"
+#include "Symbols/ParameterContainer.hpp"
+#include "Symbols/Value.hpp"
+
+namespace Interpreter {
+
+class OperationsFactory {
+  public:
+    OperationsFactory() {}
+
+    static void defineFunction(const std::string & functionName, const Symbols::FunctionParameterInfo & params,
+                               const Symbols::Variables::Type & returnType, const std::string & ns,
+                               const std::string & fileName, int line, size_t column) {
+        std::unique_ptr<DeclareFunctionStatementNode> stmt = std::make_unique<DeclareFunctionStatementNode>(
+            functionName, ns, params, returnType, nullptr, fileName, line, column);
+        Operations::Container::instance()->add(
+            ns, Operations::Operation{ Operations::Type::FuncDeclaration, functionName, std::move(stmt) });
+    }
+
+    static void defineSimpleVariable(const std::string & varName, const Symbols::Value & value, const std::string & ns,
+                                     const std::string & filename, int line, size_t column) {
+        auto literalExpr = std::make_unique<LiteralExpressionNode>(value);
+
+        std::unique_ptr<DeclareVariableStatementNode> stmt = std::make_unique<DeclareVariableStatementNode>(
+            varName, ns, value.getType(), std::move(literalExpr), filename, line, column);
+
+        Operations::Container::instance()->add(
+            ns, Operations::Operation{ Operations::Type::Declaration, varName, std::move(stmt) });
+    }
+
+    static void defineVariableWithExpression(const std::string & varName, Symbols::Variables::Type type,
+                                             const Parser::ParsedExpressionPtr pexpr, const std::string & ns,
+                                             const std::string & filename, int line, size_t column) {
+                                              // ParsedExpression → ExpressionNode
+                                              std::unique_ptr<ExpressionNode> expr = buildExpressionFromParsed(pexpr);
+
+                                              std::unique_ptr<DeclareVariableStatementNode> stmt = std::make_unique<DeclareVariableStatementNode>(
+                                                  varName, ns, type, std::move(expr), filename, line, column);
+
+                                              Operations::Container::instance()->add(
+                                                  ns, Operations::Operation{Operations::Type::Declaration, varName, std::move(stmt)});
+                                          }
+};
+
+}  // namespace Interpreter
+
+#endif  // OPERATIONSFACTORY_HPP
diff --git a/src/Interpreter/StatementNode.hpp b/src/Interpreter/StatementNode.hpp
new file mode 100644
index 0000000..ce070a8
--- /dev/null
+++ b/src/Interpreter/StatementNode.hpp
@@ -0,0 +1,26 @@
+#ifndef STATEMENT_NODE_HPP
+#define STATEMENT_NODE_HPP
+
+#include <string>
+
+namespace Interpreter {
+
+class StatementNode {
+  public:
+    std::string filename_;
+    int         line_;
+    size_t      column_;
+
+    StatementNode(const std::string & file_name, int file_line, size_t line_column) :
+        filename_(file_name),
+        line_(file_line),
+        column_(line_column) {}
+
+    virtual ~StatementNode()                                      = default;
+    virtual void interpret(class Interpreter & interpreter) const = 0;
+    virtual std::string toString() const = 0;
+};
+
+};  // namespace Interpreter
+
+#endif  // STATEMENT_NODE_HPP
diff --git a/src/Interpreter/UnaryExpressionNode.hpp b/src/Interpreter/UnaryExpressionNode.hpp
new file mode 100644
index 0000000..e3abde1
--- /dev/null
+++ b/src/Interpreter/UnaryExpressionNode.hpp
@@ -0,0 +1,64 @@
+#ifndef UNARY_EXPRESSION_NODE_HPP
+#define UNARY_EXPRESSION_NODE_HPP
+
+#include <memory>
+#include <string>
+
+#include "ExpressionNode.hpp"
+
+namespace Interpreter {
+
+class UnaryExpressionNode : public ExpressionNode {
+    std::string                     op_;
+    std::unique_ptr<ExpressionNode> operand_;
+
+  public:
+    UnaryExpressionNode(std::string op, std::unique_ptr<ExpressionNode> operand) :
+        op_(std::move(op)),
+        operand_(std::move(operand)) {}
+
+    Symbols::Value evaluate(Interpreter & interpreter) const override {
+        auto value = operand_->evaluate(interpreter);
+        auto type  = value.getType();
+
+        if (type == Symbols::Variables::Type::INTEGER) {
+            int v = value.get<int>();
+            if (op_ == "-") {
+                return Symbols::Value(-v);
+            }
+            if (op_ == "+") {
+                return Symbols::Value(+v);
+            }
+        } else if (type == Symbols::Variables::Type::DOUBLE) {
+            double v = value.get<double>();
+            if (op_ == "-") {
+                return Symbols::Value(-v);
+            }
+            if (op_ == "+") {
+                return Symbols::Value(+v);
+            }
+        } else if (type == Symbols::Variables::Type::FLOAT) {
+            float v = value.get<float>();
+            if (op_ == "-") {
+                return Symbols::Value(-v);
+            }
+            if (op_ == "+") {
+                return Symbols::Value(+v);
+            }
+        } else if (type == Symbols::Variables::Type::BOOLEAN) {
+            bool v = value.get<bool>();
+            if (op_ == "!") {
+                return Symbols::Value(!v);
+            }
+        }
+
+        throw std::runtime_error("Unsupported unary operator '" + op_ +
+                                 "' for type: " + Symbols::Variables::TypeToString(type));
+    }
+
+    std::string toString() const override { return "(" + op_ + operand_->toString() + ")"; }
+};
+
+}  // namespace Interpreter
+
+#endif  // UNARY_EXPRESSION_NODE_HPP
diff --git a/src/Interpreter/VariableExpressionNode.hpp b/src/Interpreter/VariableExpressionNode.hpp
new file mode 100644
index 0000000..6171fc3
--- /dev/null
+++ b/src/Interpreter/VariableExpressionNode.hpp
@@ -0,0 +1,36 @@
+#ifndef VARIABLEEXPRESSIONNODE_HPP
+#define VARIABLEEXPRESSIONNODE_HPP
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "Interpreter/ExpressionNode.hpp"
+#include "Interpreter/Interpreter.hpp"
+#include "Symbols/SymbolContainer.hpp"
+#include "Symbols/Value.hpp"
+
+namespace Interpreter {
+class VariableExpressionNode : public ExpressionNode {
+    std::string variableName_;
+    std::string ns;
+
+  public:
+    VariableExpressionNode(std::string varName, std::string ns) :
+        variableName_(std::move(varName)),
+        ns(std::move(ns)) {}
+
+    Symbols::Value evaluate(Interpreter & interpreter) const override {
+        if (!Symbols::SymbolContainer::instance()->exists(variableName_)) {
+            throw std::runtime_error("Variable not found: " + variableName_);
+        }
+        auto symbol = Symbols::SymbolContainer::instance()->get(ns, variableName_);
+        return symbol->getValue();
+    }
+
+    std::string toString() const override { return "$" + variableName_; }
+};
+
+};  // namespace Interpreter
+
+#endif  // VARIABLEEXPRESSIONNODE_HPP
diff --git a/src/Interpreter/VariableReferenceNode.hpp b/src/Interpreter/VariableReferenceNode.hpp
new file mode 100644
index 0000000..2906570
--- /dev/null
+++ b/src/Interpreter/VariableReferenceNode.hpp
@@ -0,0 +1,37 @@
+#ifndef INTERPRETER_VARIABLE_REFERENCE_NODE_HPP
+#define INTERPRETER_VARIABLE_REFERENCE_NODE_HPP
+
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include "ExpressionNode.hpp"
+#include "Symbols/SymbolContainer.hpp"
+#include "Symbols/Value.hpp"
+#include "Symbols/VariableSymbol.hpp"
+
+namespace Interpreter {
+class VariableReferenceNode : public ExpressionNode {
+    std::string variableName_;
+    std::string namespace_;  // pl. "global.variables"
+
+  public:
+    VariableReferenceNode(const std::string & variableName, const std::string & ns) :
+        variableName_(variableName),
+        namespace_(ns) {}
+
+    Symbols::Value evaluate(class Interpreter & /*interpreter*/) const override {
+        auto symbol = Symbols::SymbolContainer::instance()->get(namespace_, variableName_);
+        if (!symbol) {
+            throw std::runtime_error("Variable not found: " + variableName_);
+        }
+        auto varSymbol = std::dynamic_pointer_cast<Symbols::VariableSymbol>(symbol);
+        if (!varSymbol) {
+            throw std::runtime_error("Symbol is not a variable: " + variableName_);
+        }
+        return varSymbol->getValue();
+    }
+};
+
+};  // namespace Interpreter
+#endif  // INTERPRETER_VARIABLE_REFERENCE_NODE_HPP
diff --git a/src/Lexer/Lexer.hpp b/src/Lexer/Lexer.hpp
index 737ec1d..4bd0ecf 100644
--- a/src/Lexer/Lexer.hpp
+++ b/src/Lexer/Lexer.hpp
@@ -1,14 +1,15 @@
 #ifndef LEXER_HPP
 #define LEXER_HPP
 
-#include <algorithm>    // std::find_if
-#include <cctype>       // <<< Hozzáadva
+#include <algorithm>
+#include <cctype>
 #include <string>
-#include <string_view>  // <<< Hozzáadva
+#include <string_view>
 #include <unordered_map>
 #include <vector>
 
-#include "Token.hpp"  // Feltételezzük, hogy ez a fenti Token.hpp
+#include "Symbols/SymbolContainer.hpp"
+#include "Token.hpp"
 
 namespace Lexer {
 class Lexer {
@@ -32,14 +33,13 @@
         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);
+        Symbols::SymbolContainer::instance()->enter(ns);
+
         std::vector<Tokens::Token> tokens;
         Tokens::Token              token;
         do {
@@ -73,7 +73,7 @@
         if (isalpha(c) || c == '_') {
             return matchIdentifierOrKeyword(start);
         }
-        if (isdigit(c) || (isdigit(c) && peek(1) == '.')|| (c == '.' && isdigit(peek(1)))) {
+        if (isdigit(c) || (isdigit(c) && peek(1) == '.') || (c == '.' && isdigit(peek(1)))) {
             return matchNumber(start);
         }
         if (c == '"' || c == '\'') {
@@ -96,7 +96,6 @@
     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
@@ -109,13 +108,41 @@
     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_); }
+    const std::string & input() const {
+        const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+        auto         it = inputs_.find(ns);
+        if (it != inputs_.end()) {
+            return it->second;
+        }
+        throw std::runtime_error("Input not found in namespace: " + ns);
+    }
 
-    size_t & pos() { return positions_[current_namespace_]; }
+    size_t & pos() {
+        const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+        auto         it = positions_.find(ns);
+        if (it != positions_.end()) {
+            return it->second;
+        }
+        throw std::runtime_error("Unknown position in namespace: " + ns);
+    }
 
-    int & line() { return line_numbers_[current_namespace_]; }
+    int & line() {
+        const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+        auto         it = line_numbers_.find(ns);
+        if (it != line_numbers_.end()) {
+            return it->second;
+        }
+        throw std::runtime_error("Unknown line number in namespace: " + ns);
+    }
 
-    int & col() { return column_numbers_[current_namespace_]; }
+    int & col() {
+        const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+        auto         it = column_numbers_.find(ns);
+        if (it != column_numbers_.end()) {
+            return it->second;
+        }
+        throw std::runtime_error("Unknown column number in namespace: " + ns);
+    }
 
     Tokens::Token createToken(Tokens::Type type, size_t start, size_t end, const std::string & value = "") {
         Tokens::Token token;
@@ -134,8 +161,9 @@
     // --------------------------------------
 
     char peek(size_t offset = 0) const {
-        const auto & in = inputs_.at(current_namespace_);
-        size_t       cp = positions_.at(current_namespace_);
+        const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+        const auto & in = inputs_.at(ns);
+        size_t       cp = positions_.at(ns);
         if (cp + offset >= in.length()) {
             return '\0';
         }
@@ -154,10 +182,9 @@
         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 == '#');
+    bool isAtEnd() const {
+        const auto & ns = Symbols::SymbolContainer::instance()->currentScopeName();
+        return positions_.at(ns) >= inputs_.at(ns).length();
     }
 
     void skipWhitespaceAndComments() {
diff --git a/src/Lexer/TokenType.hpp b/src/Lexer/TokenType.hpp
index 2dd49ca..e29ba04 100644
--- a/src/Lexer/TokenType.hpp
+++ b/src/Lexer/TokenType.hpp
@@ -25,7 +25,7 @@
     KEYWORD_DOUBLE,
     KEYWORD_FLOAT,
     KEYWORD_BOOLEAN,
-    KEYWORD_FUNCTION,
+    KEYWORD_FUNCTION_DECLARATION,
     KEYWORD_RETURN,
     KEYWORD_NULL,
     UNKNOWN  // Ismeretlen karakter/szekvencia
@@ -69,7 +69,7 @@
             return "KEYWORD_FLOAT";
         case Lexer::Tokens::Type::KEYWORD_BOOLEAN:
             return "KEYWORD_BOOLEAN";
-        case Lexer::Tokens::Type::KEYWORD_FUNCTION:
+        case Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION:
             return "KEYWORD_FUNCTION";
         case Lexer::Tokens::Type::KEYWORD_RETURN:
             return "KEYWORD_RETURN";
diff --git a/src/Parser/ParsedExpression.hpp b/src/Parser/ParsedExpression.hpp
new file mode 100644
index 0000000..3f74478
--- /dev/null
+++ b/src/Parser/ParsedExpression.hpp
@@ -0,0 +1,66 @@
+#ifndef PARSEDEXPRESSION_HPP
+#define PARSEDEXPRESSION_HPP
+
+#include <memory>
+#include <string>
+
+#include "Symbols/Value.hpp"
+
+namespace Parser {
+
+struct ParsedExpression;
+
+using ParsedExpressionPtr = std::unique_ptr<ParsedExpression>;
+
+struct ParsedExpression {
+    enum class Kind : std::uint8_t { Literal, Variable, Binary, Unary };
+
+    Kind kind;
+
+    Symbols::Value value;
+    std::string    name;
+
+    // Műveletekhez
+    std::string         op;
+    ParsedExpressionPtr lhs;
+    ParsedExpressionPtr rhs;
+
+    // Konstruktor literálhoz
+    static ParsedExpressionPtr makeLiteral(const Symbols::Value & val) {
+        auto expr   = std::make_unique<ParsedExpression>();
+        expr->kind  = Kind::Literal;
+        expr->value = val;
+        return expr;
+    }
+
+    // Konstruktor változóhoz
+    static ParsedExpressionPtr makeVariable(const std::string & name) {
+        auto expr  = std::make_unique<ParsedExpression>();
+        expr->kind = Kind::Variable;
+        expr->name = name;
+        return expr;
+    }
+
+    // Konstruktor binárishoz
+    static ParsedExpressionPtr makeBinary(std::string op, ParsedExpressionPtr left, ParsedExpressionPtr right) {
+        auto expr  = std::make_unique<ParsedExpression>();
+        expr->kind = Kind::Binary;
+        expr->op   = std::move(op);
+        expr->lhs  = std::move(left);
+        expr->rhs  = std::move(right);
+        return expr;
+    }
+
+    // Konstruktor unárishoz
+    static ParsedExpressionPtr makeUnary(std::string op, ParsedExpressionPtr operand) {
+        auto expr  = std::make_unique<ParsedExpression>();
+        expr->kind = Kind::Unary;
+        expr->op   = std::move(op);
+        expr->rhs  = std::move(operand);
+        return expr;
+    }
+};
+
+}  // namespace Parser
+
+#endif  // PARSEDEXPRESSION_HPP
diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp
index fbd0e73..3c5af2b 100644
--- a/src/Parser/Parser.cpp
+++ b/src/Parser/Parser.cpp
@@ -9,7 +9,7 @@
     { "while",    Lexer::Tokens::Type::KEYWORD          },
     { "for",      Lexer::Tokens::Type::KEYWORD          },
     { "return",   Lexer::Tokens::Type::KEYWORD_RETURN   },
-    { "function", Lexer::Tokens::Type::KEYWORD_FUNCTION },
+    { "function", Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION },
     // Régebbiek:
     { "const",    Lexer::Tokens::Type::KEYWORD          },
     { "true",     Lexer::Tokens::Type::KEYWORD          },
diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp
index b40397e..41a7545 100644
--- a/src/Parser/Parser.hpp
+++ b/src/Parser/Parser.hpp
@@ -3,17 +3,19 @@
 
 #include <algorithm>
 #include <memory>
-#include <sstream>  // Hibaüzenetekhez
+#include <stack>
 #include <stdexcept>
 #include <string>
 #include <vector>
 
-// Szükséges header-ök a Lexer és Symbol komponensekből
+#include "Interpreter/ExpressionBuilder.hpp"
+#include "Interpreter/OperationsFactory.hpp"
 #include "Lexer/Token.hpp"
-#include "Lexer/TokenType.hpp"  // Enum és TypeToString
+#include "Lexer/TokenType.hpp"
+#include "Parser/ParsedExpression.hpp"
+#include "Symbols/ParameterContainer.hpp"
 #include "Symbols/SymbolContainer.hpp"
-#include "Symbols/SymbolFactory.hpp"
-#include "Symbols/Value.hpp"  // Symbols::Value miatt
+#include "Symbols/Value.hpp"
 
 namespace Parser {
 
@@ -32,11 +34,13 @@
   public:
     Parser() {}
 
-    void parseProgram(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string) {
+    void parseScript(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string,
+                     const std::string & filename) {
         tokens_              = tokens;
         input_str_view_      = input_string;
         current_token_index_ = 0;
-        symbol_container_    = std::make_unique<Symbols::SymbolContainer>();
+        current_filename_    = filename;
+
         try {
             while (!isAtEnd() && currentToken().type != Lexer::Tokens::Type::END_OF_FILE) {
                 parseStatement();
@@ -52,21 +56,14 @@
         }
     }
 
-    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_;
+    std::vector<Lexer::Tokens::Token> tokens_;
+    std::string_view                  input_str_view_;
+    size_t                            current_token_index_;
+    std::string                       current_filename_;
 
     // Token Stream Kezelő és Hibakezelő segédfüggvények (változatlanok)
     const Lexer::Tokens::Token & currentToken() const {
@@ -182,7 +179,7 @@
     void parseStatement() {
         const auto & token_type = currentToken().type;
 
-        if (token_type == Lexer::Tokens::Type::KEYWORD_FUNCTION) {
+        if (token_type == Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION) {
             parseFunctionDefinition();
             return;
         }
@@ -197,40 +194,33 @@
         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;
+        Symbols::Variables::Type var_type = parseType();
+
         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);
         }
+        const auto ns = Symbols::SymbolContainer::instance()->currentScopeName();
 
         expect(Lexer::Tokens::Type::OPERATOR_ASSIGNMENT, "=");
-        Symbols::Value initial_value = parseValue(var_type_enum);
+        /*
+        Symbols::Value initial_value = parseValue(var_type);
+
+        Interpreter::OperationsFactory::defineSimpleVariable(var_name, initial_value, ns, this->current_filename_,
+                                                             id_token.line_number, id_token.column_number);
+*/
+
+        auto expr = parseParsedExpression(var_type);
+        Interpreter::OperationsFactory::defineVariableWithExpression(
+            var_name, var_type, std::move(expr), ns, current_filename_, id_token.line_number, id_token.column_number);
         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);
+        expect(Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION);
         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;
@@ -242,7 +232,6 @@
         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)
@@ -275,50 +264,10 @@
             }
         }
 
-        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";
+        parseFunctionBody(opening_brace, func_name, func_return_type, param_infos);
     }
 
     // --- Elemzési Segédfüggvények ---
@@ -337,118 +286,96 @@
         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();
+        Lexer::Tokens::Token token       = currentToken();
+        bool                 is_negative = false;
 
-        /// 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;
+        // Előjel kezelése
+        if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC && (token.lexeme == "-" || token.lexeme == "+") &&
+            peekToken().type == Lexer::Tokens::Type::NUMBER) {
+            is_negative = (token.lexeme == "-");
             token       = peekToken();
-            consumeToken();
+            consumeToken();  // előjelet elfogyasztottuk
         }
 
+        // STRING típus
         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
+                return Symbols::Value(token.value);
             }
             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
+
+        // BOOLEAN típus
+        if (expected_var_type == Symbols::Variables::Type::BOOLEAN) {
+            if (token.type == Lexer::Tokens::Type::KEYWORD && (token.value == "true" || token.value == "false")) {
+                consumeToken();
+                return Symbols::Value(token.value == "true");
+            }
+            reportError("Expected boolean literal value (true or false)");
+        }
+
+        // NUMERIC típusok
+        if (expected_var_type == Symbols::Variables::Type::INTEGER ||
+            expected_var_type == Symbols::Variables::Type::DOUBLE ||
+            expected_var_type == Symbols::Variables::Type::FLOAT) {
+            if (token.type == Lexer::Tokens::Type::NUMBER) {
+                Symbols::Value val = parseNumericLiteral(token.value, is_negative, expected_var_type);
+                consumeToken();
+                return val;
+            }
+
+            reportError("Expected numeric literal value");
+        }
+
+        reportError("Unsupported variable type encountered during value parsing");
+        return Symbols::Value();  // compiler happy
     }
 
-    Symbols::SymbolContainer parseFunctionBody(const Lexer::Tokens::Token & opening_brace,
-                                               bool                         return_required = false) {
+    Symbols::Value parseNumericLiteral(const std::string & value, bool is_negative, Symbols::Variables::Type type) {
+        try {
+            switch (type) {
+                case Symbols::Variables::Type::INTEGER:
+                    {
+                        if (value.find('.') != std::string::npos) {
+                            throw std::invalid_argument("Floating point value in integer context: " + value);
+                        }
+                        int v = std::stoi(value);
+                        return Symbols::Value(is_negative ? -v : v);
+                    }
+                case Symbols::Variables::Type::DOUBLE:
+                    {
+                        double v = std::stod(value);
+                        return Symbols::Value(is_negative ? -v : v);
+                    }
+                case Symbols::Variables::Type::FLOAT:
+                    {
+                        float v = std::stof(value);
+                        return Symbols::Value(is_negative ? -v : v);
+                    }
+                default:
+                    throw std::invalid_argument("Unsupported numeric type");
+            }
+        } catch (const std::invalid_argument & e) {
+            reportError("Invalid numeric literal: " + value + " (" + e.what() + ")");
+        } catch (const std::out_of_range & e) {
+            reportError("Numeric literal out of range: " + value + " (" + e.what() + ")");
+        }
+
+        return Symbols::Value();  // unreachable
+    }
+
+    void parseFunctionBody(const Lexer::Tokens::Token & opening_brace, const std::string & function_name,
+                           Symbols::Variables::Type return_type, const Symbols::FunctionParameterInfo & params) {
         size_t               braceDepth = 0;
+        int                  peek       = 0;
         int                  tokenIndex = current_token_index_;
         Lexer::Tokens::Token currentToken_;
         Lexer::Tokens::Token closing_brace;
 
         while (tokenIndex < tokens_.size()) {
-            currentToken_ = peekToken();
-
+            currentToken_ = peekToken(peek);
             if (currentToken_.type == Lexer::Tokens::Type::PUNCTUATION) {
                 if (currentToken_.value == "{") {
                     ++braceDepth;
@@ -460,6 +387,8 @@
                     --braceDepth;
                 }
             }
+            tokenIndex++;
+            peek++;
         }
         if (braceDepth != 0) {
             reportError("Unmatched braces in function body");
@@ -468,65 +397,190 @@
         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();
+        current_token_index_ = tokenIndex;
+        expect(Lexer::Tokens::Type::PUNCTUATION, "}");
+        const std::string newns = Symbols::SymbolContainer::instance()->currentScopeName() + "." + function_name;
+        Symbols::SymbolContainer::instance()->create(newns);
+        std::shared_ptr<Parser> parser = std::make_shared<Parser>();
+        parser->parseScript(filtered_tokens, input_string, this->current_filename_);
+        Symbols::SymbolContainer::instance()->enterPreviousScope();
+        // create function
+        Interpreter::OperationsFactory::defineFunction(
+            function_name, params, return_type, Symbols::SymbolContainer::instance()->currentScopeName(),
+            this->current_filename_, currentToken_.line_number, currentToken_.column_number);
     }
 
-    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;
+    ParsedExpressionPtr parseParsedExpression(const Symbols::Variables::Type & expected_var_type) {
+        std::stack<std::string>          operator_stack;
+        std::vector<ParsedExpressionPtr> output_queue;
+
+        auto getPrecedence = [](const std::string & op) -> int {
+            if (op == "+" || op == "-") {
+                return 1;
+            }
+            if (op == "*" || op == "/") {
+                return 2;
+            }
+            if (op == "u-" || op == "u+") {
+                return 3;
+            }
+            return 0;
+        };
+
+        auto isLeftAssociative = [](const std::string & op) -> bool {
+            return !(op == "u-" || op == "u+");
+        };
+
+        auto applyOperator = [](const std::string & op, ParsedExpressionPtr rhs, ParsedExpressionPtr lhs = nullptr) {
+            if (op == "u-" || op == "u+") {
+                std::string real_op = (op == "u-") ? "-" : "+";
+                return ParsedExpression::makeUnary(real_op, std::move(rhs));
+            } else {
+                return ParsedExpression::makeBinary(op, std::move(lhs), std::move(rhs));
+            }
+        };
+
+        auto pushOperand = [&](const Lexer::Tokens::Token & token) {
+            if (token.type == Lexer::Tokens::Type::NUMBER || token.type == Lexer::Tokens::Type::STRING_LITERAL ||
+                token.type == Lexer::Tokens::Type::KEYWORD) {
+                output_queue.push_back(
+                    ParsedExpression::makeLiteral(Symbols::Value::fromString(token.value, expected_var_type)));
+            } else if (token.type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) {
+                std::string name = token.value;
+                if (!name.empty() && name[0] == '$') {
+                    name = name.substr(1);
+                }
+                output_queue.push_back(ParsedExpression::makeVariable(name));
+            } else {
+                reportError("Expected literal or variable");
+            }
+        };
+
+        bool expect_unary = true;
 
         while (true) {
-            if (isAtEnd()) {
-                reportError("Unexpected end of file inside function body (missing '}')");
-            }
-            const auto & token = currentToken();
+            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::PUNCTUATION && token.lexeme == "(") {
+                operator_stack.push("(");
+                consumeToken();
+                expect_unary = true;
+            } else if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.lexeme == ")") {
+                consumeToken();
+                while (!operator_stack.empty() && operator_stack.top() != "(") {
+                    std::string op = operator_stack.top();
+                    operator_stack.pop();
+
+                    if (op == "u-" || op == "u+") {
+                        if (output_queue.empty()) {
+                            reportError("Missing operand for unary operator");
+                        }
+                        auto rhs = std::move(output_queue.back());
+                        output_queue.pop_back();
+                        output_queue.push_back(applyOperator(op, std::move(rhs)));
+                    } else {
+                        if (output_queue.size() < 2) {
+                            reportError("Malformed expression");
+                        }
+                        auto rhs = std::move(output_queue.back());
+                        output_queue.pop_back();
+                        auto lhs = std::move(output_queue.back());
+                        output_queue.pop_back();
+                        output_queue.push_back(applyOperator(op, std::move(rhs), std::move(lhs)));
+                    }
                 }
-            }
 
-            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;
+                if (operator_stack.empty() || operator_stack.top() != "(") {
+                    reportError("Mismatched parentheses");
                 }
-                body_ss << token.lexeme;
+                operator_stack.pop();  // remove "("
+                expect_unary = false;
+            } else if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC) {
+                std::string op = std::string(token.lexeme);
+                if (expect_unary && (op == "-" || op == "+")) {
+                    op = "u" + op;  // pl. u-
+                }
+
+                while (!operator_stack.empty()) {
+                    const std::string & top = operator_stack.top();
+                    if ((isLeftAssociative(op) && getPrecedence(op) <= getPrecedence(top)) ||
+                        (!isLeftAssociative(op) && getPrecedence(op) < getPrecedence(top))) {
+                        operator_stack.pop();
+
+                        if (top == "u-" || top == "u+") {
+                            if (output_queue.empty()) {
+                                reportError("Missing operand for unary operator");
+                            }
+                            auto rhs = std::move(output_queue.back());
+                            output_queue.pop_back();
+                            output_queue.push_back(applyOperator(top, std::move(rhs)));
+                        } else {
+                            if (output_queue.size() < 2) {
+                                reportError("Malformed expression");
+                            }
+                            auto rhs = std::move(output_queue.back());
+                            output_queue.pop_back();
+                            auto lhs = std::move(output_queue.back());
+                            output_queue.pop_back();
+                            output_queue.push_back(applyOperator(top, std::move(rhs), std::move(lhs)));
+                        }
+                    } else {
+                        break;
+                    }
+                }
+
+                operator_stack.push(op);
+                consumeToken();
+                expect_unary = true;
+            } else if (token.type == Lexer::Tokens::Type::NUMBER || token.type == Lexer::Tokens::Type::STRING_LITERAL ||
+                       token.type == Lexer::Tokens::Type::KEYWORD ||
+                       token.type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) {
+                pushOperand(token);
+                consumeToken();
+                expect_unary = false;
             } else {
-                body_ss << token.lexeme;
+                break;
+            }
+        }
+
+        // Kiürítjük az operator stack-et
+        while (!operator_stack.empty()) {
+            std::string op = operator_stack.top();
+            operator_stack.pop();
+
+            if (op == "(" || op == ")") {
+                reportError("Mismatched parentheses");
             }
 
-            last_token_end_pos = token.end_pos;
-            consumeToken();
+            if (op == "u-" || op == "u+") {
+                if (output_queue.empty()) {
+                    reportError("Missing operand for unary operator");
+                }
+                auto rhs = std::move(output_queue.back());
+                output_queue.pop_back();
+                output_queue.push_back(applyOperator(op, std::move(rhs)));
+            } else {
+                if (output_queue.size() < 2) {
+                    reportError("Malformed expression");
+                }
+                auto rhs = std::move(output_queue.back());
+                output_queue.pop_back();
+                auto lhs = std::move(output_queue.back());
+                output_queue.pop_back();
+                output_queue.push_back(applyOperator(op, std::move(rhs), std::move(lhs)));
+            }
         }
 
-        if (return_required && !has_return) {
-            return "";
+        if (output_queue.size() != 1) {
+            reportError("Expression could not be parsed cleanly");
         }
 
-        return body_ss.str();
+        return std::move(output_queue.back());
     }
 
 };  // class Parser
diff --git a/src/Symbols/BaseSymbol.hpp b/src/Symbols/BaseSymbol.hpp
index 2d3cdb2..604463c 100644
--- a/src/Symbols/BaseSymbol.hpp
+++ b/src/Symbols/BaseSymbol.hpp
@@ -13,7 +13,7 @@
   protected:
     std::string   name_;
     Value         value_;
-    std::string   context_;
+    std::string   context_; // ns
     Symbols::Kind kind_;
 
   public:
@@ -40,6 +40,15 @@
 
     virtual void setValue(const Value & value) { value_ = value; }
 
+    std::string dump() const {
+        std::string r = "\t\t  "+ kindToString(this->kind_) + " name: '" + name_ + "' \n\t\t\tContext: " + context_;
+        r += " \n\t\t\tType: " + Symbols::Variables::TypeToString(value_.getType());
+        r += " \n\t\t\tValue: '" + Symbols::Value::to_string(value_) + "'";
+        return r;
+    }
+
+
+
     // Templated getter
     template <typename T> T getAs() const { return std::get<T>(value_); }
 };
diff --git a/src/Symbols/SymbolContainer.hpp b/src/Symbols/SymbolContainer.hpp
index 1985c50..c0bb814 100644
--- a/src/Symbols/SymbolContainer.hpp
+++ b/src/Symbols/SymbolContainer.hpp
@@ -1,51 +1,141 @@
-// SymbolContainer.hpp
 #ifndef SYMBOL_CONTAINER_HPP
 #define SYMBOL_CONTAINER_HPP
 
+#include <memory>
+#include <stdexcept>
+#include <unordered_map>
+
 #include "SymbolTable.hpp"
+
+#define NSMGR Symbols::SymbolContainer::instance()
 
 namespace Symbols {
 
 class SymbolContainer {
-    std::shared_ptr<SymbolTable> globalScope_;
-    std::shared_ptr<SymbolTable> currentScope_;
+    std::unordered_map<std::string, std::shared_ptr<SymbolTable>> scopes_;
+    std::string                                                   currentScope_  = "global";
+    std::string                                                   previousScope_ = "global";
 
-public:
-    SymbolContainer() {
-        globalScope_ = std::make_shared<SymbolTable>();
-        currentScope_ = globalScope_;
+  public:
+    static SymbolContainer * instance() {
+        static SymbolContainer instance_;
+        return &instance_;
     }
 
-    void enterScope() {
-        currentScope_ = std::make_shared<SymbolTable>(currentScope_);
+    explicit SymbolContainer(const std::string & default_scope_name = "global") { create(default_scope_name); }
+
+    // --- Scope management ---
+
+    void create(const std::string & name) {
+        scopes_[name]  = std::make_shared<SymbolTable>();
+        previousScope_ = currentScope_;
+        currentScope_  = name;
     }
 
-    void leaveScope() {
-        if (currentScope_->getParent()) {
-            currentScope_ = currentScope_->getParent();
+    void enter(const std::string & name) {
+        if (scopes_.contains(name)) {
+            previousScope_ = currentScope_;
+            currentScope_  = name;
+        } else {
+            throw std::runtime_error("Scope does not exist: " + name);
         }
     }
 
-    void define(const std::string& ns, const SymbolPtr& symbol) {
-        currentScope_->define(ns, symbol);
+    void enterPreviousScope() { currentScope_ = previousScope_; }
+
+    [[nodiscard]] std::string currentScopeName() const { return currentScope_; }
+
+    std::vector<std::string> getScopeNames() const {
+        std::vector<std::string> result;
+        result.reserve(scopes_.size());
+        for (const auto & [scopeName, _] : scopes_) {
+            result.push_back(scopeName);
+        }
+        return result;
     }
 
-    SymbolPtr resolve(const std::string& ns, const std::string& name) const {
-        return currentScope_->get(ns, name);
+    // --- Symbol operations ---
+
+    std::string add(const SymbolPtr & symbol) {
+        const std::string ns = getNamespaceForSymbol(symbol);
+        scopes_[currentScope_]->define(ns, symbol);
+        return ns;
     }
 
-    bool exists(const std::string& ns, const std::string& name) const {
-        return currentScope_->exists(ns, name);
+    std::vector<std::string> getNameSpaces(const std::string & scopeName) const {
+        std::vector<std::string> result;
+        auto                     it = scopes_.find(scopeName);
+        if (it != scopes_.end()) {
+            return it->second->listNSs();
+        }
+        return result;
     }
 
-    std::vector<SymbolPtr> listNamespace(const std::string& ns) const {
-        return currentScope_->listAll(ns);
+    std::vector<SymbolPtr> getAll(const std::string & ns = "") const {
+        std::vector<SymbolPtr> result;
+        for (const auto & [_, table] : scopes_) {
+            auto symbols = ns.empty() ? table->listAll() : table->listAll(ns);
+            result.insert(result.end(), symbols.begin(), symbols.end());
+        }
+        return result;
     }
 
-    std::shared_ptr<SymbolTable> getGlobalScope() const { return globalScope_; }
-    std::shared_ptr<SymbolTable> getCurrentScope() const { return currentScope_; }
+    bool exists(const std::string & name, std::string fullNamespace = "") const {
+        if (fullNamespace.empty()) {
+            fullNamespace = currentScope_;
+        }
+
+        for (const auto & [_, table] : scopes_) {
+            if (table->exists(fullNamespace, name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    SymbolPtr get(const std::string & fullNamespace, const std::string & name) const {
+        for (const auto & [_, table] : scopes_) {
+            auto sym = table->get(fullNamespace, name);
+            if (sym) {
+                return sym;
+            }
+        }
+        return nullptr;
+    }
+
+    static std::string dump() {
+        std::string result = "";
+
+        std::cout << "\n--- Defined Scopes ---" << '\n';
+        for (const auto & scope_name : instance()->getScopeNames()) {
+            result += scope_name + '\n';
+            for (const auto & sname : instance()->getNameSpaces(scope_name)) {
+                result += "\t -" + sname + '\n';
+                for (const auto & symbol : instance()->getAll(sname)) {
+                    result += symbol->dump() + '\n';
+                }
+            }
+        }
+        return result;
+    }
+
+  private:
+    std::string getNamespaceForSymbol(const SymbolPtr & symbol) const {
+        std::string base = symbol->context().empty() ? currentScope_ : symbol->context();
+
+        switch (symbol->type()) {
+            case Symbols::Kind::Variable:
+                return base + ".variables";
+            case Symbols::Kind::Function:
+                return base + ".functions";
+            case Symbols::Kind::Constant:
+                return base + ".constants";
+            default:
+                return base + ".others";
+        }
+    }
 };
 
-} // namespace Symbols
+}  // namespace Symbols
 
 #endif
diff --git a/src/Symbols/SymbolKind.hpp b/src/Symbols/SymbolKind.hpp
index 5f9c8e8..8b4c5bf 100644
--- a/src/Symbols/SymbolKind.hpp
+++ b/src/Symbols/SymbolKind.hpp
@@ -3,6 +3,8 @@
 #define SYMBOL_KIND_HPP
 
 #include <cstdint>
+#include <string>
+#include <unordered_map>
 
 namespace Symbols {
 
@@ -13,6 +15,19 @@
     // Later: Module, Class, etc..
 };
 
-}; // namespace Symbols
+static std::string kindToString(Symbols::Kind kind) {
+    std::unordered_map<Symbols::Kind, std::string> KindToString = {
+        { Symbols::Kind::Variable, "Variable" },
+        { Symbols::Kind::Constant, "Constant" },
+        { Symbols::Kind::Function, "Function" },
+    };
+
+    auto it = KindToString.find(kind);
+    if (it != KindToString.end()) {
+        return it->second;
+    }
+    return "Unknown kind: " + std::to_string(static_cast<int>(kind));
+}
+};  // namespace Symbols
 
 #endif
diff --git a/src/Symbols/SymbolTable.hpp b/src/Symbols/SymbolTable.hpp
index 0c4c7da..f774f8d 100644
--- a/src/Symbols/SymbolTable.hpp
+++ b/src/Symbols/SymbolTable.hpp
@@ -1,4 +1,3 @@
-// SymbolTable.hpp
 #ifndef SYMBOL_TABLE_HPP
 #define SYMBOL_TABLE_HPP
 
@@ -10,12 +9,9 @@
 namespace Symbols {
 
 class SymbolTable {
-    NamespaceMap                 symbols_;
-    std::shared_ptr<SymbolTable> parent_ = nullptr;
+    NamespaceMap symbols_;
 
   public:
-    SymbolTable(std::shared_ptr<SymbolTable> parent = nullptr) : parent_(std::move(parent)) {}
-
     void define(const std::string & ns, const SymbolPtr & symbol) { symbols_[ns][symbol->name()] = symbol; }
 
     bool exists(const std::string & ns, const std::string & name) const { return get(ns, name) != nullptr; }
@@ -29,10 +25,6 @@
                 return it->second;
             }
         }
-        // Rekurzívan keresünk a szülő scope-ban
-        if (parent_) {
-            return parent_->get(ns, name);
-        }
         return nullptr;
     }
 
@@ -43,12 +35,21 @@
         }
     }
 
-    std::vector<SymbolPtr> listAll(const std::string & ns) const {
+    std::vector<std::string> listNSs() {
+        std::vector<std::string> result;
+        for (const auto & [ns, _] : symbols_) {
+            result.push_back(ns);
+        }
+        return result;
+    }
+
+    std::vector<SymbolPtr> listAll(const std::string & prefix = "") const {
         std::vector<SymbolPtr> result;
-        auto                   it = symbols_.find(ns);
-        if (it != symbols_.end()) {
-            for (const auto & [_, sym] : it->second) {
-                result.push_back(sym);
+        for (const auto & [ns, map] : symbols_) {
+            if (prefix.empty() || ns.starts_with(prefix)) {
+                for (const auto & [_, sym] : map) {
+                    result.push_back(sym);
+                }
             }
         }
         return result;
@@ -57,8 +58,6 @@
     void clear(const std::string & ns) { symbols_.erase(ns); }
 
     void clearAll() { symbols_.clear(); }
-
-    std::shared_ptr<SymbolTable> getParent() const { return parent_; }
 };
 
 }  // namespace Symbols
diff --git a/src/Symbols/Value.hpp b/src/Symbols/Value.hpp
index 4c52b04..a0ff38b 100644
--- a/src/Symbols/Value.hpp
+++ b/src/Symbols/Value.hpp
@@ -1,10 +1,13 @@
 #ifndef SYMBOL_VALUE_HPP
 #define SYMBOL_VALUE_HPP
 
+#include <algorithm>
 #include <iostream>
 #include <stdexcept>
 #include <string>
 #include <variant>
+
+#include "Symbols/VariableTypes.hpp"
 
 namespace Symbols {
 
@@ -14,23 +17,32 @@
 
     Value() = default;
 
-    Value(int v) : value_(v) {}
+    Value(int v) : value_(v) { type_ = Symbols::Variables::Type::INTEGER; }
 
-    Value(double v) : value_(v) {}
+    Value(double v) : value_(v) { type_ = Symbols::Variables::Type::DOUBLE; }
 
-    Value(float v) : value_(v) {}
+    Value(float v) : value_(v) { type_ = Symbols::Variables::Type::FLOAT; }
 
-    Value(const std::string & v) : value_(v) {}
+    Value(const std::string & v) : value_(v) { type_ = Symbols::Variables::Type::STRING; }
 
-    Value(const char * v) : value_(std::string(v)) {}
+    Value(const char * v) : value_(std::string(v)) { type_ = Symbols::Variables::Type::STRING; }
 
-    Value(bool v) : value_(v) {}
+    Value(bool v) : value_(v) { type_ = Symbols::Variables::Type::BOOLEAN; }
+
+    Value(const std::string & str, bool autoDetectType) { *this = fromString(str, autoDetectType); }
 
     const Variant & get() const { return value_; }
+
+    Symbols::Variables::Type getType() const { return type_; }
 
     Variant & get() { return value_; }
 
     template <typename T> T get() const { return std::get<T>(value_); }
+
+    static Symbols::Value makeNull() {
+        auto v = Value("null");
+        return v;
+    }
 
     // operator+
     friend Value operator+(const Value & lhs, const Value & rhs) {
@@ -68,8 +80,87 @@
 
     static std::string to_string(const Value & val) { return to_string(val.value_); }
 
+    static Value fromString(const std::string & str, bool autoDetectType) {
+        if (!autoDetectType) {
+            return fromStringToString(str);
+        }
+
+        std::string trimmed = str;
+        trimmed.erase(0, trimmed.find_first_not_of(" \t\n\r"));
+        trimmed.erase(trimmed.find_last_not_of(" \t\n\r") + 1);
+
+        // Check bool
+        std::string lower = trimmed;
+        std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+        if (lower == "true" || lower == "false" || lower == "1" || lower == "0") {
+            try {
+                return fromStringToBool(trimmed);
+            } catch (...) {
+            }
+        }
+
+        // Check int
+        try {
+            size_t idx;
+            int    i = std::stoi(trimmed, &idx);
+            if (idx == trimmed.size()) {
+                return fromStringToInt(trimmed);
+            }
+        } catch (...) {
+        }
+
+        // Check double
+        try {
+            size_t idx;
+            double d = std::stod(trimmed, &idx);
+            if (idx == trimmed.size()) {
+                return fromStringToDouble(trimmed);
+            }
+        } catch (...) {
+        }
+
+        // Fallback
+        return fromStringToString(str);
+    }
+
+    static Value fromString(const std::string & str, Symbols::Variables::Type type) {
+        switch (type) {
+            case Symbols::Variables::Type::INTEGER:
+                return fromStringToInt(str);
+            case Symbols::Variables::Type::DOUBLE:
+                return fromStringToDouble(str);
+            case Symbols::Variables::Type::FLOAT:
+                return fromStringToFloat(str);
+            case Symbols::Variables::Type::BOOLEAN:
+                return fromStringToBool(str);
+            case Symbols::Variables::Type::STRING:
+            default:
+                return fromStringToString(str);
+        }
+    }
   private:
-    Variant value_;
+    Variant                  value_;
+    Symbols::Variables::Type type_;
+
+    static Value fromStringToInt(const std::string & str) { return Value(std::stoi(str)); }
+
+    static Value fromStringToDouble(const std::string & str) { return Value(std::stod(str)); }
+
+    static Value fromStringToFloat(const std::string & str) { return Value(std::stof(str)); }
+
+    static Value fromStringToBool(const std::string & str) {
+        std::string s = str;
+        std::transform(s.begin(), s.end(), s.begin(), ::tolower);
+        if (s == "true" || s == "1") {
+            return Value(true);
+        }
+        if (s == "false" || s == "0") {
+            return Value(false);
+        }
+        throw std::invalid_argument("Invalid bool string: " + str);
+    }
+
+    static Value fromStringToString(const std::string & str) { return Value(str); }
 };
 
 }  // namespace Symbols
diff --git a/src/VoidScript.hpp b/src/VoidScript.hpp
index d1188b5..4f0aed4 100644
--- a/src/VoidScript.hpp
+++ b/src/VoidScript.hpp
@@ -5,74 +5,68 @@
 #include <fstream>
 #include <string>
 
+#include "Interpreter/Interpreter.hpp"
 #include "Lexer/Lexer.hpp"
 #include "Parser/Parser.hpp"
 
 class VoidScript {
   private:
-    std::string                     file;
+    std::vector<std::string>        files;
     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) {
+    static std::string readFile(const std::string & 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);
+            return "";
         }
-        file_content = std::string((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
+        std::string content = std::string((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
         input.close();
+        return content;
+    }
+
+  public:
+    VoidScript(const std::string & file) :
+
+        lexer(std::make_shared<Lexer::Lexer>()),
+        parser(std::make_shared<Parser::Parser>()) {
+        this->files.emplace(this->files.begin(), file);
+
+        lexer->setKeyWords(Parser::Parser::keywords);
     }
 
     int run() {
         try {
-            this->lexer->addNamespaceInput(this->file, this->file_content);
-            const auto tokens = this->lexer->tokenizeNamespace(this->file);
+            while (!files.empty()) {
+                std::string file = files.back();
+                const std::string file_content = readFile(file);
+                files.pop_back();
 
-            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::string _default_namespace_ = file;
+                std::replace(_default_namespace_.begin(), _default_namespace_.end(), '.', '_');
 
-            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';
-                }
-            }
+                Symbols::SymbolContainer::instance()->create(_default_namespace_);
 
-            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';
-                }
-            }
+
+                const std::string ns = Symbols::SymbolContainer::instance()->currentScopeName();
+
+                this->lexer->addNamespaceInput(ns, file_content);
+                const auto tokens = this->lexer->tokenizeNamespace(ns);
+
+                std::cout << Operations::Container::dump() << "\n";
+
+                parser->parseScript(tokens, file_content, file);
+
+                Interpreter::Interpreter interpreter;
+                interpreter.run();
+
+                std::cout << Symbols::SymbolContainer::dump() << "\n";
+            }  // while (!files.empty())
 
             return 0;
         } catch (const Parser::SyntaxError & e) {

--
Gitblit v1.9.3