From c47a9298fe30c365be65c218c22ca0136b204142 Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Thu, 29 Dec 2022 21:08:37 +0100 Subject: [PATCH] new operator modulo and fix operator priority for simple addition --- calc.c | 3 +++ parser.c | 58 ++++++++++++++++++++++++++++++++++++-------------------- parser.h | 4 ++-- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/calc.c b/calc.c index 945bddd..a26d775 100644 --- a/calc.c +++ b/calc.c @@ -135,6 +135,8 @@ int main (int argc, char *argv[]) // test: echo "1 - 2" | calc.exe | grep -q '=> -1' // test: echo "2 * 3" | calc.exe | grep -q '=> 6' // test: echo "1 / 2" | calc.exe | grep -q '=> 5e-1' +// test: echo "8 % 3" | calc.exe | grep -q '=> 2' +// test: echo "-9 % 3.1" | calc.exe | grep -q '=> -2.8' // test: echo "2 ^ 3" | calc.exe | grep -q '=> 8' // test: echo "1e-1 + 2.34e3" | calc.exe | grep -q '=> 2.3401' // test: echo "sqrt (2)" | calc.exe | grep -q '=> 1.414213' @@ -159,5 +161,6 @@ int main (int argc, char *argv[]) // test: echo "2 ^ 3 * 4 + 5" | calc.exe | grep -q '=> 3.7e1' // test: echo "2 + 3 * 4 ^ 5" | calc.exe | grep -q '=> 3.074e3' // test: echo "2 ^ 3 * 4 + cos(5/6)" | calc.exe | grep -q '=> 3.267241e1' +// test: echo "95-6.3*15" | calc.exe | grep -q '=> 4.999971e-1' /* vim: set ts=4 sw=4 et: */ diff --git a/parser.c b/parser.c index 0244307..75cc294 100644 --- a/parser.c +++ b/parser.c @@ -47,25 +47,26 @@ element_t *newelement (func_t function, int nbops, int prio) /* functions */ -#define NB_OPERATORS 5 +#define NB_OPERATORS 6 keyword_t operators[NB_OPERATORS] = { { "+\t", Add, 2, 1, 1}, { "-\t", Sub, 2, 1, 1}, { "*", Mul, 2, 1, 2}, { "/", Div, 2, 1, 2}, - { "^", Pow, 2, 1, 3} + { "%", Mod, 2, 1, 3}, + { "^", Pow, 2, 1, 4} }; #define NB_FUNCTIONS 7 keyword_t functions[NB_FUNCTIONS] = { - { "sqrt", Sqr, 1, 4, 4}, - { "pow", Pow, 2, 3, 4}, - { "cos", Cos, 1, 3, 4}, - { "sin", Sin, 1, 3, 4}, - { "atan", Atn, 1, 4, 4}, - { "exp", Exp, 1, 3, 4}, - { "log", Log, 1, 3, 4} + { "sqrt", Sqr, 1, 4, 5}, + { "pow", Pow, 2, 3, 5}, + { "cos", Cos, 1, 3, 5}, + { "sin", Sin, 1, 3, 5}, + { "atan", Atn, 1, 4, 5}, + { "exp", Exp, 1, 3, 5}, + { "log", Log, 1, 3, 5} }; /* parser function */ @@ -145,7 +146,7 @@ element_t *parser (char *str, char **next, int prio) VERBOSE (DEBUG, PRINTOUT ("start processing operator\n")); if (root) { if ((prio) && (prio > operator->prio)) { - VERBOSE (DEBUG, PRINTOUT ("stop processing operator because operator priority\n")); + VERBOSE (DEBUG, PRINTOUT ("stop because operator priority\n")); *next = str; return root; } @@ -212,29 +213,41 @@ element_t *parser (char *str, char **next, int prio) float value = strtof (str, &pt); VERBOSE (INFO, PRINTOUT ("Value: %f\n", value)); if (str != pt) { - new = newelement (Val, 1, 4); - if (new == NULL) { - return ERROR_OP; - } - new->value = value; if (root == NULL) { + new = newelement (Val, 1, 4); + if (new == NULL) { + return ERROR_OP; + } + new->value = value; root = new; + str = pt; } else if (root->func == Val) { if ((*str == '+') || (*str == '-')) { - element_t *add = newelement (Add, 2, 1); - if (add == NULL) { + if ((prio) && (prio > 1)) { + VERBOSE (DEBUG, PRINTOUT ("stop because operator priority\n")); + *next = str; + return root; + } + new = newelement (Add, 2, 1); + if (new == NULL) { + return ERROR_OP; + } + new->ops[0] = root; + new->ops[1] = parser (str, &str, new->prio); + if (new->ops[1] == ERROR_OP) { + return ERROR_OP; + } + root = newelement (Val, 1, 4); + if (root == ERROR_OP) { return ERROR_OP; } - add->ops[0] = root; - add->ops[1] = new; - root = add; + root->ops[0] = new; } else { return ERROR_OP; } } else { return ERROR_OP; } - str = pt; found = 1; } VERBOSE (DEBUG, PRINTOUT ("stop processing value\n")); @@ -275,6 +288,7 @@ void print_element (element_t *root, int level) case Sub: func = "Subtraction"; break; case Mul: func = "Multiplication"; break; case Div: func = "Division"; break; + case Mod: func = "Modulo"; break; case Pow: func = "Power"; break; case Sqr: func = "Square Root"; break; case Cos: func = "Cosine"; break; @@ -321,6 +335,7 @@ double evaluate_element (element_t *root) case Sub: case Mul: case Div: + case Mod: case Pow: if (root->ops[1]) { op1 = evaluate_element (root->ops[1]); @@ -348,6 +363,7 @@ double evaluate_element (element_t *root) case Sub: return op0 - op1; case Mul: return op0 * op1; case Div: return op0 / op1; + case Mod: return fmod (op0, op1); case Pow: return pow (op0, op1); case Sqr: return sqrt (op0); case Cos: return cos (op0); diff --git a/parser.h b/parser.h index ed17452..8038a9d 100644 --- a/parser.h +++ b/parser.h @@ -6,8 +6,8 @@ typedef enum { Val = 0, Add, Sub, - Mul, Div, Pow, - Sqr, + Mul, Div, Mod, + Pow, Sqr, Cos, Sin, Atn, Log, Exp } func_t; -- 2.30.2