This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

229 рядки
7.0 KiB

  1. from __future__ import absolute_import
  2. import unittest
  3. from lark import Lark
  4. from lark.lexer import Token
  5. from lark.tree import Tree
  6. from lark.visitors import Visitor, Transformer, Discard
  7. from lark.parsers.earley_forest import TreeForestTransformer, handles_ambiguity
  8. class TestTreeForestTransformer(unittest.TestCase):
  9. grammar = """
  10. start: ab bc cd
  11. !ab: "A" "B"?
  12. !bc: "B"? "C"?
  13. !cd: "C"? "D"
  14. """
  15. parser = Lark(grammar, parser='earley', ambiguity='forest')
  16. forest = parser.parse("ABCD")
  17. def test_identity_resolve_ambiguity(self):
  18. l = Lark(self.grammar, parser='earley', ambiguity='resolve')
  19. tree1 = l.parse("ABCD")
  20. tree2 = TreeForestTransformer(resolve_ambiguity=True).transform(self.forest)
  21. self.assertEqual(tree1, tree2)
  22. def test_identity_explicit_ambiguity(self):
  23. l = Lark(self.grammar, parser='earley', ambiguity='explicit')
  24. tree1 = l.parse("ABCD")
  25. tree2 = TreeForestTransformer(resolve_ambiguity=False).transform(self.forest)
  26. self.assertEqual(tree1, tree2)
  27. def test_tree_class(self):
  28. class CustomTree(Tree):
  29. pass
  30. class TreeChecker(Visitor):
  31. def __default__(self, tree):
  32. assert isinstance(tree, CustomTree)
  33. tree = TreeForestTransformer(resolve_ambiguity=False, tree_class=CustomTree).transform(self.forest)
  34. TreeChecker().visit(tree)
  35. def test_token_calls(self):
  36. visited = [False] * 4
  37. class CustomTransformer(TreeForestTransformer):
  38. def A(self, node):
  39. assert node.type == 'A'
  40. visited[0] = True
  41. def B(self, node):
  42. assert node.type == 'B'
  43. visited[1] = True
  44. def C(self, node):
  45. assert node.type == 'C'
  46. visited[2] = True
  47. def D(self, node):
  48. assert node.type == 'D'
  49. visited[3] = True
  50. tree = CustomTransformer(resolve_ambiguity=False).transform(self.forest)
  51. assert visited == [True] * 4
  52. def test_default_token(self):
  53. token_count = [0]
  54. class CustomTransformer(TreeForestTransformer):
  55. def __default_token__(self, node):
  56. token_count[0] += 1
  57. assert isinstance(node, Token)
  58. tree = CustomTransformer(resolve_ambiguity=True).transform(self.forest)
  59. self.assertEqual(token_count[0], 4)
  60. def test_rule_calls(self):
  61. visited_start = [False]
  62. visited_ab = [False]
  63. visited_bc = [False]
  64. visited_cd = [False]
  65. class CustomTransformer(TreeForestTransformer):
  66. def start(self, data):
  67. visited_start[0] = True
  68. def ab(self, data):
  69. visited_ab[0] = True
  70. def bc(self, data):
  71. visited_bc[0] = True
  72. def cd(self, data):
  73. visited_cd[0] = True
  74. tree = CustomTransformer(resolve_ambiguity=False).transform(self.forest)
  75. self.assertTrue(visited_start[0])
  76. self.assertTrue(visited_ab[0])
  77. self.assertTrue(visited_bc[0])
  78. self.assertTrue(visited_cd[0])
  79. def test_default_rule(self):
  80. rule_count = [0]
  81. class CustomTransformer(TreeForestTransformer):
  82. def __default__(self, name, data):
  83. rule_count[0] += 1
  84. tree = CustomTransformer(resolve_ambiguity=True).transform(self.forest)
  85. self.assertEqual(rule_count[0], 4)
  86. def test_default_ambig(self):
  87. ambig_count = [0]
  88. class CustomTransformer(TreeForestTransformer):
  89. def __default_ambig__(self, name, data):
  90. if len(data) > 1:
  91. ambig_count[0] += 1
  92. tree = CustomTransformer(resolve_ambiguity=False).transform(self.forest)
  93. self.assertEqual(ambig_count[0], 1)
  94. def test_handles_ambiguity(self):
  95. class CustomTransformer(TreeForestTransformer):
  96. @handles_ambiguity
  97. def start(self, data):
  98. assert isinstance(data, list)
  99. assert len(data) == 4
  100. for tree in data:
  101. assert tree.data == 'start'
  102. return 'handled'
  103. @handles_ambiguity
  104. def ab(self, data):
  105. assert isinstance(data, list)
  106. assert len(data) == 1
  107. assert data[0].data == 'ab'
  108. tree = CustomTransformer(resolve_ambiguity=False).transform(self.forest)
  109. self.assertEqual(tree, 'handled')
  110. def test_discard(self):
  111. class CustomTransformer(TreeForestTransformer):
  112. def bc(self, data):
  113. raise Discard()
  114. def D(self, node):
  115. raise Discard()
  116. class TreeChecker(Transformer):
  117. def bc(self, children):
  118. assert False
  119. def D(self, token):
  120. assert False
  121. tree = CustomTransformer(resolve_ambiguity=False).transform(self.forest)
  122. TreeChecker(visit_tokens=True).transform(tree)
  123. def test_aliases(self):
  124. visited_ambiguous = [False]
  125. visited_full = [False]
  126. class CustomTransformer(TreeForestTransformer):
  127. @handles_ambiguity
  128. def start(self, data):
  129. for tree in data:
  130. assert tree.data == 'ambiguous' or tree.data == 'full'
  131. def ambiguous(self, data):
  132. visited_ambiguous[0] = True
  133. assert len(data) == 3
  134. assert data[0].data == 'ab'
  135. assert data[1].data == 'bc'
  136. assert data[2].data == 'cd'
  137. return self.tree_class('ambiguous', data)
  138. def full(self, data):
  139. visited_full[0] = True
  140. assert len(data) == 1
  141. assert data[0].data == 'abcd'
  142. return self.tree_class('full', data)
  143. grammar = """
  144. start: ab bc cd -> ambiguous
  145. | abcd -> full
  146. !ab: "A" "B"?
  147. !bc: "B"? "C"?
  148. !cd: "C"? "D"
  149. !abcd: "ABCD"
  150. """
  151. l = Lark(grammar, parser='earley', ambiguity='forest')
  152. forest = l.parse('ABCD')
  153. tree = CustomTransformer(resolve_ambiguity=False).transform(forest)
  154. self.assertTrue(visited_ambiguous[0])
  155. self.assertTrue(visited_full[0])
  156. def test_transformation(self):
  157. class CustomTransformer(TreeForestTransformer):
  158. def __default__(self, name, data):
  159. result = []
  160. for item in data:
  161. if isinstance(item, list):
  162. result += item
  163. else:
  164. result.append(item)
  165. return result
  166. def __default_token__(self, node):
  167. return node.lower()
  168. def __default_ambig__(self, name, data):
  169. return data[0]
  170. result = CustomTransformer(resolve_ambiguity=False).transform(self.forest)
  171. expected = ['a', 'b', 'c', 'd']
  172. self.assertEqual(result, expected)
  173. if __name__ == '__main__':
  174. unittest.main()