Răsfoiți Sursa

Parser will add negation to left-most child of scope.

Sander Mathijs van Veen 14 ani în urmă
părinte
comite
53f649a7ab
7 a modificat fișierele cu 49 adăugiri și 17 ștergeri
  1. 1 1
      external/graph_drawing
  2. 12 0
      src/node.py
  3. 25 10
      src/parser.py
  4. 4 0
      src/possibilities.py
  5. 2 1
      src/rules/negation.py
  6. 2 2
      tests/test_b1_ch08.py
  7. 3 3
      tests/test_b1_ch10.py

+ 1 - 1
external/graph_drawing

@@ -1 +1 @@
-Subproject commit 821bdb8f8408fb36ee1d92ada162589794a8c5b3
+Subproject commit fbfd0f2a3af6157d4994270bcdfa660910a2119d

+ 12 - 0
src/node.py

@@ -72,6 +72,18 @@ class ExpressionBase(object):
     def clone(self):
         return copy.deepcopy(self)
 
+    def left(self):
+        """
+        Return the left-most child of this node. When this instance is a leaf,
+        the leaf will be returned.
+        """
+        node = self
+
+        while not node.is_leaf:
+            node = node[0]
+
+        return node
+
     def __lt__(self, other):
         """
         Comparison between this expression{node,leaf} and another

+ 25 - 10
src/parser.py

@@ -16,7 +16,7 @@ sys.path.insert(1, EXTERNAL_MODS)
 from pybison import BisonParser, BisonSyntaxError
 from graph_drawing.graph import generate_graph
 
-from node import TYPE_OPERATOR, OP_COMMA, OP_NEG
+from node import TYPE_OPERATOR, OP_COMMA, OP_NEG, OP_MUL, Scope
 from rules import RULES
 from possibilities import filter_duplicates, pick_suggestion, apply_suggestion
 
@@ -193,14 +193,18 @@ class Parser(BisonParser):
         if not retval.negated and retval.type != TYPE_OPERATOR:
             return retval
 
-        if self.subtree_map and retval.type == TYPE_OPERATOR:
+        if self.subtree_map:  # and retval.type == TYPE_OPERATOR:
             # Update the subtree map to let the subtree point to its parent
             # node.
             parent_nodes = self.subtree_map.keys()
 
-            for child in retval:
-                if child in parent_nodes:
-                    self.subtree_map[child] = retval
+            if retval.is_leaf:
+                if retval in parent_nodes:
+                    self.subtree_map[retval] = None
+            else:
+                for child in retval:
+                    if child in parent_nodes:
+                        self.subtree_map[child] = retval
 
         if retval.type == TYPE_OPERATOR and retval.op in RULES:
             handlers = RULES[retval.op]
@@ -357,9 +361,14 @@ class Parser(BisonParser):
         """
 
         if option == 0:  # rule: NEG exp
-            node = values[1]
-            node.negated += 1
-            return node
+            # Add negation to the left-most child
+            if values[1].is_leaf or values[1].op != OP_MUL:
+                values[1].negated += 1
+            else:
+                child = Scope(values[1])[0]
+                child.negated += 1
+
+            return values[1]
 
         raise BisonSyntaxError('Unsupported option %d in target "%s".'
                                % (option, target))  # pragma: nocover
@@ -378,12 +387,18 @@ class Parser(BisonParser):
 
         if option == 4:  # rule: exp MINUS exp
             node = values[2]
-            node.negated += 1
+
+            # Add negation to the left-most child
+            if node.is_leaf or node.op != OP_MUL:
+                node.negated += 1
+            else:
+                node = Scope(node)[0]
+                node.negated += 1
 
             # Explicit call the hook handler on the created unary negation.
             node = self.hook_handler('binary', 4, names, values, node)
 
-            return Node('+', values[0], node)
+            return Node('+', values[0], values[2])
 
         raise BisonSyntaxError('Unsupported option %d in target "%s".'
                                % (option, target))  # pragma: nocover

+ 4 - 0
src/possibilities.py

@@ -73,6 +73,9 @@ def apply_suggestion(root, subtree_map, suggestion):
     else:
         parent_node = None
 
+    print 'suggestion:', suggestion.root, parent_node
+    print 'subtree_map:', subtree_map
+
     # There is either a parent node or the subtree is the root node.
     # FIXME: FAIL: test_diagnostic_test_application in tests/test_b1_ch08.py
     #try:
@@ -85,4 +88,5 @@ def apply_suggestion(root, subtree_map, suggestion):
     if parent_node:
         parent_node.substitute(suggestion.root, subtree)
         return root
+
     return subtree

+ 2 - 1
src/rules/negation.py

@@ -1,4 +1,4 @@
-from ..node import Scope, OP_ADD, OP_MUL, OP_DIV, TYPE_OPERATOR
+from ..node import Scope, OP_ADD, OP_MUL, OP_DIV
 from ..possibilities import Possibility as P, MESSAGES
 from ..translate import _
 
@@ -46,6 +46,7 @@ def match_negate_polynome(node):
     --a       ->  a
     -(a + b)  ->  -a - b
     """
+    print 'match_negate_polynome:', node, node.negated
     assert node.negated, str(node.negated) + '; ' + str(node)
 
     p = []

+ 2 - 2
tests/test_b1_ch08.py

@@ -11,9 +11,9 @@ class TestB1Ch08(unittest.TestCase):
         run_expressions(Parser, [
             ('6*5^2', L(6) * L(5) ** 2),
             ('-5*(-3)^2', (-L(5)) * (-L(3)) ** 2),
-            ('7p-3p', L(7) * 'p' + -(L(3) * 'p')),
+            ('7p-3p', L(7) * 'p' + (-L(3) * 'p')),
             ('-5a*-6', (-L(5)) * 'a' * (-L(6))),
-            ('3a-8--5-2a', L(3) * 'a' + -L(8) + -(-L(5)) + -(L(2) * 'a')),
+            ('3a-8--5-2a', L(3) * 'a' + -L(8) + (--L(5)) + (-L(2) * 'a')),
             ])
 
     def test_diagnostic_test_application(self):

+ 3 - 3
tests/test_b1_ch10.py

@@ -9,12 +9,12 @@ class TestB1Ch10(unittest.TestCase):
 
     def test_diagnostic_test(self):
         run_expressions(Parser, [
-            ('5(a-2b)', L(5) * (L('a') + -(L(2) * 'b'))),
+            ('5(a-2b)', L(5) * (L('a') + (-L(2) * 'b'))),
             ('-(3a+6b)', -(L(3) * L('a') + L(6) * 'b')),
             ('18-(a-12)', L(18) + -(L('a') + -L(12))),
             ('-p-q+5(p-q)-3q-2(p-q)',
-                -L('p') + -L('q') + L(5) * (L('p') + -L('q')) + -(L(3) * 'q') \
-                + - (L(2) * (L('p') + -L('q')))
+                -L('p') + -L('q') + L(5) * (L('p') + -L('q')) + (-L(3) * 'q') \
+                + (-L(2) * (L('p') + -L('q')))
             ),
             ('(2+3/7)^4',
                 N('^', N('+', L(2), N('/', L(3), L(7))), L(4))