| .env | ●●●●● patch | view | raw | blame | history | |
| .gitignore | ●●●●● patch | view | raw | blame | history | |
| .gitsecret/paths/mapping.cfg | patch | view | raw | blame | history | |
| src/Interpreter/Interpreter.hpp | ●●●●● patch | view | raw | blame | history | |
| src/Interpreter/Operation.hpp | ●●●●● patch | view | raw | blame | history | |
| src/Interpreter/OperationsFactory.hpp | ●●●●● patch | view | raw | blame | history | |
| src/Parser/ParsedExpression.hpp | ●●●●● patch | view | raw | blame | history | |
| src/Parser/Parser.cpp | ●●●●● patch | view | raw | blame | history | |
| src/Parser/Parser.hpp | ●●●●● patch | view | raw | blame | history | |
| src/Symbols/SymbolContainer.hpp | ●●●●● patch | view | raw | blame | history | |
| src/Symbols/SymbolTable.hpp | ●●●●● patch | view | raw | blame | history | |
| src/Symbols/Value.hpp | ●●●●● patch | view | raw | blame | history | |
| src/VoidScript.hpp | ●●●●● patch | view | raw | blame | history |
.env
New file @@ -0,0 +1 @@ OPENAI_API_KEY=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 .gitignore
@@ -22,3 +22,5 @@ .vscode .cache build .gitsecret/keys/random_seed !*.secret .gitsecret/paths/mapping.cfg
src/Interpreter/Interpreter.hpp
@@ -6,6 +6,7 @@ #include "Interpreter/Operation.hpp" #include "Interpreter/OperationContainer.hpp" #include "Symbols/SymbolContainer.hpp" namespace Interpreter { @@ -38,7 +39,13 @@ break; } case Operations::Type::FunctionCall: case Operations::Type::FunctionCall: { // Check that the called function is defined in the symbol table if (!Symbols::SymbolContainer::instance()->exists(op.targetName)) { throw std::runtime_error("Function not declared: " + op.targetName); } break; } case Operations::Type::Return: case Operations::Type::Loop: case Operations::Type::Break: @@ -47,7 +54,7 @@ case Operations::Type::Import: case Operations::Type::Error: case Operations::Type::Conditional: // TODO: implementálható később // TODO: implement these operations later break; default: throw std::runtime_error("Not implemented operation type"); src/Interpreter/Operation.hpp
@@ -6,7 +6,7 @@ #include <string> #include <unordered_map> #include "Interpreter/StatementNode.hpp" #include "StatementNode.hpp" namespace Operations { enum class Type : std::uint8_t { @@ -62,7 +62,8 @@ } std::string toString() const { return "Target: " + targetName + " Type: " + this->typeToString() + " Statement: " + statement->toString(); return "Target: " + targetName + " Type: " + this->typeToString() + " Statement: " + ((statement == nullptr) ? "no statement" : statement->toString()); } }; }; // namespace Operations src/Interpreter/OperationsFactory.hpp
@@ -52,6 +52,25 @@ Operations::Container::instance()->add( ns, Operations::Operation{Operations::Type::Declaration, varName, std::move(stmt)}); } /** * @brief Record a function call operation for later detection. * @param functionName Name of the function being called. * @param ns Current namespace scope. * @param fileName Source filename. * @param line Line number of call. * @param column Column number of call. */ static void callFunction(const std::string & functionName, const std::string & ns, const std::string & fileName, int line, size_t column) { // No associated StatementNode; this is for detection only Operations::Container::instance()->add( ns, Operations::Operation{Operations::Type::FunctionCall, functionName, nullptr}); } }; } // namespace Interpreter src/Parser/ParsedExpression.hpp
@@ -4,8 +4,8 @@ #include <memory> #include <string> #include "Symbols/SymbolContainer.hpp" #include "Symbols/Value.hpp" #include "../Symbols/SymbolContainer.hpp" #include "../Symbols/Value.hpp" namespace Parser { src/Parser/Parser.cpp
@@ -1,4 +1,5 @@ #include "Parser/Parser.hpp" #include <stack> #include "Interpreter/OperationsFactory.hpp" @@ -108,6 +109,34 @@ parseFunctionBody(opening_brace, func_name, func_return_type, param_infos); } // Parse a top-level function call, e.g., foo(arg1, arg2); void Parser::parseCallStatement() { // Function name auto id_token = expect(Lexer::Tokens::Type::IDENTIFIER); std::string func_name = id_token.value; // Opening parenthesis expect(Lexer::Tokens::Type::PUNCTUATION, "("); // Parse comma-separated argument expressions std::vector<ParsedExpressionPtr> args; if (!(currentToken().type == Lexer::Tokens::Type::PUNCTUATION && currentToken().value == ")")) { while (true) { // Parse expression with no expected type auto expr = parseParsedExpression(Symbols::Variables::Type::NULL_TYPE); args.push_back(std::move(expr)); if (match(Lexer::Tokens::Type::PUNCTUATION, ",")) { continue; } break; } } // Closing parenthesis and semicolon expect(Lexer::Tokens::Type::PUNCTUATION, ")"); expect(Lexer::Tokens::Type::PUNCTUATION, ";"); // Record the function call operation Interpreter::OperationsFactory::callFunction(func_name, Symbols::SymbolContainer::instance()->currentScopeName(), this->current_filename_, id_token.line_number, id_token.column_number); } Symbols::Value Parser::parseNumericLiteral(const std::string & value, bool is_negative, Symbols::Variables::Type type) { try { switch (type) { @@ -210,7 +239,23 @@ consumeToken(); expect_unary = true; } else if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.lexeme == ")") { // Only handle grouping parentheses if a matching "(" exists on the operator stack std::stack<std::string> temp_stack = operator_stack; bool has_paren = false; while (!temp_stack.empty()) { if (temp_stack.top() == "(") { has_paren = true; break; } temp_stack.pop(); } if (!has_paren) { // End of this expression context; do not consume call-closing parenthesis here break; } // Consume the grouping closing parenthesis consumeToken(); // Unwind operators until the matching "(" is found while (!operator_stack.empty() && operator_stack.top() != "(") { std::string op = operator_stack.top(); operator_stack.pop(); @@ -233,11 +278,11 @@ output_queue.push_back(Lexer::applyOperator(op, std::move(rhs), std::move(lhs))); } } if (operator_stack.empty() || operator_stack.top() != "(") { reportError("Mismatched parentheses"); Parser::reportError("Mismatched parentheses", token); } operator_stack.pop(); // remove "(" // Pop the matching "(" operator_stack.pop(); expect_unary = false; } else if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC) { std::string op = std::string(token.lexeme); @@ -254,14 +299,14 @@ if (top == "u-" || top == "u+") { if (output_queue.empty()) { reportError("Missing operand for unary operator"); Parser::reportError("Missing operand for unary operator", token); } auto rhs = std::move(output_queue.back()); output_queue.pop_back(); output_queue.push_back(Lexer::applyOperator(top, std::move(rhs))); } else { if (output_queue.size() < 2) { reportError("Malformed expression"); Parser::reportError("Malformed expression", token); } auto rhs = std::move(output_queue.back()); output_queue.pop_back(); @@ -281,7 +326,7 @@ token.type == Lexer::Tokens::Type::KEYWORD || token.type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) { if (Lexer::pushOperand(token, expected_var_type, output_queue) == false) { reportError("Expected literal or variable"); Parser::reportError("Invalid type", token, "literal or variable"); } consumeToken(); expect_unary = false; @@ -296,12 +341,13 @@ operator_stack.pop(); if (op == "(" || op == ")") { reportError("Mismatched parentheses"); Parser::reportError("Mismatched parentheses", tokens_[current_token_index_]); } if (op == "u-" || op == "u+") { if (output_queue.empty()) { reportError("Missing operand for unary operator"); Parser::reportError("Invalid type", tokens_[current_token_index_], "literal or variable"); } auto rhs = std::move(output_queue.back()); output_queue.pop_back(); @@ -309,6 +355,7 @@ } else { if (output_queue.size() < 2) { reportError("Malformed expression"); Parser::reportError("Mailformed expression", tokens_[current_token_index_]); } auto rhs = std::move(output_queue.back()); output_queue.pop_back(); src/Parser/Parser.hpp
@@ -161,6 +161,11 @@ throw Exception(message, expected, line, col); } [[noreturn]] static void reportError(const std::string & message, const Lexer::Tokens::Token & token, const std::string & expected = "") { throw Exception(message, expected, token); } // parseStatement (unchanged) void parseStatement() { const auto & token_type = currentToken().type; @@ -175,12 +180,20 @@ parseVariableDefinition(); return; } // Function call if identifier followed by '(' if (currentToken().type == Lexer::Tokens::Type::IDENTIFIER && peekToken().type == Lexer::Tokens::Type::PUNCTUATION && peekToken().value == "(") { parseCallStatement(); return; } reportError("Unexpected token at beginning of statement"); } void parseVariableDefinition(); void parseFunctionDefinition(); // Parse a top-level function call statement (e.g., foo(arg1, arg2);) void parseCallStatement(); // --- Parsing helper functions --- src/Symbols/SymbolContainer.hpp
@@ -1,6 +1,7 @@ #ifndef SYMBOL_CONTAINER_HPP #define SYMBOL_CONTAINER_HPP #include <iostream> #include <memory> #include <stdexcept> #include <unordered_map> @@ -33,7 +34,8 @@ } void enter(const std::string & name) { if (scopes_.contains(name)) { auto it = scopes_.find(name); if (it != scopes_.end()) { previousScope_ = currentScope_; currentScope_ = name; } else { @@ -104,7 +106,7 @@ } static std::string dump() { std::string result = ""; std::string result; std::cout << "\n--- Defined Scopes ---" << '\n'; for (const auto & scope_name : instance()->getScopeNames()) { src/Symbols/SymbolTable.hpp
@@ -2,7 +2,7 @@ #define SYMBOL_TABLE_HPP #include <vector> #include <string> #include "SymbolTypes.hpp" namespace Symbols { @@ -45,7 +45,7 @@ std::vector<SymbolPtr> listAll(const std::string & prefix = "") const { std::vector<SymbolPtr> result; for (const auto & [ns, map] : symbols_) { if (prefix.empty() || ns.starts_with(prefix)) { if (prefix.empty() || ns.substr(0,prefix.length()) == prefix) { for (const auto & [_, sym] : map) { result.push_back(sym); } src/Symbols/Value.hpp
@@ -2,12 +2,11 @@ #define SYMBOL_VALUE_HPP #include <algorithm> #include <iostream> #include <stdexcept> #include <string> #include <variant> #include "Symbols/VariableTypes.hpp" #include "VariableTypes.hpp" namespace Symbols { src/VoidScript.hpp
@@ -54,13 +54,6 @@ this->lexer->addNamespaceInput(ns, file_content); const auto tokens = this->lexer->tokenizeNamespace(ns); // dump tokens std::cout << "--- Tokens ---\n"; for (const auto & token : tokens) { token.print(); } std::cout << Operations::Container::dump() << "\n"; parser->parseScript(tokens, file_content, file);