Skip to content
Authors

File main.cpp

File List > cli > src > main.cpp

Go to the documentation of this file

#include <ostream>
#include <pdgl_defs.h>
#include <production_store.h>
#include <toml_parser.h>
#include <resolution_machine.h>

#include <argparse.h>
#include <cstddef>
#include <string>
#include <iostream>
#include <random>

class PDGL_cli {
public:
    PDGL_cli(const std::string *input, size_t stack_size, size_t seed);
    explicit PDGL_cli(const std::string *input);
    ~PDGL_cli();
    bool run();

private:
    void init(const std::string *input, size_t stack_size, size_t seed);

    const std::string *language;                                         
    prodstr_store_t *store;                                              
    resmach_stack_t *stack;                                              
    size_t stack_size;                                                   
    size_t seed;                                                         
};

PDGL_cli::~PDGL_cli()
{
    if (nullptr != this->store)
    {
        tomlprsr_free(this->store);
    }

    for (size_t i = 0; i < this->stack_size; i++)
    {
        delete[] this->stack->partials[i].buff;
    }
    delete[] this->stack->partials;
    delete this->stack;
}

PDGL_cli::PDGL_cli(const std::string *input, size_t stack_size, size_t seed)
{
    this->init(input, stack_size, seed);
}

PDGL_cli::PDGL_cli(const std::string *input)
{
    std::random_device rd;

    this->init(input, 100, rd());
}

void PDGL_cli::init(const std::string *input, size_t stack_size, size_t seed)
{
    this->seed             = seed;
    this->language         = input;
    this->store            = nullptr;
    this->stack_size       = stack_size;
    this->stack            = new resmach_stack_t{ nullptr };
    this->stack->stack_len = this->stack_size;
    this->stack->partials  = new resmach_partial_t[this->stack_size];
    for (size_t i = 0; i < this->stack_size; i++)
    {
        this->stack->partials[i].partial_ptr = new char[DEFS_PDGL_MAX_STRING_SIZE];
        this->stack->partials[i].buff        =
            static_cast <const char *>(this->stack->partials[i].partial_ptr);
    }
}

bool PDGL_cli::run()
{
    /* Parse the TOML */
    this->store = tomlprsr_parse(static_cast <const char *>(this->language->c_str()));
    if (nullptr != this->store)
    {
        srand(this->seed);

        /* Run the machine */
        unsigned int ret_val = resmach_execute(this->store, this->stack, stdout);

        if (ret_val != RESMACH_EXECUTE_SUCCESS)
        {
            /* When error happens, diagnose it and report. */
            std::string error_rpt = "";
            if ((ret_val & RESMACH_EXECUTE_NO_ENTRY) == RESMACH_EXECUTE_NO_ENTRY)
            {
                error_rpt += "* No entry production in toml\n";
            }
            std::cout << "Error in execution! Found the following:" << std::endl << error_rpt
                      << std::endl;
            return false;
        }
    }
    else
    {
        std::cout
            <<
            "Error in Parsing the toml! Check your toml syntax and check you have an entry production."
            << std::endl;
        return false;
    }
    std::cout << std::endl;
    return true;
}

static const char *const usages[] = {
    "pdgl_cli [options] ",
    NULL,
};

int main(int argc, const char **argv)
{
    size_t count      = 10u;
    size_t stack_size = 100u;

    struct argparse_option options[] = {
        OPT_HELP(),
        OPT_GROUP("Basic options"),
        OPT_INTEGER('c',
                    "count",
                    &count,
                    "Number of words to produce.",
                    NULL,
                    0,
                    0),
        OPT_INTEGER('s',
                    "stack",
                    &stack_size,
                    "Size of stack to use",
                    NULL,
                    0,
                    0),
        OPT_END(),
    };
    struct argparse        argparse;

    argparse_init(&argparse, options, usages, 0);
    argparse_describe(&argparse, "\nGenerate words in a grammar.",
                      "\nGenerate words in a grammar.");
    (void)argparse_parse(&argparse, argc, argv);

    std::random_device rd;
    std::string        language;

    /*@@@NOTE: I'm not sure if this is really a great way to do this. It requires feeding of an EOF
     * symbol. */
    do{
        std::string temp;
        std::getline(std::cin, temp);
        language += temp + "\n";
    }while (!std::cin.eof());

    for (size_t i = 0; i < count; i++)
    {
        PDGL_cli *pdgl    = new PDGL_cli(&language, stack_size, rd());
        bool      success = pdgl->run();
        delete pdgl;
        if (!success)
        {
            return 1;
        }
    }

    return 0;
}