possibilities.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. from node import TYPE_OPERATOR
  2. import re
  3. # Each rule will append its hint message to the following dictionary. The
  4. # function pointer to the apply function of the rule is used as key. The
  5. # corresponding value is a string, which will be used to produce the hint
  6. # message. The string will be processed using string.format().
  7. MESSAGES = {}
  8. class Possibility(object):
  9. def __init__(self, root, handler, args=()):
  10. self.root = root
  11. self.handler = handler
  12. self.args = args
  13. def __str__(self):
  14. if self.handler in MESSAGES:
  15. msg = MESSAGES[self.handler]
  16. if callable(msg):
  17. msg = msg(self.root, self.args)
  18. # Surround math notation with backticks. If there are any backticks
  19. # already, do not add additional backticks. The add_backticks
  20. # lambda is necessary otherwise because \1 and \2 are not matched
  21. # both at the same time.
  22. add_backticks = lambda x: '`%s`' % ''.join(x.groups(''))
  23. msg = re.sub('`([^`]*)`|(\(?{[^. ]+)', add_backticks, msg)
  24. return msg.format(self.root, *self.args)
  25. return repr(self)
  26. def __repr__(self):
  27. return '<Possibility root="%s" handler=%s args=%s>' \
  28. % (self.root, self.handler.func_name, self.args)
  29. def __eq__(self, other):
  30. """
  31. Use node hash comparison when comparing to other Possibility to assert
  32. that its is the same object as in this one.
  33. """
  34. return self.handler == other.handler \
  35. and hash(self.root) == hash(other.root) \
  36. and self.args == other.args
  37. def find_parent_node(root, child):
  38. nodes = [root]
  39. while nodes:
  40. node = nodes.pop()
  41. while node:
  42. if node.type != TYPE_OPERATOR:
  43. break
  44. if child in node:
  45. return node
  46. if len(node) > 1:
  47. nodes.append(node[1])
  48. node = node[0]
  49. def apply_suggestion(root, suggestion):
  50. # TODO: clone the root node before modifying. After deep copying the root
  51. # node, the subtree_map cannot be used since the hash() of each node in the
  52. # deep copied root node has changed.
  53. #root = root.clone()
  54. subtree = suggestion.handler(suggestion.root, suggestion.args)
  55. parent_node = find_parent_node(root, suggestion.root)
  56. # There is either a parent node or the subtree is the root node.
  57. # FIXME: FAIL: test_diagnostic_test_application in tests/test_b1_ch08.py
  58. #try:
  59. # assert bool(parent_node) != (subtree == root)
  60. #except:
  61. # print 'parent_node: %s' % (str(parent_node))
  62. # print 'subtree: %s == %s' % (str(subtree), str(root))
  63. # raise
  64. if parent_node:
  65. parent_node.substitute(suggestion.root, subtree)
  66. return root
  67. return subtree