[gnome-calculator] Fix precedences & related bugs.



commit 917fafcb062412c66230bde4cfed5437ba0da235
Author: PioneerAxon <arth svnit gmail com>
Date:   Sat Aug 3 10:16:52 2013 +0530

    Fix precedences & related bugs.
    
    Fix the precedence of Divide, Mod and function parameters.
    Add precedence test cases.

 src/equation-parser.vala |   70 +++++++++++++++++++++++++++++++++++++--------
 src/test-equation.vala   |   41 +++++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 13 deletions(-)
---
diff --git a/src/equation-parser.vala b/src/equation-parser.vala
index 3df6c9a..fcb7910 100644
--- a/src/equation-parser.vala
+++ b/src/equation-parser.vala
@@ -22,18 +22,19 @@ private enum Precedence
     UNKNOWN         = 0,
     ADD_SUBTRACT    = 1,
     MULTIPLY        = 2,
+    /* MOD and DIVIDE must have same preedence. */
     MOD             = 3,
-    DIVIDE          = 4,
-    NOT             = 5,
-    ROOT            = 6,
-    FUNCTION        = 7,
-    BOOLEAN         = 8,
-    PERCENTAGE      = 9,
+    DIVIDE          = 3,
+    NOT             = 4,
+    ROOT            = 5,
+    FUNCTION        = 6,
+    BOOLEAN         = 7,
+    PERCENTAGE      = 8,
     /* UNARY_MINUS and POWER must have same precedence. */
-    UNARY_MINUS     = 10,
-    POWER           = 10,
-    FACTORIAL       = 11,
-    NUMBER_VARIABLE = 12,
+    UNARY_MINUS     = 9,
+    POWER           = 9,
+    FACTORIAL       = 10,
+    NUMBER_VARIABLE = 11,
     /* DEPTH should be always at the bottom. It stops node jumping off the current depth level. */
     DEPTH
 }
@@ -1709,6 +1710,7 @@ public class Parser
         var token = lexer.get_next_token ();
         if (token.type == LexerTokenType.FUNCTION)
         {
+            depth_level++;
             var token_old = token;
             token = lexer.get_next_token ();
             if (token.type == LexerTokenType.SUP_NUMBER)
@@ -1716,7 +1718,21 @@ public class Parser
                 /* Pass power as void * value. That will be taken care in pf_apply_func_with_power. */
 
                 insert_into_tree_unary (new FunctionWithPowerNode (this, token_old, make_precedence_t 
(token_old.type), get_associativity (token_old), token.text));
-                if (!expression ())
+                if (!expression_1 ())
+                {
+                    depth_level--;
+                    return false;
+                }
+
+                token = lexer.get_next_token ();
+                if (token.type == LexerTokenType.FACTORIAL)
+                    insert_into_tree_unary (new FactorialNode (this, token, make_precedence_t (token.type), 
get_associativity (token)));
+                else
+                    lexer.roll_back ();
+
+                depth_level--;
+
+                if (!expression_2 ())
                     return false;
 
                 return true;
@@ -1726,7 +1742,21 @@ public class Parser
                 /* Pass power as void * value. That will be taken care in pf_apply_func_with_npower. */
 
                 insert_into_tree_unary (new FunctionWithNegativePowerNode (this, token_old, 
make_precedence_t (token_old.type), get_associativity (token_old), token.text));
-                if (!expression ())
+                if (!expression_1 ())
+                {
+                    depth_level--;
+                    return false;
+                }
+
+                token = lexer.get_next_token ();
+                if (token.type == LexerTokenType.FACTORIAL)
+                    insert_into_tree_unary (new FactorialNode (this, token, make_precedence_t (token.type), 
get_associativity (token)));
+                else
+                    lexer.roll_back ();
+
+                depth_level--;
+
+                if (!expression_2 ())
                     return false;
 
                 return true;
@@ -1735,7 +1765,21 @@ public class Parser
             {
                 lexer.roll_back ();
                 insert_into_tree_unary (new FunctionNode (this, token_old, make_precedence_t 
(token_old.type), get_associativity (token_old)));
-                if (!expression ())
+                if (!expression_1 ())
+                {
+                    depth_level--;
+                    return false;
+                }
+
+                token = lexer.get_next_token ();
+                if (token.type == LexerTokenType.FACTORIAL)
+                    insert_into_tree_unary (new FactorialNode (this, token, make_precedence_t (token.type), 
get_associativity (token)));
+                else
+                    lexer.roll_back ();
+
+                depth_level--;
+
+                if (!expression_2 ())
                     return false;
 
                 return true;
diff --git a/src/test-equation.vala b/src/test-equation.vala
index 5c0a782..6e8a933 100644
--- a/src/test-equation.vala
+++ b/src/test-equation.vala
@@ -620,6 +620,46 @@ private void test_base_conversion ()
     test ("x in hex", "2₁₆", 0);
 }
 
+private void test_precedence ()
+{
+    number_base = 10;
+    wordlen = 32;
+    angle_units = AngleUnit.DEGREES;
+    enable_conversions = true;
+    enable_variables = true;
+
+    test ("1 + 2 - 3 * 4 / 5", "0.6", 0);
+    test ("10 mod 4 / 2", "1", 0);
+    test ("20 / 10 mod 3", "2", 0);
+    test ("12 / 3 √4", "8", 0);
+    test ("√5!", "10.95445115", 0);
+    test ("4 ^ sin 30", "2", 0);
+    test ("4 ^ (sin 30)", "2", 0);
+    test ("4 ^ sin (30)", "2", 0);
+    test ("sin (30) ^ 4", "0.0625", 0);
+    test ("sin 30 ^ 4", "0.0625", 0);
+    test ("sin (30 ^ 4)", "0", 0);
+
+    test ("10 / - 2", "−5", 0);
+    test ("10 * - 2", "−20", 0);
+    test ("10 ^ -2", "0.01", 0);
+    test ("-10 ^ 2", "−100", 0);
+    test ("sin (-30)", "−0.5", 0);
+    test ("sin - 30", "−0.5", 0);
+
+    test ("6 + 3!", "12", 0);
+    test ("4 * 3!", "24", 0);
+    test ("100 mod 3!", "4", 0);
+    test ("5! mod 7", "1", 0);
+    test ("24 / 3!", "4", 0);
+    test ("4! / 6", "4", 0);
+    test ("cos 5!", "−0.5", 0);
+    test ("sin 6!", "0", 0);
+    test ("- 4!", "−24", 0);
+    test ("3! ^ 3", "216", 0);
+    test ("3 ^ 3!", "729", 0);
+}
+
 public int main (string[] args)
 {
     Intl.setlocale (LocaleCategory.ALL, "C");
@@ -627,6 +667,7 @@ public int main (string[] args)
     test_conversions ();
     test_equations ();
     test_base_conversion ();
+    test_precedence ();
 
     if (fail_count == 0)
         stdout.printf ("Passed all %i tests\n", pass_count);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]