Procházet zdrojové kódy

Removed subtree_map and fixed almost all unit tests.

Sander Mathijs van Veen před 14 roky
rodič
revize
564c751bbe

+ 6 - 0
src/node.py

@@ -331,6 +331,9 @@ class ExpressionLeaf(Leaf, ExpressionBase):
         return self.negated == other.negated and self.type == other.type \
                and self.value == other.value
 
+    def __repr__(self):
+        return '-' * self.negated + str(self.value)
+
     def equals(self, other):
         """
         Check non-strict equivalence.
@@ -375,6 +378,9 @@ class Scope(object):
         return isinstance(other, Scope) and self.node == other.node \
                and self.nodes == other.nodes
 
+    def __repr__(self):
+        return '<Scope of "%s">' % repr(self.node)
+
     def remove(self, node, **kwargs):
         if node.is_leaf:
             node_cmp = hash(node)

+ 16 - 16
src/parser.py

@@ -81,7 +81,7 @@ class Parser(BisonParser):
         self.read_buffer = ''
         self.read_queue = Queue.Queue()
 
-        self.subtree_map = {}
+        #self.subtree_map = {}
         self.root_node = None
         self.possibilities = self.last_possibilities = []
 
@@ -193,18 +193,19 @@ class Parser(BisonParser):
         if not retval.negated and retval.type != TYPE_OPERATOR:
             return retval
 
-        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()
+        #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()
 
-            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.is_leaf:
+        #    #    if retval in parent_nodes:
+        #    #        self.subtree_map[retval] = None
+        #    #else:
+        #    for child in retval:
+        #        print 'child:', child, 'in', parent_nodes
+        #        if child in parent_nodes:
+        #            self.subtree_map[child] = retval
 
         if retval.type == TYPE_OPERATOR and retval.op in RULES:
             handlers = RULES[retval.op]
@@ -220,8 +221,8 @@ class Parser(BisonParser):
             # Record the subtree root node in order to avoid tree traversal.
             # At this moment, the node is the root node since the expression is
             # parser using the left-innermost parsing strategy.
-            for p in possibilities:
-                self.subtree_map[p.root] = None
+            #for p in possibilities:
+            #    self.subtree_map[p.root] = None
 
             self.possibilities.extend(possibilities)
 
@@ -242,8 +243,7 @@ class Parser(BisonParser):
         if not suggestion:
             return self.root_node
 
-        expression = apply_suggestion(self.root_node, self.subtree_map,
-                                    suggestion)
+        expression = apply_suggestion(self.root_node, suggestion)
 
         if self.verbose:
             print 'After application, expression=', expression

+ 25 - 8
src/possibilities.py

@@ -1,3 +1,6 @@
+from node import TYPE_OPERATOR
+
+
 # Each rule will append its hint message to the following dictionary. The
 # function pointer to the apply function of the rule is used as key. The
 # corresponding value is a string, which will be used to produce the hint
@@ -60,7 +63,27 @@ def pick_suggestion(possibilities):
     return possibilities[suggestion]
 
 
-def apply_suggestion(root, subtree_map, suggestion):
+def find_parent_node(root, child):
+    nodes = [root]
+
+    while nodes:
+        node = nodes.pop()
+
+        while node:
+
+            if node.type != TYPE_OPERATOR:
+                break
+
+            if child in node:
+                return node
+
+            if len(node) > 1:
+                nodes.append(node[1])
+
+            node = node[0]
+
+
+def apply_suggestion(root, suggestion):
     # TODO: clone the root node before modifying. After deep copying the root
     # node, the subtree_map cannot be used since the hash() of each node in the
     # deep copied root node has changed.
@@ -68,13 +91,7 @@ def apply_suggestion(root, subtree_map, suggestion):
 
     subtree = suggestion.handler(suggestion.root, suggestion.args)
 
-    if suggestion.root in subtree_map:
-        parent_node = subtree_map[suggestion.root]
-    else:
-        parent_node = None
-
-    print 'suggestion:', suggestion.root, parent_node
-    print 'subtree_map:', subtree_map
+    parent_node = find_parent_node(root, suggestion.root)
 
     # 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

+ 1 - 1
src/rules/negation.py

@@ -46,7 +46,7 @@ def match_negate_polynome(node):
     --a       ->  a
     -(a + b)  ->  -a - b
     """
