This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

229 Zeilen
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()