changeset 692:391310cfba26

Fix & precedence vs +.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 16 Apr 2013 17:28:32 +0300
parents e7663dd15eea
children 837ad9dcc348
files dmeval.c tests/testeval.sh
diffstat 2 files changed, 61 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/dmeval.c	Tue Apr 16 17:05:38 2013 +0300
+++ b/dmeval.c	Tue Apr 16 17:28:32 2013 +0300
@@ -883,24 +883,59 @@
                 node = NULL;
                 break;
 
-            case OP_ADD:
-            case OP_SUB:
             
-            case OP_AND:
-            case OP_XOR:
-            case OP_OR:
-
-            case OP_VAR:
-            case OP_CONST:
+            default:
                 if (dm_eval_push_node(&list, node) == NULL)
                     return -32;
 
                 node = node->next;
                 break;
+        }
+        else
+        if (pass == 2)
+        switch (node->op)
+        {
+            case OP_ADD:
+                // Pop previous node, f.e. 5*3 -> 5
+                if ((tmp = dm_eval_pop_node(&list)) == NULL)
+                    return -24;
+
+                // Add subexpression node
+                if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
+                    return -3;
+
+                // Add popped node into subexpression
+                dm_eval_push_node(&(sub->subexpr), tmp);
+                
+                // Add this operator into subexpression
+                dm_eval_add_node(&(sub->subexpr), node->op);
+
+                // Next node
+                node = node->next;
+                if (node == NULL)
+                    return -72;
+
+                if (node->op == OP_FUNC || node->op == OP_SUBEXPR)
+                {
+                    // It's a function or sub-expression
+                    if ((tmp = dm_eval_push_node(&(sub->subexpr), node)) == NULL)
+                        return -178;
+                    
+                    if ((res = dm_eval_reorder_do(ev, node->subexpr, &(tmp->subexpr), pass)) != 0)
+                        return res;
+                }
+                else
+                    dm_eval_push_node(&(sub->subexpr), node);
+
+                node = node->next;
+                break;
 
             default:
-                dm_eval_err(ev, "Invalid opcode %d in node %p.\n", node->op, node);
-                return -4;
+                if (dm_eval_push_node(&list, node) == NULL)
+                    return -32;
+
+                node = node->next;
+                break;
         }
     }
 
@@ -911,13 +946,16 @@
 
 int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
 {
-    DMEvalNode *tmp = NULL;
+    DMEvalNode *tmp = NULL, *tmp2 = NULL;
     int res;
     
     if ((res = dm_eval_reorder_do(ev, node, &tmp, 0)) != 0)
         return res;
 
-    return dm_eval_reorder_do(ev, tmp, result, 1);
+    if ((res = dm_eval_reorder_do(ev, tmp, &tmp2, 1)) != 0)
+        return res;
+
+    return dm_eval_reorder_do(ev, tmp2, result, 2);
 }
 
 
--- a/tests/testeval.sh	Tue Apr 16 17:05:38 2013 +0300
+++ b/tests/testeval.sh	Tue Apr 16 17:28:32 2013 +0300
@@ -16,6 +16,11 @@
 3 * -1 + 5 << 1
 7 + 3 << 2 * 3
 7 * 3 << 4 - 3
+127&127 + 12&3
+1+3*5&7
+35&3 + 2
+9+5&(3 + 7)
+(5*(7&3) + 1)
 " | while read f; do
   if test "x$f" != "x"; then
      printf "#include <stdio.h>\nint main(int argc, char *argv[])\n{\n  (void) argc; (void) argv;\n  printf(\"%%1.5f\\\\n\", (double) (%s));\n  return 0;\n}\n" "$f" > "$CTEST.c"
@@ -28,6 +33,12 @@
          echo "RESULT MISMATCH: '$f'"
          echo " C test: $RES1"
          echo "   eval: $RES2"
+         cat "$CTEST.c"
+       elif test "x$1" != "x"; then
+         echo "---------------------------------------------"
+         echo "FORMULA: '$f'"
+         echo " C test: $RES1"
+         echo "   eval: $RES2"
        fi
      fi
   fi