[gnome-calculator] Fix precedences & related bugs.
- From: Arth Patel <arthpatel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calculator] Fix precedences & related bugs.
- Date: Sat, 3 Aug 2013 04:55:35 +0000 (UTC)
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]