Przeglądaj źródła

Improved preprocessor: a 4 (with space in between) is now converted to a*4 instead of a^4.

Taddeus Kroes 14 lat temu
rodzic
commit
31876fd43a
2 zmienionych plików z 25 dodań i 13 usunięć
  1. 12 12
      src/parser.py
  2. 13 1
      tests/test_parser.py

+ 12 - 12
src/parser.py

@@ -180,16 +180,17 @@ class Parser(BisonParser):
         #   - "4a" with "4*a".
         #   - "a4" with "a^4".
 
-        pattern = ('(?:(\))\s*(\(|\[)'                       # )(  -> ) * (
-                                                             # )[  -> ) * [
-                + '|([\x00-\x09\x0b-\x19a-z0-9])\s*(\(|\[)'  # a(  -> a * (
-                                                             # a[  -> a * [
-                + '|(\))\s*([\x00-\x09\x0b-\x19a-z0-9])'     # )a  -> ) * a
+        pattern = ('(?:(\))\s*(\(|\[)'                        # )(  -> ) * (
+                                                              # )[  -> ) * [
+                + '|([\x00-\x09\x0b-\x19a-z0-9])\s*(\(|\[)'   # a(  -> a * (
+                                                              # a[  -> a * [
+                + '|(\))\s*([\x00-\x09\x0b-\x19a-z0-9])'      # )a  -> ) * a
                 + '|([\x00-\x09\x0b-\x19a-z])\s*'
-                  + '([\x00-\x09\x0b-\x19a-z])'              # ab  -> a * b
-                + '|([0-9])\s*([\x00-\x09\x0b-\x19a-z])'     # 4a  -> 4 * a
-                + '|([\x00-\x09\x0b-\x19a-z])\s*([0-9])'     # a4  -> a ^ 4
-                + '|([0-9])\s+([0-9]))'                      # 4 4 -> 4 * 4
+                  + '([\x00-\x09\x0b-\x19a-z])'               # ab  -> a * b
+                + '|([0-9])\s*([\x00-\x09\x0b-\x19a-z])'      # 4a  -> 4 * a
+                + '|([\x00-\x09\x0b-\x19a-z])([0-9])'         # a4  -> a ^ 4
+                + '|([\x00-\x09\x0b-\x19a-z0-9])(\s+[0-9]))'  # a 4 -> a * 4,
+                                                              # 4 4 -> 4 * 4
                 )
 
         def preprocess_data(match):
@@ -204,12 +205,11 @@ class Parser(BisonParser):
             # If all characters on the right are numbers. e.g. "a4", the
             # expression implies exponentiation. Make sure ")4" is not
             # converted into an exponentiation, because that's multiplication.
-            if left != ')' and not 48 <= ord(left) < 58 \
-                    and all(map(lambda x: 48 <= ord(x) < 58, list(right))):
+            if left != ')' and not left.isdigit() and right.isdigit():
                 return '%s^%s' % (left, right)
 
             # match: ab | abc | abcd (where left = "a")
-            return '*'.join([left] + list(right))
+            return '*'.join([left] + list(re.sub(r'^ +', '', right)))
 
         if self.verbose:  # pragma: nocover
             data_before = data

+ 13 - 1
tests/test_parser.py

@@ -42,6 +42,15 @@ class TestParser(unittest.TestCase):
 
         self.assertNotEqual(possibilities1, possibilities2)
 
+    def test_preprocessor(self):
+        self.assertEqual(tree('ab'), tree('a * b'))
+        self.assertEqual(tree('abc'), tree('a * b * c'))
+        self.assertEqual(tree('a2'), tree('a ^ 2'))
+        self.assertEqual(tree('a 2'), tree('a * 2'))
+        self.assertEqual(tree('2a'), tree('2 * a'))
+        self.assertEqual(tree('2(a + b)'), tree('2 * (a + b)'))
+        self.assertEqual(tree('(a + b)2'), tree('(a + b) * 2'))
+
     def test_moved_negation(self):
         a, b = tree('a,b')
 
@@ -100,7 +109,7 @@ class TestParser(unittest.TestCase):
             # FIXME: self.assertEqual(tree('a' + token + 'a'), a * t * a)
 
     def test_integral(self):
-        x, y, dx, a, b = tree('x, y, dx, a, b')
+        x, y, dx, a, b, l2 = tree('x, y, dx, a, b, 2')
 
         self.assertEqual(tree('int x'), integral(x, x))
         self.assertEqual(tree('int x2'), integral(x ** 2, x))
@@ -112,6 +121,9 @@ class TestParser(unittest.TestCase):
         self.assertEqual(tree('int_(a-b)^(a+b) x2'),
                          integral(x ** 2, x, a - b, a + b))
 
+        self.assertEqual(tree('int_a^b 2x'), integral(l2 * x, x, a, b))
+        self.assertEqual(tree('int_a^b2 x'), integral(x, x, a, b ** 2))
+
     def test_indefinite_integral(self):
         x2, a, b = tree('x ^ 2, a, b')