evaluation function
authorLaurent Mazet <mazet@softndesign.org>
Thu, 29 Dec 2022 09:37:30 +0000 (10:37 +0100)
committerLaurent Mazet <mazet@softndesign.org>
Thu, 29 Dec 2022 09:37:30 +0000 (10:37 +0100)
calc.c
parser.c
parser.h

diff --git a/calc.c b/calc.c
index b83bbd6af9f91ab16a971a6cb0339305e1de0950..945bdddbc250e0089c04e6534099b9326c363243 100644 (file)
--- a/calc.c
+++ b/calc.c
@@ -1,6 +1,6 @@
 /* depend: */
 /* cflags: */
-/* linker: atoi.o debug.o fdprintf.o parser.o */
+/* linker: atoi.o debug.o fdprintf.o parser.o -lm */
 
 //#include <malloc.h>
 #include <stddef.h>
@@ -103,7 +103,8 @@ int main (int argc, char *argv[])
                     VERBOSE (WARNING, PRINTOUT ("error while parsing: %s\n", buffer));
                     ret = 1;
                } else {
-                    print_element (element, 0);
+                    VERBOSE (INFO, print_element (element, 0));
+                    PRINTOUT ("=> %f\n", evaluate_element (element));
                     ret = 0;
                 }
                 //fsync (stdfdout);
@@ -130,33 +131,33 @@ int main (int argc, char *argv[])
 // test: calc.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
 // test: calc.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }'
 // test: calc.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
-// test: echo "1 + 2" | calc.exe
-// test: echo "1 - 2" | calc.exe
-// test: echo "1 * 2" | calc.exe
-// test: echo "1 / 2" | calc.exe
-// test: echo "2 ^ 3" | calc.exe
-// test: echo "1e-1 + 2.34e5" | calc.exe
-// test: echo "sqrt (2)" | calc.exe
-// test: echo "pow (2, 3)" | calc.exe
-// test: echo "cos (2)" | calc.exe
-// test: echo "sin (2)" | calc.exe
-// test: echo "atan (2)" | calc.exe
-// test: echo "exp (2)" | calc.exe
-// test: echo "log (2)" | calc.exe
-// test: echo "1 + 2 - 3" | calc.exe
-// test: echo "1 + cos (2 - 3)" | calc.exe
-// test: echo "cos (1 / 2) * 3" | calc.exe
-// test: echo "1 + 4 * (2 - 3)" | calc.exe
-// test: echo "(2 - 3) / 4" | calc.exe
-// test: echo "pow (2 - 3, 8 / 3)" | calc.exe
-// test: echo "1 + -2" | calc.exe
-// test: echo "1 - +2" | calc.exe
-// test: echo "-1 + +2" | calc.exe
-// test: echo "-1+2" | calc.exe
-// test: echo "1-2" | calc.exe
-// test: echo "1 * 2 / 3 + 4" | calc.exe
-// test: echo "2 ^ 3 * 4 + 5" | calc.exe
-// test: echo "2 + 3 * 4 ^ 5" | calc.exe
-// test: echo "2 ^ 3 * 4 + cos(5/6)" | calc.exe
+// test: echo "1 + 2" | calc.exe | grep -q '=> 3'
+// 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 "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'
+// test: echo "pow (2, 3)" | calc.exe | grep -q '=> 8'
+// test: echo "cos (2)" | calc.exe | grep -q '=> -4.161468e-1'
+// test: echo "sin (2)" | calc.exe | grep -q '=> 9.092974e-1'
+// test: echo "atan (2)" | calc.exe | grep -q '=> 1.107148'
+// test: echo "exp (2)" | calc.exe | grep -q '=> 7.389056'
+// test: echo "log (2)" | calc.exe | grep -q '=> 6.931471e-1'
+// test: echo "2 + 3 - 4" | calc.exe | grep -q '=> 1'
+// test: echo "1 + cos (2 - 3)" | calc.exe | grep -q '=> 1.54030'
+// test: echo "cos (1 / 2) * 3" | calc.exe | grep -q '=> 2.63274'
+// test: echo "1 + 4 * (2 - 3)" | calc.exe | grep -q '=> -3'
+// test: echo "(2 - 3) / 4" | calc.exe | grep -q '=> -2.5e-1'
+// test: echo "pow (8 - 3, 4 / 3)" | calc.exe | grep -q '=> 8.549879'
+// test: echo "1 + -2" | calc.exe | grep -q '=> -1'
+// test: echo "1 - +2" | calc.exe | grep -q '=> -1'
+// test: echo "-1 + +2" | calc.exe | grep -q '=> 1'
+// test: echo "-1+2" | calc.exe | grep -q '=> 1'
+// test: echo "1-2" | calc.exe | grep -q '=> -1'
+// test: echo "1 * 2 / 3 + 4" | calc.exe | grep -q '=> 4.666666'
+// 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'
 
 /* vim: set ts=4 sw=4 et: */
