Added 'Parameters' data type
This commit is contained in:
parent
2c766fd38e
commit
205c77ef8d
11
main.cpp
11
main.cpp
@ -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) {
|
||||
|
67
src/eval.cpp
67
src/eval.cpp
@ -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;
|
||||
}
|
||||
|
16
src/eval.h
16
src/eval.h
@ -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> ®s;
|
||||
dc_stack_t &stack;
|
||||
Parameters ¶meters;
|
||||
};
|
||||
|
@ -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) {
|
||||
|
11
src/macro.h
11
src/macro.h
@ -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> ®s;
|
||||
Parameters parameters;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user