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

parent bf7d96e6
graph_drawing @ fbfd0f2a
Subproject commit 821bdb8f8408fb36ee1d92ada162589794a8c5b3 Subproject commit fbfd0f2a3af6157d4994270bcdfa660910a2119d
...@@ -72,6 +72,18 @@ class ExpressionBase(object): ...@@ -72,6 +72,18 @@ class ExpressionBase(object):
def clone(self): def clone(self):
return copy.deepcopy(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): def __lt__(self, other):
""" """
Comparison between this expression{node,leaf} and another Comparison between this expression{node,leaf} and another
......
...@@ -16,7 +16,7 @@ sys.path.insert(1, EXTERNAL_MODS) ...@@ -16,7 +16,7 @@ sys.path.insert(1, EXTERNAL_MODS)
from pybison import BisonParser, BisonSyntaxError from pybison import BisonParser, BisonSyntaxError
from graph_drawing.graph import generate_graph 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 rules import RULES
from possibilities import filter_duplicates, pick_suggestion, apply_suggestion from possibilities import filter_duplicates, pick_suggestion, apply_suggestion
...@@ -193,14 +193,18 @@ class Parser(BisonParser): ...@@ -193,14 +193,18 @@ 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()
for child in retval: if retval.is_leaf:
if child in parent_nodes: if retval in parent_nodes:
self.subtree_map[child] = retval 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: if retval.type == TYPE_OPERATOR and retval.op in RULES:
handlers = RULES[retval.op] handlers = RULES[retval.op]
...@@ -357,9 +361,14 @@ class Parser(BisonParser): ...@@ -357,9 +361,14 @@ class Parser(BisonParser):
""" """
if option == 0: # rule: NEG exp if option == 0: # rule: NEG exp
node = values[1] # Add negation to the left-most child
node.negated += 1 if values[1].is_leaf or values[1].op != OP_MUL:
return node values[1].negated += 1
else:
child = Scope(values[1])[0]
child.negated += 1
return values[1]
raise BisonSyntaxError('Unsupported option %d in target "%s".' raise BisonSyntaxError('Unsupported option %d in target "%s".'
% (option, target)) # pragma: nocover % (option, target)) # pragma: nocover
...@@ -378,12 +387,18 @@ class Parser(BisonParser): ...@@ -378,12 +387,18 @@ class Parser(BisonParser):
if option == 4: # rule: exp MINUS exp if option == 4: # rule: exp MINUS exp
node = values[2] 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. # Explicit call the hook handler on the created unary negation.
node = self.hook_handler('binary', 4, names, values, node) 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".' raise BisonSyntaxError('Unsupported option %d in target "%s".'
% (option, target)) # pragma: nocover % (option, target)) # pragma: nocover
......
...@@ -73,6 +73,9 @@ def apply_suggestion(root, subtree_map, suggestion): ...@@ -73,6 +73,9 @@ def apply_suggestion(root, subtree_map, suggestion):
else: else:
parent_node = None 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
#try: #try:
...@@ -85,4 +88,5 @@ def apply_suggestion(root, subtree_map, suggestion): ...@@ -85,4 +88,5 @@ def apply_suggestion(root, subtree_map, suggestion):
if parent_node: if parent_node:
parent_node.substitute(suggestion.root, subtree) parent_node.substitute(suggestion.root, subtree)
return root return root
return subtree return subtree
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 ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
...@@ -46,6 +46,7 @@ def match_negate_polynome(node): ...@@ -46,6 +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
assert node.negated, str(node.negated) + '; ' + str(node) assert node.negated, str(node.negated) + '; ' + str(node)
p = [] p = []
......
...@@ -11,9 +11,9 @@ class TestB1Ch08(unittest.TestCase): ...@@ -11,9 +11,9 @@ class TestB1Ch08(unittest.TestCase):
run_expressions(Parser, [ run_expressions(Parser, [
('6*5^2', L(6) * L(5) ** 2), ('6*5^2', L(6) * L(5) ** 2),
('-5*(-3)^2', (-L(5)) * (-L(3)) ** 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))), ('-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): def test_diagnostic_test_application(self):
......
...@@ -9,12 +9,12 @@ class TestB1Ch10(unittest.TestCase): ...@@ -9,12 +9,12 @@ class TestB1Ch10(unittest.TestCase):
def test_diagnostic_test(self): def test_diagnostic_test(self):
run_expressions(Parser, [ 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')), ('-(3a+6b)', -(L(3) * L('a') + L(6) * 'b')),
('18-(a-12)', L(18) + -(L('a') + -L(12))), ('18-(a-12)', L(18) + -(L('a') + -L(12))),
('-p-q+5(p-q)-3q-2(p-q)', ('-p-q+5(p-q)-3q-2(p-q)',
-L('p') + -L('q') + L(5) * (L('p') + -L('q')) + -(L(3) * 'q') \ -L('p') + -L('q') + L(5) * (L('p') + -L('q')) + (-L(3) * 'q') \
+ - (L(2) * (L('p') + -L('q'))) + (-L(2) * (L('p') + -L('q')))
), ),
('(2+3/7)^4', ('(2+3/7)^4',
N('^', N('+', L(2), N('/', L(3), L(7))), L(4)) N('^', N('+', L(2), N('/', L(3), L(7))), L(4))
......
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