Added 'Parameters' data type

This commit is contained in:
Marco Cetica 2023-11-15 10:23:29 +01:00
parent 2c766fd38e
commit 205c77ef8d
Signed by: marco
GPG Key ID: 45060A949E90D0FD
8 changed files with 101 additions and 63 deletions

View File

@ -29,6 +29,11 @@ int main(int argc, char **argv) {
bool execute_file = false;
dc_stack_t stack;
std::unordered_map<char, Register> regs;
Parameters parameters = {
.precision = 0,
.iradix = 10,
.oradix = radix_base::DEC
};
struct option long_opts[] = {
{"expression", required_argument, nullptr, 'e'},
{"file", required_argument, nullptr, 'f'},
@ -63,7 +68,7 @@ int main(int argc, char **argv) {
// Split string expression into a vector
std::vector<std::string> tokens = Macro::split(cli_expression);
// Evaluate expression
Evaluate evaluator(tokens, regs, stack);
Evaluate evaluator(tokens, regs, stack, parameters);
auto err = evaluator.eval();
// Handle errors
if(err != std::nullopt) {
@ -105,7 +110,7 @@ int main(int argc, char **argv) {
}
// Evaluate expression
Evaluate evaluator(tokens, regs, stack);
Evaluate evaluator(tokens, regs, stack, parameters);
auto err = evaluator.eval();
// Handle errors
if(err != std::nullopt) {
@ -122,7 +127,7 @@ int main(int argc, char **argv) {
// Split string expression into a vector
std::vector<std::string> tokens = Macro::split(stdin_expression);
// Evaluate expression
Evaluate evaluator(tokens, regs, stack);
Evaluate evaluator(tokens, regs, stack, parameters);
auto err = evaluator.eval();
// Handle errors
if(err != std::nullopt) {

View File

@ -191,19 +191,27 @@ std::optional<std::string> Evaluate::eval() {
return err;
}
} else if(val == "k") { // SET PRECISION
err = fn_set_precision();
if(err != std::nullopt) {
return err;
}
} else if(val == "K") { // GET PRECISION
err = fn_get_precision();
if(err != std::nullopt) {
return err;
}
} else if(val == "o") { // SET OUTPUT BASE
} else if(val == "O") { // GET OUTPUT BASE
} else if(val == "i") { // SET INPUT BASE
} else if(val == "I") { // GET INPUT BASE
} else if(val == "x") { // EXECUTE MACRO
auto macro = std::make_unique<Macro>(OPType::EX, this->regs);
auto macro = std::make_unique<Macro>(OPType::EX, this->regs, this->parameters);
err = macro->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(val == "?") { // READ LINE FROM STDIN
auto macro = std::make_unique<Macro>(OPType::RI, this->regs);
auto macro = std::make_unique<Macro>(OPType::RI, this->regs, this->parameters);
err = macro->exec(this->stack);
if(err != std::nullopt) {
return err;
@ -308,37 +316,37 @@ std::optional<std::string> Evaluate::parse_macro_command(std::string val) {
// execute register's content as a macro
std::optional<std::string> err = std::nullopt;
if(operation == ">") {
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::GT, dc_register, this->regs);
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::GT, dc_register, this->regs, this->parameters);
err = macro->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(operation == "<") {
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::LT, dc_register, this->regs);
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::LT, dc_register, this->regs, this->parameters);
err = macro->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(operation == "=") {
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::EQ, dc_register, this->regs);
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::EQ, dc_register, this->regs, this->parameters);
err = macro->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(operation == ">=") {
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::GEQ, dc_register, this->regs);
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::GEQ, dc_register, this->regs, this->parameters);
err = macro->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(operation == "<=") {
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::LEQ, dc_register, this->regs);
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::LEQ, dc_register, this->regs, this->parameters);
err = macro->exec(this->stack);
if(err != std::nullopt) {
return err;
}
} else if(operation == "!=") {
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::NEQ, dc_register, this->regs);
auto macro = std::make_unique<Macro>(OPType::CMP, Operator::NEQ, dc_register, this->regs, this->parameters);
err = macro->exec(this->stack);
if(err != std::nullopt) {
return err;
@ -528,3 +536,46 @@ std::optional<std::string> Evaluate::parse_array_command(std::string val) {
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_set_precision() {
// Check if stack has enough elements
if(this->stack.empty()) {
return "'k' requires one operand";
}
// Pop the head of the stack
auto head = std::stol(this->stack.back());
this->stack.pop_back();
// Check if precision is non-negative
if(head < 0) {
return "Precision must be >=0";
}
// Set precision parameter
this->parameters.precision = head;
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_get_precision() {
this->stack.push_back(std::to_string(this->parameters.precision));
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_set_oradix() {
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_get_oradix() {
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_set_iradix() {
return std::nullopt;
}
std::optional<std::string> Evaluate::fn_get_iradix() {
return std::nullopt;
}

View File

@ -8,10 +8,11 @@
class Evaluate {
public:
Evaluate(const std::vector<std::string> e, std::unordered_map<char, Register> &r, dc_stack_t &s)
: expr(std::move(e)), regs(r), stack(s) {}
Evaluate(std::unordered_map<char, Register> &r, dc_stack_t &s)
: regs(r), stack(s) {}
Evaluate(const std::vector<std::string> e, std::unordered_map<char,
Register> &r, dc_stack_t &s, Parameters &p)
: expr(std::move(e)), regs(r), stack(s), parameters(p) {}
Evaluate(std::unordered_map<char, Register> &r, dc_stack_t &s, Parameters &p)
: regs(r), stack(s), parameters(p) {}
std::optional<std::string> eval();
private:
@ -20,8 +21,15 @@ private:
std::optional<std::string> parse_macro_command(std::string val);
std::optional<std::string> parse_register_command(std::string val);
std::optional<std::string> parse_array_command(std::string val);
std::optional<std::string> fn_set_precision();
std::optional<std::string> fn_get_precision();
std::optional<std::string> fn_set_oradix();
std::optional<std::string> fn_get_oradix();
std::optional<std::string> fn_set_iradix();
std::optional<std::string> fn_get_iradix();
std::vector<std::string> expr;
std::unordered_map<char, Register> &regs;
dc_stack_t &stack;
Parameters &parameters;
};

View File

@ -32,7 +32,7 @@ std::optional<std::string> Macro::fn_execute(dc_stack_t &stack) {
if(!is_num<double>(head)) {
stack.pop_back();
std::vector<std::string> tokens = split(head);
Evaluate evaluator(tokens, this->regs, stack);
Evaluate evaluator(tokens, this->regs, stack, this->parameters);
auto err = evaluator.eval();
if(err != std::nullopt) {
@ -70,7 +70,7 @@ std::optional<std::string> Macro::fn_evaluate_macro(dc_stack_t &stack) {
case Operator::GT: {
if(head > second) {
std::vector<std::string> tokens = split(dc_macro);
Evaluate evaluator(tokens, this->regs, stack);
Evaluate evaluator(tokens, this->regs, stack, this->parameters);
auto err = evaluator.eval();
if(err != std::nullopt) {
@ -82,7 +82,7 @@ std::optional<std::string> Macro::fn_evaluate_macro(dc_stack_t &stack) {
case Operator::LT: {
if(head < second) {
std::vector<std::string> tokens = split(dc_macro);
Evaluate evaluator(tokens, this->regs, stack);
Evaluate evaluator(tokens, this->regs, stack, this->parameters);
auto err = evaluator.eval();
if(err != std::nullopt) {
@ -94,7 +94,7 @@ std::optional<std::string> Macro::fn_evaluate_macro(dc_stack_t &stack) {
case Operator::EQ: {
if(head == second) {
std::vector<std::string> tokens = split(dc_macro);
Evaluate evaluator(tokens, this->regs, stack);
Evaluate evaluator(tokens, this->regs, stack, this->parameters);
auto err = evaluator.eval();
if(err != std::nullopt) {
@ -106,7 +106,7 @@ std::optional<std::string> Macro::fn_evaluate_macro(dc_stack_t &stack) {
case Operator::GEQ: {
if(head >= second) {
std::vector<std::string> tokens = split(dc_macro);
Evaluate evaluator(tokens, this->regs, stack);
Evaluate evaluator(tokens, this->regs, stack, this->parameters);
auto err = evaluator.eval();
if(err != std::nullopt) {
@ -118,7 +118,7 @@ std::optional<std::string> Macro::fn_evaluate_macro(dc_stack_t &stack) {
case Operator::LEQ: {
if(head <= second) {
std::vector<std::string> tokens = split(dc_macro);
Evaluate evaluator(tokens, this->regs, stack);
Evaluate evaluator(tokens, this->regs, stack, this->parameters);
auto err = evaluator.eval();
if(err != std::nullopt) {
@ -130,7 +130,7 @@ std::optional<std::string> Macro::fn_evaluate_macro(dc_stack_t &stack) {
case Operator::NEQ: {
if(head != second) {
std::vector<std::string> tokens = split(dc_macro);
Evaluate evaluator(tokens, this->regs, stack);
Evaluate evaluator(tokens, this->regs, stack, this->parameters);
auto err = evaluator.eval();
if(err != std::nullopt) {
@ -156,7 +156,7 @@ std::optional<std::string> Macro::fn_read_input(dc_stack_t &stack) {
// Push the input onto the main stack and execute it as a macro
stack.push_back(user_input);
Evaluate evaluator(this->regs, stack);
Evaluate evaluator(this->regs, stack, this->parameters);
auto err = evaluator.eval();
if(err != std::nullopt) {

View File

@ -8,10 +8,12 @@ enum class Operator {
class Macro : public IOperation {
public:
Macro(const OPType op_t, const Operator o, const char dc_r, std::unordered_map<char, Register> &r)
: op_type(std::move(op_t)), op(std::move(o)), dc_register(std::move(dc_r)), regs(r) {}
Macro(const OPType op_t, std::unordered_map<char, Register> &r)
: op_type(std::move(op_t)), regs(r) {}
Macro(const OPType op_t, const Operator o,
const char dc_r, std::unordered_map<char, Register> &r, Parameters &p)
: op_type(std::move(op_t)), op(std::move(o)),
dc_register(std::move(dc_r)), regs(r), parameters(p) {}
Macro(const OPType op_t, std::unordered_map<char, Register> &r, Parameters &p)
: op_type(std::move(op_t)), regs(r), parameters(p) {}
std::optional<std::string> exec(dc_stack_t &stack) override;
static std::vector<std::string> split(std::string str);
@ -24,4 +26,5 @@ private:
Operator op;
char dc_register;
std::unordered_map<char, Register> &regs;
Parameters parameters;
};

View File

@ -180,33 +180,3 @@ std::optional<std::string> Stack::fn_stack_size(dc_stack_t &stack) {
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_precision(dc_stack_t &stack) {
(void)stack;
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_precision(dc_stack_t &stack) {
(void)stack;
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_oradix(dc_stack_t &stack) {
(void)stack;
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_oradix(dc_stack_t &stack) {
(void)stack;
return std::nullopt;
}
std::optional<std::string> Stack::fn_set_iradix(dc_stack_t &stack) {
(void)stack;
return std::nullopt;
}
std::optional<std::string> Stack::fn_get_iradix(dc_stack_t &stack) {
(void)stack;
return std::nullopt;
}

View File

@ -20,12 +20,6 @@ private:
std::optional<std::string> fn_print_stack(dc_stack_t &stack);
std::optional<std::string> fn_head_size(dc_stack_t &stack);
std::optional<std::string> fn_stack_size(dc_stack_t &stack);
std::optional<std::string> fn_set_precision(dc_stack_t &stack);
std::optional<std::string> fn_get_precision(dc_stack_t &stack);
std::optional<std::string> fn_set_oradix(dc_stack_t &stack);
std::optional<std::string> fn_get_oradix(dc_stack_t &stack);
std::optional<std::string> fn_set_iradix(dc_stack_t &stack);
std::optional<std::string> fn_get_iradix(dc_stack_t &stack);
OPType op_type;
};

View File

@ -8,3 +8,10 @@ typedef struct {
dc_stack_t stack;
std::unordered_map<int, std::string> array;
} Register;
enum class radix_base { DEC = 10, BIN = 2, OCT = 8, HEX = 16 };
typedef struct {
unsigned int precision;
unsigned short iradix;
radix_base oradix;
} Parameters;