Parcourir la source

Fixed float overflow error in grammar and changed '**' -> '^'.

Sander Mathijs van Veen il y a 14 ans
Parent
commit
1bf9107444
2 fichiers modifiés avec 58 ajouts et 14 suppressions
  1. 27 14
      src/calc.py
  2. 31 0
      tests/test_calc.py

+ 27 - 14
src/calc.py

@@ -106,22 +106,35 @@ class Parser(BisonParser):
             print 'on_exp: got %s %s %s %s' % (target, option, names, values)
 
         if option == 0:
+            # TODO: A bit hacky, this achieves long integers and floats.
+            # return float(values[0]) if '.' in values[0] else long(values[0])
             return float(values[0])
-        elif option == 1:
-            return values[0] + values[2]
-        elif option == 2:
-            return values[0] - values[2]
-        elif option == 3:
-            return values[0] * values[2]
-        elif option == 4:
-            return values[0] / values[2]
-        elif option == 5:
-            return - values[1]
-        elif option == 6:
-            return values[0] ** values[2]
-        elif option == 7:
+
+        if option == 7:
             return values[1]
 
+        try:
+            if option == 1:
+                return values[0] + values[2]
+
+            if option == 2:
+                return values[0] - values[2]
+
+            if option == 3:
+                return values[0] * values[2]
+
+            if option == 4:
+                return values[0] / values[2]
+
+            if option == 5:
+                return - values[1]
+
+            if option == 6:
+                return values[0] ** values[2]
+        except OverflowError:
+            print >>sys.stderr, 'error: Overflow occured in "%s" %s %s %s' \
+                                % (target, option, names, values)
+
     # -----------------------------------------
     # raw lex script, verbatim here
     # -----------------------------------------
@@ -147,7 +160,7 @@ class Parser(BisonParser):
     "+"    { returntoken(PLUS); }
     "-"    { returntoken(MINUS); }
     "*"    { returntoken(TIMES); }
-    "**"   { returntoken(POW); }
+    "^"    { returntoken(POW); }
     "/"    { returntoken(DIVIDE); }
     "quit" { printf("lex: got QUIT\n"); yyterminate(); returntoken(QUIT); }
 

+ 31 - 0
tests/test_calc.py

@@ -1,3 +1,4 @@
+import sys
 import unittest
 
 
@@ -38,5 +39,35 @@ class TestCalc(unittest.TestCase):
     def tearDown(self):
         pass
 
+    def run_expressions(self, expressions, fail=True):
+        for exp, out in expressions:
+            try:
+                res = TestParser([exp], keepfiles=1).run()
+                assert res == out
+            except:
+                print >>sys.stderr, 'error: %s = %s, but expected: %s' \
+                                    % (exp, str(res), str(out))
+                if fail:
+                    raise
+
     def test_constructor(self):
         assert TestParser(['1+4'], keepfiles=1).run() == 5.0
+
+    def test_basic_on_exp(self):
+        expressions = [('4', 4.0),
+                       ('3+4', 7.0),
+                       ('3-4', -1.0),
+                       ('3/4', .75),
+                       ('-4', -4.0),
+                       ('3^4', 81.0),
+                       ('(4)', 4.0)]
+
+        self.run_expressions(expressions)
+
+    def test_infinity(self):
+        expressions = [('2^9999', None),
+                       ('2^-9999', 0.0),
+                       ('2^99999999999', None),
+                       ('2^-99999999999', 0.0)]
+
+        self.run_expressions(expressions, fail=False)