A simple scripting language in C++
Ferenc Szontágh
2025-04-17 ba9a9199d01b0fdd4bf9a54914f8058bf71f30c5
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) {