all number supported
[calc.git] / parser.c
index 677f9a4e0a3ea1deee747888ebc74dfffc60db4e..8ddd83ad62e14a80b1f152d00bb11ff7234c723f 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -13,10 +13,16 @@ int codecmp (char *ref, char *str)
     int sig;
 
     while (*ref != '\0') {
-        sig = *str++ - *ref++;
+        if (*ref == '\t') {
+             sig = (*str == '.') ? -1 : ((*str >= '0') && (*str <= '9'));
+        } else {
+            sig = *str - *ref;
+        }
         if (sig != 0) {
             return (sig > 0) ? 1 : -1;
         }
+        str++;
+        ref++;
     }
 
     return 0;
@@ -39,13 +45,11 @@ element_t *newelement (func_t function, int nbops)
 
 /* functions */
 
-#define NB_OPERATORS 7
+#define NB_OPERATORS 5
 
 keyword_t operators[NB_OPERATORS] = {
-    { "+ ",  Add, 2, 1 },
-    { "+\t", Add, 2, 1 },
-    { "- ",  Sub, 2, 1 },
-    { "- ",  Sub, 2, 1 },
+    { "+\t",  Add, 2, 1 },
+    { "-\t", Sub, 2, 1 },
     { "*",   Mul, 2, 1 },
     { "/",   Div, 2, 1 },
     { "^",   Pow, 2, 1 }
@@ -64,15 +68,18 @@ keyword_t functions[NB_FUNCTIONS] = {
 
 /* parser function */
 
-element_t *parser (char *str) {
+element_t *parser (char *str, char **next)
+{
     element_t *root = NULL;
     int i;
 
+    VERBOSE (DEBUG, PRINTOUT ("Starting parsing\n"));
+
     /* main loop */
     while (*str != '\0') {
         int found = 0;
         element_t *new = NULL;
-        VERBOSE (DEBUG, PRINTOUT ("Processing: %s\n", str));
+        VERBOSE (INFO, PRINTOUT ("Processing: %s\n", str));
 
         /* skip spaces and tabs */
 
@@ -81,111 +88,159 @@ element_t *parser (char *str) {
             continue;
         }
 
+        /* check for open bracket */
+
+        if (*str == '(') {
+            VERBOSE (DEBUG, PRINTOUT ("start processing bracket\n"));
+            if (root) {
+                do {
+                    found = 0;
+                    new = parser (str + 1, &str);
+                    if (new == ERROR_OP) {
+                        return ERROR_OP;
+                    }
+                    for (i = 0; i < root->nbops; i++) {
+                        if (root->ops[i] == NULL) {
+                            root->ops[i] = new;
+                            found = 1;
+                            break;
+                        }
+                    }
+                    if (!found) {
+                        return ERROR_OP;
+                    }
+                } while (*str == ',');
+            } else {
+                root = newelement (Val, 1);
+                if (root == NULL) {
+                    return ERROR_OP;
+                }
+                new = parser (str + 1, &str);
+                if ((new == ERROR_OP) || (*str == ',')) {
+                    return ERROR_OP;
+                }
+                root->ops[0] = new;
+            }
+            str++;
+            VERBOSE (DEBUG, PRINTOUT ("stop processing bracket\n"));
+            continue;
+        }
+
+        /* check for closing bracket or koma */
+
+        if ((*str == ')') || (*str == ',')) {
+            if (next != NULL) {
+                *next = str;
+            }
+            return root;
+        }
+
         /* look for operators */
 
         for (i = 0; i < NB_OPERATORS; i++) {
             keyword_t *operator = operators + i;
             if (codecmp (operator->keyword, str) == 0) {
-                if ((root) && (root->func == Val)) {
-                    VERBOSE (DEBUG, PRINTOUT ("Oper: %d\n", operator->func));
+                VERBOSE (DEBUG, PRINTOUT ("start processing operator\n"));
+                str += operator->offset;
+                if ((root) && (root->func != Set)) {
+                    VERBOSE (INFO, PRINTOUT ("Oper: %d\n", operator->func));
                     new = newelement (operator->func, operator->nbops);
                     if (new == NULL) {
-                        return (element_t *)-1;
+                        return ERROR_OP;
                     }
                     new->ops[0] = root;
                     root = new;
-                 } else {
-                    return (element_t *)(-1);
+                    new = parser (str, &str);
+                    if (new == ERROR_OP) {
+                        return ERROR_OP;
+                    }
+                    root->ops[1] = new;
+                } else {
+                    return ERROR_OP;
                 }
-                str += operator->offset;
                 found = 1;
+                VERBOSE (DEBUG, PRINTOUT ("stop processing operator\n"));
                 break;
             }
         }
         if (found) {
-            VERBOSE (DEBUG, PRINTOUT ("stop processing operator\n"));
             continue;
         }
+
         /* look for functions */
 
         for (i = 0; i < NB_FUNCTIONS; i++) {
             keyword_t *function = functions + i;
             if (codecmp (function->keyword, str) == 0) {
+                VERBOSE (DEBUG, PRINTOUT ("start processing function\n"));
                 if (root == NULL) {
-                    VERBOSE (DEBUG, PRINTOUT ("Func: %d\n", function->func));
+                    VERBOSE (INFO, PRINTOUT ("Func: %d\n", function->func));
                     new = newelement (function->func, function->nbops);
                     if (new == NULL) {
-                        return (element_t *)-1;
+                        return ERROR_OP;
                     }
                     root = new;
                  } else {
-                    return (element_t *)(-1);
+                    return ERROR_OP;
                 }
                 str += function->offset;
                 found = 1;
+                VERBOSE (DEBUG, PRINTOUT ("stop processing function\n"));
                 break;
             }
         }
         if (found) {
-            VERBOSE (DEBUG, PRINTOUT ("stop processing function\n"));
             continue;
         }
 
-       /* last attend to detect addition and substraction */
-
-       if (((*str == '-') || (*str == '+')) &&
-           ((*(str + 1) >= '0') && (*(str + 1) <= '9')) &&
-           ((root) && (root->func == Val))) {
-            VERBOSE (DEBUG, PRINTOUT ("Oper: %d\n", Add));
-            new = newelement (Add, 2);
-            if (new == NULL) {
-                return (element_t *)-1;
-            }
-            new->ops[0] = root;
-            root = new;
-       }
-
         /* look for number */
 
         if (((*str >= '0') && (*str <= '9')) ||
-            (*str == '.') || (*str == '-') ||(*str == '+')) {
+            (*str == '.') || (*str == '+') || (*str == '-')) {
+            VERBOSE (DEBUG, PRINTOUT ("start processing value\n"));
             char *pt;
             float value = strtof (str, &pt);
-            VERBOSE (DEBUG, PRINTOUT ("Value: %f\n", value));
+            VERBOSE (INFO, PRINTOUT ("Value: %f\n", value));
             if (str != pt) {
                 new = newelement (Val, 1);
-                new->value = value;
                 if (new == NULL) {
-                    return (element_t *)-1;
+                    return ERROR_OP;
                 }
+                new->value = value;
                 if (root == NULL) {
                     root = new;
-                } else {
-                    for (i = 0; i < root->nbops; i++) {
-                        if (root->ops[i] == NULL) {
-                            root->ops[i] = new;
-                            found = 1;
-                            break;
+                } else if (root->func == Val) {
+                    if ((*str == '+') || (*str == '-')) {
+                        element_t *add = newelement (Add, 2);
+                        if (add == NULL) {
+                            return ERROR_OP;
                         }
+                        add->ops[0] = root;
+                        add->ops[1] = new;
+                        root = add;
+                    } else {
+                        return ERROR_OP;
                     }
-                    if (!found) {
-                        return (element_t *)-1;
-                    }
+                } else {
+                    return ERROR_OP;
                 }
                 str = pt;
                 found = 1;
             }
+            VERBOSE (DEBUG, PRINTOUT ("stop processing value\n"));
         }
 
         /* error */
 
         if (!found) {
-            return (element_t *)-1;
+            return ERROR_OP;
         }
 
     }
 
+    if (next != NULL) {
+        *next = str;
+    }
     return root;
 }
 
@@ -196,15 +251,17 @@ void print_element (element_t *root, int level)
     char *func = NULL;
     int i;
 
-    if (root == NULL)
+    if ((root == NULL) || (root == ERROR_OP)) {
         return;
-    
+    }
+
     for (i = 0; i < level; i++) {
         PRINTOUT (" ");
     }
 
     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;
@@ -220,7 +277,7 @@ void print_element (element_t *root, int level)
 
     PRINTOUT ("Function: %s\n", func);
 
-    if (root->func == Val) {
+    if ((root->func == Val) && (root->ops[0] == NULL)) {
         for (i = 0; i < level; i++) {
             PRINTOUT (" ");
         }