Removed subtree_map and fixed almost all unit tests.

parent 38c0a798
...@@ -331,6 +331,9 @@ class ExpressionLeaf(Leaf, ExpressionBase): ...@@ -331,6 +331,9 @@ class ExpressionLeaf(Leaf, ExpressionBase):
return self.negated == other.negated and self.type == other.type \ return self.negated == other.negated and self.type == other.type \
and self.value == other.value and self.value == other.value
def __repr__(self):
return '-' * self.negated + str(self.value)
def equals(self, other): def equals(self, other):
""" """
Check non-strict equivalence. Check non-strict equivalence.
...@@ -375,6 +378,9 @@ class Scope(object): ...@@ -375,6 +378,9 @@ class Scope(object):
return isinstance(other, Scope) and self.node == other.node \ return isinstance(other, Scope) and self.node == other.node \
and self.nodes == other.nodes and self.nodes == other.nodes
def __repr__(self):
return '<Scope of "%s">' % repr(self.node)
def remove(self, node, **kwargs): def remove(self, node, **kwargs):
if node.is_leaf: if node.is_leaf:
node_cmp = hash(node) node_cmp = hash(node)
......
...@@ -81,7 +81,7 @@ class Parser(BisonParser): ...@@ -81,7 +81,7 @@ class Parser(BisonParser):
self.read_buffer = '' self.read_buffer = ''
self.read_queue = Queue.Queue() self.read_queue = Queue.Queue()
self.subtree_map = {} #self.subtree_map = {}
self.root_node = None self.root_node = None
self.possibilities = self.last_possibilities = [] self.possibilities = self.last_possibilities = []
...@@ -193,18 +193,19 @@ class Parser(BisonParser): ...@@ -193,18 +193,19 @@ class Parser(BisonParser):
if not retval.negated and retval.type != TYPE_OPERATOR: if not retval.negated and retval.type != TYPE_OPERATOR:
return retval 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 # # Update the subtree map to let the subtree point to its parent
# node. # # node.
parent_nodes = self.subtree_map.keys() # parent_nodes = self.subtree_map.keys()
if retval.is_leaf: # #if retval.is_leaf:
if retval in parent_nodes: # # if retval in parent_nodes:
self.subtree_map[retval] = None # # self.subtree_map[retval] = None
else: # #else:
for child in retval: # for child in retval:
if child in parent_nodes: # print 'child:', child, 'in', parent_nodes
self.subtree_map[child] = retval # if child in parent_nodes:
# self.subtree_map[child] = retval
if retval.type == TYPE_OPERATOR and retval.op in RULES: if retval.type == TYPE_OPERATOR and retval.op in RULES:
handlers = RULES[retval.op] handlers = RULES[retval.op]
...@@ -220,8 +221,8 @@ class Parser(BisonParser): ...@@ -220,8 +221,8 @@ class Parser(BisonParser):
# Record the subtree root node in order to avoid tree traversal. # Record the subtree root node in order to avoid tree traversal.
# At this moment, the node is the root node since the expression is # At this moment, the node is the root node since the expression is
# parser using the left-innermost parsing strategy. # parser using the left-innermost parsing strategy.
for p in possibilities: #for p in possibilities:
self.subtree_map[p.root] = None # self.subtree_map[p.root] = None
self.possibilities.extend(possibilities) self.possibilities.extend(possibilities)
...@@ -242,8 +243,7 @@ class Parser(BisonParser): ...@@ -242,8 +243,7 @@ class Parser(BisonParser):
if not suggestion: if not suggestion:
return self.root_node return self.root_node
expression = apply_suggestion(self.root_node, self.subtree_map, expression = apply_suggestion(self.root_node, suggestion)
suggestion)
if self.verbose: if self.verbose:
print 'After application, expression=', expression print 'After application, expression=', expression
......
from node import TYPE_OPERATOR
# Each rule will append its hint message to the following dictionary. The # 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 # 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 # corresponding value is a string, which will be used to produce the hint
...@@ -60,7 +63,27 @@ def pick_suggestion(possibilities): ...@@ -60,7 +63,27 @@ def pick_suggestion(possibilities):
return possibilities[suggestion] 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 # 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 # node, the subtree_map cannot be used since the hash() of each node in the
# deep copied root node has changed. # deep copied root node has changed.
...@@ -68,13 +91,7 @@ def apply_suggestion(root, subtree_map, suggestion): ...@@ -68,13 +91,7 @@ def apply_suggestion(root, subtree_map, suggestion):
subtree = suggestion.handler(suggestion.root, suggestion.args) subtree = suggestion.handler(suggestion.root, suggestion.args)
if suggestion.root in subtree_map: parent_node = find_parent_node(root, suggestion.root)
parent_node = subtree_map[suggestion.root]
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. # 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 # FIXME: FAIL: test_diagnostic_test_application in tests/test_b1_ch08.py
......
...@@ -46,7 +46,7 @@ def match_negate_polynome(node): ...@@ -46,7 +46,7 @@ def match_negate_polynome(node):
--a -> a --a -> a
-(a + b) -> -a - b -(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) assert node.negated, str(node.negated) + '; ' + str(node)
p = [] p = []
......
...@@ -17,10 +17,15 @@ def add_numerics(root, args): ...@@ -17,10 +17,15 @@ def add_numerics(root, args):
""" """
scope, n0, n1, c0, c1 = 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 # Replace the left node with the new expression
leaf = Leaf(c0.value + c1.value) scope.replace(n0, leaf)
print 'New leaf:', c0.value, c1.value, leaf
scope.replace(n0, leaf.negate(c0.negated + c1.negated))
# Remove the right node # Remove the right node
scope.remove(n1) scope.remove(n1)
......
...@@ -27,9 +27,11 @@ class TestParser(unittest.TestCase): ...@@ -27,9 +27,11 @@ class TestParser(unittest.TestCase):
def test_reset_after_failure(self): def test_reset_after_failure(self):
parser = ParserWrapper(Parser) parser = ParserWrapper(Parser)
parser.run(['-(3a+6b)']) parser.run(['-(3a+6b)'])
possibilities = parser.parser.possibilities possibilities1 = parser.parser.possibilities
print possibilities self.assertNotEqual(possibilities1, [])
parser.run(['5+2*6']) parser.run(['5+2*6'])
possibilities = parser.parser.possibilities possibilities2 = parser.parser.possibilities
print possibilities self.assertNotEqual(possibilities2, [])
self.assertNotEqual(possibilities1, possibilities2)
...@@ -45,7 +45,7 @@ class TestPossibilities(unittest.TestCase): ...@@ -45,7 +45,7 @@ class TestPossibilities(unittest.TestCase):
possibilities = parser.parser.possibilities possibilities = parser.parser.possibilities
self.assertEqual('\n'.join([repr(pos) for pos in possibilities]), self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
'<Possibility root="3 + 4" handler=add_numerics' \ '<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): def test_multiple_runs(self):
parser = ParserWrapper(Parser) parser = ParserWrapper(Parser)
...@@ -53,21 +53,19 @@ class TestPossibilities(unittest.TestCase): ...@@ -53,21 +53,19 @@ class TestPossibilities(unittest.TestCase):
possibilities = parser.parser.possibilities possibilities = parser.parser.possibilities
self.assertEqual('\n'.join([repr(pos) for pos in possibilities]), self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
'<Possibility root="1 + 2" handler=add_numerics' \ '<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(['', ' ']) parser.run(['', ' '])
possibilities = parser.parser.possibilities possibilities = parser.parser.possibilities
self.assertEqual('\n'.join([repr(pos) for pos in possibilities]), self.assertEqual(possibilities, [])
'<Possibility root="1 + 2" handler=add_numerics' \
' args=(1, 2, 1, 2)>')
# Overwrite previous possibilities with new ones # Overwrite previous possibilities with new ones
parser.run(['3+4']) parser.run(['3+4'])
possibilities = parser.parser.possibilities possibilities = parser.parser.possibilities
self.assertEqual('\n'.join([repr(pos) for pos in possibilities]), self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
'<Possibility root="3 + 4" handler=add_numerics' \ '<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): def test_filter_duplicates(self):
a, b = ab = tree('a + b') a, b = ab = tree('a + b')
......
...@@ -84,7 +84,7 @@ class TestRulesPowers(RulesTestCase): ...@@ -84,7 +84,7 @@ class TestRulesPowers(RulesTestCase):
possibilities = match_remove_negative_exponent(root) possibilities = match_remove_negative_exponent(root)
self.assertEqualPos(possibilities, self.assertEqualPos(possibilities,
[P(root, remove_negative_exponent, (a, p))]) [P(root, remove_negative_exponent, (a, -p))])
def test_match_exponent_to_root(self): def test_match_exponent_to_root(self):
a, n, m, l1 = tree('a,n,m,1') a, n, m, l1 = tree('a,n,m,1')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment