This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

255 lignes
7.7 KiB

  1. from __future__ import absolute_import
  2. import sys
  3. from unittest import TestCase, main
  4. from lark import Lark, Token, Tree, ParseError, UnexpectedInput
  5. from lark.load_grammar import GrammarError, GRAMMAR_ERRORS, find_grammar_errors
  6. from lark.load_grammar import FromPackageLoader
  7. class TestGrammar(TestCase):
  8. def setUp(self):
  9. pass
  10. def test_errors(self):
  11. for msg, examples in GRAMMAR_ERRORS:
  12. for example in examples:
  13. try:
  14. p = Lark(example)
  15. except GrammarError as e:
  16. assert msg in str(e)
  17. else:
  18. assert False, "example did not raise an error"
  19. def test_empty_literal(self):
  20. # Issues #888
  21. self.assertRaises(GrammarError, Lark, "start: \"\"")
  22. def test_override_rule(self):
  23. # Overrides the 'sep' template in existing grammar to add an optional terminating delimiter
  24. # Thus extending it beyond its original capacity
  25. p = Lark("""
  26. %import .test_templates_import (start, sep)
  27. %override sep{item, delim}: item (delim item)* delim?
  28. %ignore " "
  29. """, source_path=__file__)
  30. a = p.parse('[1, 2, 3]')
  31. b = p.parse('[1, 2, 3, ]')
  32. assert a == b
  33. self.assertRaises(GrammarError, Lark, """
  34. %import .test_templates_import (start, sep)
  35. %override sep{item}: item (delim item)* delim?
  36. """, source_path=__file__)
  37. self.assertRaises(GrammarError, Lark, """
  38. %override sep{item}: item (delim item)* delim?
  39. """, source_path=__file__)
  40. def test_override_terminal(self):
  41. p = Lark("""
  42. %import .grammars.ab (startab, A, B)
  43. %override A: "c"
  44. %override B: "d"
  45. """, start='startab', source_path=__file__)
  46. a = p.parse('cd')
  47. self.assertEqual(a.children[0].children, [Token('A', 'c'), Token('B', 'd')])
  48. def test_extend_rule(self):
  49. p = Lark("""
  50. %import .grammars.ab (startab, A, B, expr)
  51. %extend expr: B A
  52. """, start='startab', source_path=__file__)
  53. a = p.parse('abab')
  54. self.assertEqual(a.children[0].children, ['a', Tree('expr', ['b', 'a']), 'b'])
  55. self.assertRaises(GrammarError, Lark, """
  56. %extend expr: B A
  57. """)
  58. def test_extend_term(self):
  59. p = Lark("""
  60. %import .grammars.ab (startab, A, B, expr)
  61. %extend A: "c"
  62. """, start='startab', source_path=__file__)
  63. a = p.parse('acbb')
  64. self.assertEqual(a.children[0].children, ['a', Tree('expr', ['c', 'b']), 'b'])
  65. def test_extend_twice(self):
  66. p = Lark("""
  67. start: x+
  68. x: "a"
  69. %extend x: "b"
  70. %extend x: "c"
  71. """)
  72. assert p.parse("abccbba") == p.parse("cbabbbb")
  73. def test_undefined_ignore(self):
  74. g = """!start: "A"
  75. %ignore B
  76. """
  77. self.assertRaises( GrammarError, Lark, g)
  78. g = """!start: "A"
  79. %ignore start
  80. """
  81. self.assertRaises( GrammarError, Lark, g)
  82. def test_alias_in_terminal(self):
  83. g = """start: TERM
  84. TERM: "a" -> alias
  85. """
  86. self.assertRaises( GrammarError, Lark, g)
  87. def test_undefined_rule(self):
  88. self.assertRaises(GrammarError, Lark, """start: a""")
  89. def test_undefined_term(self):
  90. self.assertRaises(GrammarError, Lark, """start: A""")
  91. def test_token_multiline_only_works_with_x_flag(self):
  92. g = r"""start: ABC
  93. ABC: / a b c
  94. d
  95. e f
  96. /i
  97. """
  98. self.assertRaises( GrammarError, Lark, g)
  99. def test_import_custom_sources(self):
  100. custom_loader = FromPackageLoader('tests', ('grammars', ))
  101. grammar = """
  102. start: startab
  103. %import ab.startab
  104. """
  105. p = Lark(grammar, import_paths=[custom_loader])
  106. self.assertEqual(p.parse('ab'),
  107. Tree('start', [Tree('startab', [Tree('ab__expr', [Token('ab__A', 'a'), Token('ab__B', 'b')])])]))
  108. def test_import_custom_sources2(self):
  109. custom_loader = FromPackageLoader('tests', ('grammars', ))
  110. grammar = """
  111. start: rule_to_import
  112. %import test_relative_import_of_nested_grammar__grammar_to_import.rule_to_import
  113. """
  114. p = Lark(grammar, import_paths=[custom_loader])
  115. x = p.parse('N')
  116. self.assertEqual(next(x.find_data('rule_to_import')).children, ['N'])
  117. def test_import_custom_sources3(self):
  118. custom_loader2 = FromPackageLoader('tests')
  119. grammar = """
  120. %import .test_relative_import (start, WS)
  121. %ignore WS
  122. """
  123. p = Lark(grammar, import_paths=[custom_loader2], source_path=__file__) # import relative to current file
  124. x = p.parse('12 capybaras')
  125. self.assertEqual(x.children, ['12', 'capybaras'])
  126. def test_find_grammar_errors(self):
  127. text = """
  128. a: rule
  129. b rule
  130. c: rule
  131. B.: "hello" f
  132. D: "okay"
  133. """
  134. assert [e.line for e, _s in find_grammar_errors(text)] == [3, 5]
  135. text = """
  136. a: rule
  137. b rule
  138. | ok
  139. c: rule
  140. B.: "hello" f
  141. D: "okay"
  142. """
  143. assert [e.line for e, _s in find_grammar_errors(text)] == [3, 4, 6]
  144. text = """
  145. a: rule @#$#@$@&&
  146. b: rule
  147. | ok
  148. c: rule
  149. B: "hello" f @
  150. D: "okay"
  151. """
  152. x = find_grammar_errors(text)
  153. assert [e.line for e, _s in find_grammar_errors(text)] == [2, 6]
  154. def test_ranged_repeat_terms(self):
  155. g = u"""!start: AAA
  156. AAA: "A"~3
  157. """
  158. l = Lark(g, parser='lalr')
  159. self.assertEqual(l.parse(u'AAA'), Tree('start', ["AAA"]))
  160. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AA')
  161. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAAA')
  162. g = u"""!start: AABB CC
  163. AABB: "A"~0..2 "B"~2
  164. CC: "C"~1..2
  165. """
  166. l = Lark(g, parser='lalr')
  167. self.assertEqual(l.parse(u'AABBCC'), Tree('start', ['AABB', 'CC']))
  168. self.assertEqual(l.parse(u'BBC'), Tree('start', ['BB', 'C']))
  169. self.assertEqual(l.parse(u'ABBCC'), Tree('start', ['ABB', 'CC']))
  170. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAAB')
  171. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAABBB')
  172. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'ABB')
  173. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAAABB')
  174. def test_ranged_repeat_large(self):
  175. g = u"""!start: "A"~60
  176. """
  177. l = Lark(g, parser='lalr')
  178. self.assertGreater(len(l.rules), 1, "Expected that more than one rule will be generated")
  179. self.assertEqual(l.parse(u'A' * 60), Tree('start', ["A"] * 60))
  180. self.assertRaises(ParseError, l.parse, u'A' * 59)
  181. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'A' * 61)
  182. g = u"""!start: "A"~15..100
  183. """
  184. l = Lark(g, parser='lalr')
  185. for i in range(0, 110):
  186. if 15 <= i <= 100:
  187. self.assertEqual(l.parse(u'A' * i), Tree('start', ['A']*i))
  188. else:
  189. self.assertRaises(UnexpectedInput, l.parse, u'A' * i)
  190. # 8191 is a Mersenne prime
  191. g = u"""start: "A"~8191
  192. """
  193. l = Lark(g, parser='lalr')
  194. self.assertEqual(l.parse(u'A' * 8191), Tree('start', []))
  195. self.assertRaises(UnexpectedInput, l.parse, u'A' * 8190)
  196. self.assertRaises(UnexpectedInput, l.parse, u'A' * 8192)
  197. if __name__ == '__main__':
  198. main()