Browse Source

Parentheses are now only added to sub-expressions when nescesary.

Taddeus Kroes 14 năm trước cách đây
mục cha
commit
15abdd61c3
2 tập tin đã thay đổi với 38 bổ sung6 xóa
  1. 22 5
      line.py
  2. 16 1
      tests/test_line.py

+ 22 - 5
line.py

@@ -82,11 +82,21 @@ def generate_line(root):
         if is_operator(node):
             if arity == 1:
                 # Unary operator
-                sub_exp = traverse(node[0])
-
-                if ' ' in sub_exp:
-                    # Negated sub-expressions with spaces in them should be
-                    # enclosed in parentheses
+                sub = node[0]
+                sub_exp = traverse(sub)
+
+                # Negated sub-expressions with spaces in them should be
+                # enclosed in parentheses, unless they have a higher precedence
+                # than subtraction are rewritten to a factor of a subtraction:
+                # -(1 + 2)
+                # -(1 - 2)
+                # -4a
+                # -(4 * 5)
+                # 1 - 4 * 5
+                # 1 + -(4 * 5)  ->  1 - 4 * 5
+                if ' ' in sub_exp and not (not isinstance(sub, Leaf) \
+                        and hasattr(node, 'marked_negation')
+                        and pred(sub) > 0):
                     sub_exp = '(' + sub_exp + ')'
 
                 result = op + sub_exp
@@ -97,6 +107,13 @@ def generate_line(root):
                 sep = ' ' + op + ' '
                 e = []
 
+                # Mark added and subtracted negations for later use when adding
+                # parentheses
+                if op in ('+', '-'):
+                    for child in node:
+                        if child.title() == '-' and len(child) == 1:
+                            child.marked_negation = True
+
                 for i, child in enumerate(node):
                     exp = traverse(child)
 

+ 16 - 1
tests/test_line.py

@@ -154,12 +154,27 @@ class TestLine(unittest.TestCase):
         self.assertFalse(is_int(neg_a))
         self.assertFalse(is_int(plus))
 
-    def test_negated_nary(self):
+    def test_negated_addition_subtraction(self):
         neg = N('-', N('+', L(1), L(2)))
         self.assertEquals(generate_line(neg), '-(1 + 2)')
 
+        neg = N('-', N('-', L(1), L(2)))
+        self.assertEquals(generate_line(neg), '-(1 - 2)')
+
+        neg = N('+', L(1), N('-', N('+', L(1), L(2))))
+        self.assertEquals(generate_line(neg), '1 - (1 + 2)')
+
         neg = N('-', N('*', L(4), L('a')))
         self.assertEquals(generate_line(neg), '-4a')
 
+        neg = N('-', N('*', L(4), L(5)))
+        self.assertEquals(generate_line(neg), '-(4 * 5)')
+
+        plus = N('+', L(1), N('-', N('*', L(4), L(5))))
+        self.assertEquals(generate_line(plus), '1 - 4 * 5')
+
+        plus = N('+', L(1), N('-', L(4)))
+        self.assertEquals(generate_line(plus), '1 - 4')
+
         neg = N('-', N('-', L(1)))
         self.assertEquals(generate_line(neg), '--1')