Removed subtree_map and fixed almost all unit tests.

parent 38c0a798
......@@ -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)
......
......@@ -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
......
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
......
......@@ -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 = []
......
......@@ -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)
......
......@@ -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)
......@@ -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')
......
......@@ -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')
......
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