From: Laurent Mazet Date: Fri, 30 Dec 2022 16:40:58 +0000 (+0100) Subject: correct manage cascade minus and divide X-Git-Tag: v0.8~57 X-Git-Url: https://secure.softndesign.org/git/?a=commitdiff_plain;h=3b4b0bbecb130cc76d4cd16d00518f70d11f0820;p=calc.git correct manage cascade minus and divide --- diff --git a/calc.c b/calc.c index e8c8e5a..a571374 100644 --- a/calc.c +++ b/calc.c @@ -104,7 +104,7 @@ int main (int argc, char *argv[]) ret = 1; } else { VERBOSE (INFO, print_element (element, 0)); - PRINTOUT ("=> %f\n", evaluate_element (element)); + PRINTOUT ("=> %f\n", evaluate_element (element, 0)); ret = 0; } //fsync (stdfdout); @@ -163,6 +163,8 @@ int main (int argc, char *argv[]) // 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-1" | calc.exe | grep -q '=> -5.000028e-1' +// test: echo "95 - 6.3 * 15 - 1" | calc.exe | grep -q '=> -5.000028e-1' // test: echo "95-6.3+15" | calc.exe | grep -q '=> 1.037e2' +// test: echo "-cos (0) + 1" | calc.exe | grep -q '=> 0' /* vim: set ts=4 sw=4 et: */ diff --git a/parser.c b/parser.c index fdabef2..13efac3 100644 --- a/parser.c +++ b/parser.c @@ -82,7 +82,7 @@ element_t *subparser (element_t **proot, char **pstr, func_t func, int nbops, in if (new->ops[1] == ERROR_OP) { return ERROR_OP; } - *proot = newelement (Val, 1, 4); + *proot = newelement (Val, 1, 5); if (*proot == ERROR_OP) { return ERROR_OP; } @@ -136,7 +136,7 @@ element_t *parser (char *str, char **next, int prio) } } while (*str == ','); } else { - root = newelement (Val, 1, 4); + root = newelement (Val, 1, 5); if (root == NULL) { return ERROR_OP; } @@ -177,6 +177,12 @@ element_t *parser (char *str, char **next, int prio) if (subparser (&root, &str, operator->func, operator->nbops, operator->prio) == ERROR_OP) { return ERROR_OP; } + } else if (*str == '-') { + new = newelement (Sig, 1, 9); + if (new == NULL) { + return ERROR_OP; + } + root = new; } else { return ERROR_OP; } @@ -225,7 +231,7 @@ element_t *parser (char *str, char **next, int prio) VERBOSE (INFO, PRINTOUT ("Value: %f\n", value)); if (str != pt) { if (root == NULL) { - new = newelement (Val, 1, 4); + new = newelement (Val, 1, 5); if (new == NULL) { return ERROR_OP; } @@ -296,6 +302,7 @@ void print_element (element_t *root, int level) case Atn: func = "Arc Tangent"; break; case Log: func = "Logarithm"; break; case Exp: func = "Exponantial"; break; + case Sig: func = "Sign"; break; } PRINTOUT ("Function: %s\n", func); @@ -312,24 +319,45 @@ void print_element (element_t *root, int level) } } +#define MASK_SUB 0x1 +#define MASK_DIV 0x2 + /* evaluate element tree */ -double evaluate_element (element_t *root) +double evaluate_element (element_t *root, char mask) { double op0 = 0, op1 = 0; + char nextmask = mask; if ((root == NULL) || (root == ERROR_OP)) { VERBOSE (WARNING, PRINTOUT ("error while evaluating\n")); return 0; } + /* mask to manage sub operator sub and div */ + switch (root->func) { + case Add: + nextmask &= ~MASK_SUB; + nextmask &= ~MASK_DIV; + break; + case Sub: + nextmask |= MASK_SUB; + nextmask &= ~MASK_DIV; + break; + case Mul: + nextmask &= ~MASK_DIV; + break; + case Div: + nextmask |= MASK_DIV; + break; + default: + nextmask = mask; + } + switch (root->func) { case Val: - if (root->ops[0]) { - return evaluate_element (root->ops[0]); - } else { - return root->value; - } + case Sig: + op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value; break; case Add: case Sub: @@ -338,7 +366,7 @@ double evaluate_element (element_t *root) case Mod: case Pow: if (root->ops[1]) { - op1 = evaluate_element (root->ops[1]); + op1 = evaluate_element (root->ops[1], nextmask); } else { VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[1])\n")); return 0; @@ -351,7 +379,7 @@ double evaluate_element (element_t *root) case Log: case Exp: if (root->ops[0]) { - op0 = evaluate_element (root->ops[0]); + op0 = evaluate_element (root->ops[0], 0); } else { VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[0])\n")); return 0; @@ -359,10 +387,12 @@ double evaluate_element (element_t *root) } switch (root->func) { - case Add: return op0 + op1; - case Sub: return op0 - op1; - case Mul: return op0 * op1; - case Div: return op0 / op1; + case Val: return op0; + case Sig: return -op0; + case Add: return ((mask & MASK_SUB) == 0) ? op0 + op1 : op0 - op1; + case Sub: return ((mask & MASK_SUB) == 0) ? op0 - op1 : op0 + op1; + case Mul: return ((mask & MASK_DIV) == 0) ? op0 * op1 : op0 / op1; + case Div: return ((mask & MASK_DIV) == 0) ? op0 / op1 : op0 * op1; case Mod: return fmod (op0, op1); case Pow: return pow (op0, op1); case Sqr: return sqrt (op0); @@ -371,7 +401,6 @@ double evaluate_element (element_t *root) case Atn: return atan (op0); case Log: return log (op0); case Exp: return exp (op0); - default: break; } return 0; diff --git a/parser.h b/parser.h index 8038a9d..c746aaf 100644 --- a/parser.h +++ b/parser.h @@ -9,7 +9,8 @@ typedef enum { Mul, Div, Mod, Pow, Sqr, Cos, Sin, Atn, - Log, Exp + Log, Exp, + Sig } func_t; /* keyword type */ @@ -41,7 +42,7 @@ element_t *parser (char *str, char **next, int prio); void print_element (element_t *root, int level); -double evaluate_element (element_t *root); +double evaluate_element (element_t *root, char mask); #endif /* __PARSER_H__ */