-    print 'match_negate_polynome:', node, node.negated
+    #print 'match_negate_polynome:', node, node.negated
     assert node.negated, str(node.negated) + '; ' + str(node)
 
     p = []

+ 8 - 3
src/rules/numerics.py

@@ -17,10 +17,15 @@ def add_numerics(root, args):
     """
     scope, n0, n1, c0, c1 = args
 
+    value = c0.actual_value() + c1.actual_value()
+
+    if value < 0:
+        leaf = Leaf(-value).negate()
+    else:
+        leaf = Leaf(value)
+
     # Replace the left node with the new expression
-    leaf = Leaf(c0.value + c1.value)
-    print 'New leaf:', c0.value, c1.value, leaf
-    scope.replace(n0, leaf.negate(c0.negated + c1.negated))
+    scope.replace(n0, leaf)
 
     # Remove the right node
     scope.remove(n1)

+ 6 - 4
tests/test_parser.py

@@ -27,9 +27,11 @@ class TestParser(unittest.TestCase):
     def test_reset_after_failure(self):
         parser = ParserWrapper(Parser)
         parser.run(['-(3a+6b)'])
-        possibilities = parser.parser.possibilities
-        print possibilities
+        possibilities1 = parser.parser.possibilities
+        self.assertNotEqual(possibilities1, [])
 
         parser.run(['5+2*6'])
-        possibilities = parser.parser.possibilities
-        print possibilities
+        possibilities2 = parser.parser.possibilities
+        self.assertNotEqual(possibilities2, [])
+
+        self.assertNotEqual(possibilities1, possibilities2)

+ 5 - 7
tests/test_possibilities.py

@@ -45,7 +45,7 @@ class TestPossibilities(unittest.TestCase):
         possibilities = parser.parser.possibilities
         self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
                     '<Possibility root="3 + 4" handler=add_numerics' \
-                    ' args=(3, 4, 3, 4)>')
+                    ' args=(<Scope of "3 + 4">, 3, 4, 3, 4)>')
 
     def test_multiple_runs(self):
         parser = ParserWrapper(Parser)
@@ -53,21 +53,19 @@ class TestPossibilities(unittest.TestCase):
         possibilities = parser.parser.possibilities
         self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
                     '<Possibility root="1 + 2" handler=add_numerics' \
-                    ' args=(1, 2, 1, 2)>')
+                    ' args=(<Scope of "1 + 2">, 1, 2, 1, 2)>')
 
-        # Keep previous possibilities (skip whitespace lines)
+        # Remove previous possibilities after second run() call.
         parser.run(['', ' '])
         possibilities = parser.parser.possibilities
-        self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
-                    '<Possibility root="1 + 2" handler=add_numerics' \
-                    ' args=(1, 2, 1, 2)>')
+        self.assertEqual(possibilities, [])
 
         # Overwrite previous possibilities with new ones
         parser.run(['3+4'])
         possibilities = parser.parser.possibilities
         self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
                     '<Possibility root="3 + 4" handler=add_numerics' \
-                    ' args=(3, 4, 3, 4)>')
+                    ' args=(<Scope of "3 + 4">, 3, 4, 3, 4)>')
 
     def test_filter_duplicates(self):
         a, b = ab = tree('a + b')

+ 1 - 1
tests/test_rules_powers.py

@@ -84,7 +84,7 @@ class TestRulesPowers(RulesTestCase):
 
         possibilities = match_remove_negative_exponent(root)
         self.assertEqualPos(possibilities,
-                [P(root, remove_negative_exponent, (a, p))])
+                [P(root, remove_negative_exponent, (a, -p))])
 
     def test_match_exponent_to_root(self):
         a, n, m, l1 = tree('a,n,m,1')