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.

110 lines
3.4 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. if rule1.origin != rule2.origin:
  9. if rule1.options and rule2.options:
  10. if rule1.options.priority is not None and rule2.options.priority is not None:
  11. assert rule1.options.priority != rule2.options.priority, "Priority is the same between both rules: %s == %s" % (rule1, rule2)
  12. return -compare(rule1.options.priority, rule2.options.priority)
  13. return 0
  14. c = compare( len(rule1.expansion), len(rule2.expansion))
  15. if rule1.origin.startswith('__'): # XXX hack! We need to set priority in parser, not here
  16. c = -c
  17. return c
  18. def _compare_drv(tree1, tree2):
  19. if not (isinstance(tree1, Tree) and isinstance(tree2, Tree)):
  20. try:
  21. return -compare(tree1, tree2)
  22. except TypeError:
  23. return 0
  24. try:
  25. rule1, rule2 = tree1.rule, tree2.rule
  26. except AttributeError:
  27. # Probably trees that don't take part in this parse (better way to distinguish?)
  28. return -compare(tree1, tree2)
  29. # XXX These artifacts can appear due to imperfections in the ordering of Visitor_NoRecurse,
  30. # when confronted with duplicate (same-id) nodes. Fixing this ordering is possible, but would be
  31. # computationally inefficient. So we handle it here.
  32. if tree1.data == '_ambig':
  33. _standard_resolve_ambig(tree1)
  34. if tree2.data == '_ambig':
  35. _standard_resolve_ambig(tree2)
  36. c = _compare_rules(tree1.rule, tree2.rule)
  37. if c:
  38. return c
  39. # rules are "equal", so compare trees
  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. best = min(tree.children, key=cmp_to_key(_compare_drv))
  48. assert best.data == 'drv'
  49. tree.set('drv', best.children)
  50. tree.rule = best.rule # needed for applying callbacks
  51. def standard_resolve_ambig(tree):
  52. for ambig in tree.find_data('_ambig'):
  53. _standard_resolve_ambig(ambig)
  54. return tree
  55. # Anti-score Sum
  56. #
  57. # Author: Uriva (https://github.com/uriva)
  58. def _antiscore_sum_drv(tree):
  59. if not isinstance(tree, Tree):
  60. return 0
  61. # XXX These artifacts can appear due to imperfections in the ordering of Visitor_NoRecurse,
  62. # when confronted with duplicate (same-id) nodes. Fixing this ordering is possible, but would be
  63. # computationally inefficient. So we handle it here.
  64. if tree.data == '_ambig':
  65. _antiscore_sum_resolve_ambig(tree)
  66. try:
  67. priority = tree.rule.options.priority
  68. except AttributeError:
  69. # Probably trees that don't take part in this parse (better way to distinguish?)
  70. priority = None
  71. return (priority or 0) + sum(map(_antiscore_sum_drv, tree.children), 0)
  72. def _antiscore_sum_resolve_ambig(tree):
  73. assert tree.data == '_ambig'
  74. best = min(tree.children, key=_antiscore_sum_drv)
  75. assert best.data == 'drv'
  76. tree.set('drv', best.children)
  77. tree.rule = best.rule # needed for applying callbacks
  78. def antiscore_sum_resolve_ambig(tree):
  79. for ambig in tree.find_data('_ambig'):
  80. _antiscore_sum_resolve_ambig(ambig)
  81. return tree