This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.0 KiB

  1. from ..utils import compare
  2. from functools import cmp_to_key
  3. from ..tree import Tree, Visitor_NoRecurse
  4. # Standard ambiguity resolver (uses comparison)
  5. #
  6. # Author: Erez Sh
  7. def _compare_rules(rule1, rule2):
  8. c = -compare( len(rule1.expansion), len(rule2.expansion))
  9. if rule1.origin.startswith('__'): # XXX hack! We should set priority in parser, not here
  10. c = -c
  11. return c
  12. def _sum_priority(tree):
  13. p = 0
  14. for n in tree.iter_subtrees():
  15. try:
  16. p += n.rule.options.priority or 0
  17. except AttributeError:
  18. pass
  19. return p
  20. def _compare_priority(tree1, tree2):
  21. tree1.iter_subtrees()
  22. def _compare_drv(tree1, tree2):
  23. try:
  24. rule1, rule2 = tree1.rule, tree2.rule
  25. except AttributeError:
  26. # Probably non-trees, or user trees that weren't created by the parse (better way to distinguish?)
  27. return compare(tree1, tree2)
  28. assert tree1.data != '_ambig'
  29. assert tree2.data != '_ambig'
  30. p1 = _sum_priority(tree1)
  31. p2 = _sum_priority(tree2)
  32. c = (p1 or p2) and compare(p1, p2)
  33. if c:
  34. return c
  35. c = _compare_rules(tree1.rule, tree2.rule)
  36. if c:
  37. return c
  38. # rules are "equal", so compare trees
  39. if len(tree1.children) == len(tree2.children):
  40. for t1, t2 in zip(tree1.children, tree2.children):
  41. c = _compare_drv(t1, t2)
  42. if c:
  43. return c
  44. return compare(len(tree1.children), len(tree2.children))
  45. def _standard_resolve_ambig(tree):
  46. assert tree.data == '_ambig'
  47. key_f = cmp_to_key(_compare_drv)
  48. best = max(tree.children, key=key_f)
  49. assert best.data == 'drv'
  50. tree.set('drv', best.children)
  51. tree.rule = best.rule # needed for applying callbacks
  52. def standard_resolve_ambig(tree):
  53. for ambig in tree.find_data('_ambig'):
  54. _standard_resolve_ambig(ambig)
  55. return tree
  56. # Anti-score Sum
  57. #
  58. # Author: Uriva (https://github.com/uriva)
  59. def _antiscore_sum_drv(tree):
  60. if not isinstance(tree, Tree):
  61. return 0
  62. # XXX These artifacts can appear due to imperfections in the ordering of Visitor_NoRecurse,
  63. # when confronted with duplicate (same-id) nodes. Fixing this ordering is possible, but would be
  64. # computationally inefficient. So we handle it here.
  65. if tree.data == '_ambig':
  66. _antiscore_sum_resolve_ambig(tree)
  67. try:
  68. priority = tree.rule.options.priority
  69. except AttributeError:
  70. # Probably trees that don't take part in this parse (better way to distinguish?)
  71. priority = None
  72. return (priority or 0) + sum(map(_antiscore_sum_drv, tree.children), 0)
  73. def _antiscore_sum_resolve_ambig(tree):
  74. assert tree.data == '_ambig'
  75. best = min(tree.children, key=_antiscore_sum_drv)
  76. assert best.data == 'drv'
  77. tree.set('drv', best.children)
  78. tree.rule = best.rule # needed for applying callbacks
  79. def antiscore_sum_resolve_ambig(tree):
  80. for ambig in tree.find_data('_ambig'):
  81. _antiscore_sum_resolve_ambig(ambig)
  82. return tree