index 0caa750c65020c7f490c3da51ed64b7a82e8a0b5..02443079228e3385b361b5e2f027152ad48f18ad 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1,4 +1,5 @@
 #include <malloc.h>
+#include <math.h>
 #include <stdlib.h>
 
 #include "debug.h"
@@ -270,7 +271,6 @@ void print_element (element_t *root, int level)
 
     switch (root->func) {
     case Val: func = "Value"; break;
-    case Set: func = "Set"; break;
     case Add: func = "Addition"; break;
     case Sub: func = "Subtraction"; break;
     case Mul: func = "Multiplication"; break;
@@ -298,4 +298,67 @@ void print_element (element_t *root, int level)
     }
 }
 
+/* evaluate element tree */
+
+double evaluate_element (element_t *root)
+{
+    double op0 = 0, op1 = 0;
+
+    if ((root == NULL) || (root == ERROR_OP)) {
+        VERBOSE (WARNING, PRINTOUT ("error while evaluating\n"));
+        return 0;
+    }
+
+    switch (root->func) {
+    case Val:
+        if (root->ops[0]) {
+            return evaluate_element (root->ops[0]);
+        } else {
+            return root->value;
+        }
+        break;
+    case Add:
+    case Sub:
+    case Mul:
+    case Div:
+    case Pow:
+        if (root->ops[1]) {
+            op1 = evaluate_element (root->ops[1]);
+        } else {
+            VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[1])\n"));
+            return 0;
+        }
+        /* fallthrough */
+    case Sqr:
+    case Cos:
+    case Sin:
+    case Atn:
+    case Log:
+    case Exp:
+        if (root->ops[0]) {
+            op0 = evaluate_element (root->ops[0]);
+        } else {
+            VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[0])\n"));
+            return 0;
+        }
+    }
+
+    switch (root->func) {
+    case Add: return op0 + op1;
+    case Sub: return op0 - op1;
+    case Mul: return op0 * op1;
+    case Div: return op0 / op1;
+    case Pow: return pow (op0, op1);
+    case Sqr: return sqrt (op0);
+    case Cos: return cos (op0);
+    case Sin: return sin (op0);
+    case Atn: return atan (op0);
+    case Log: return log (op0);
+    case Exp: return exp (op0);
+    default: break;
+    }
+
+    return 0;
+}
+
 /* vim: set ts=4 sw=4 et: */
index 767fcf08bdc848c6005157f22368744e5b9e7ea7..ed17452867d4a1014d943f066b2cf685c8408176 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -4,7 +4,7 @@
 /* function type */
 
 typedef enum {
-    Val = 0, Set,
+    Val = 0,
     Add, Sub,
     Mul, Div, Pow,
     Sqr,
@@ -41,6 +41,8 @@ element_t *parser (char *str, char **next, int prio);
 
 void print_element (element_t *root, int level);
 
+double evaluate_element (element_t *root);
+
 #endif /* __PARSER_H__ */
 
 /* vim: set ts=4 sw=4 et: */