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.

1518 lines
52 KiB

  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import
  3. import unittest
  4. import logging
  5. import os
  6. import sys
  7. try:
  8. from cStringIO import StringIO as cStringIO
  9. except ImportError:
  10. # Available only in Python 2.x, 3.x only has io.StringIO from below
  11. cStringIO = None
  12. from io import (
  13. StringIO as uStringIO,
  14. open,
  15. )
  16. logging.basicConfig(level=logging.INFO)
  17. from lark.lark import Lark
  18. from lark.exceptions import GrammarError, ParseError, UnexpectedToken, UnexpectedInput, UnexpectedCharacters
  19. from lark.tree import Tree
  20. from lark.visitors import Transformer, Transformer_InPlace, v_args
  21. from lark.grammar import Rule
  22. from lark.lexer import TerminalDef
  23. __path__ = os.path.dirname(__file__)
  24. def _read(n, *args):
  25. with open(os.path.join(__path__, n), *args) as f:
  26. return f.read()
  27. class TestParsers(unittest.TestCase):
  28. def test_same_ast(self):
  29. "Tests that Earley and LALR parsers produce equal trees"
  30. g = Lark(r"""start: "(" name_list ("," "*" NAME)? ")"
  31. name_list: NAME | name_list "," NAME
  32. NAME: /\w+/ """, parser='lalr')
  33. l = g.parse('(a,b,c,*x)')
  34. g = Lark(r"""start: "(" name_list ("," "*" NAME)? ")"
  35. name_list: NAME | name_list "," NAME
  36. NAME: /\w/+ """)
  37. l2 = g.parse('(a,b,c,*x)')
  38. assert l == l2, '%s != %s' % (l.pretty(), l2.pretty())
  39. def test_infinite_recurse(self):
  40. g = """start: a
  41. a: a | "a"
  42. """
  43. self.assertRaises(GrammarError, Lark, g, parser='lalr')
  44. # TODO: should it? shouldn't it?
  45. # l = Lark(g, parser='earley', lexer='dynamic')
  46. # self.assertRaises(ParseError, l.parse, 'a')
  47. def test_propagate_positions(self):
  48. g = Lark("""start: a
  49. a: "a"
  50. """, propagate_positions=True)
  51. r = g.parse('a')
  52. self.assertEqual( r.children[0].meta.line, 1 )
  53. def test_expand1(self):
  54. g = Lark("""start: a
  55. ?a: b
  56. b: "x"
  57. """)
  58. r = g.parse('x')
  59. self.assertEqual( r.children[0].data, "b" )
  60. g = Lark("""start: a
  61. ?a: b -> c
  62. b: "x"
  63. """)
  64. r = g.parse('x')
  65. self.assertEqual( r.children[0].data, "c" )
  66. g = Lark("""start: a
  67. ?a: B -> c
  68. B: "x"
  69. """)
  70. self.assertEqual( r.children[0].data, "c" )
  71. g = Lark("""start: a
  72. ?a: b b -> c
  73. b: "x"
  74. """)
  75. r = g.parse('xx')
  76. self.assertEqual( r.children[0].data, "c" )
  77. def test_embedded_transformer(self):
  78. class T(Transformer):
  79. def a(self, children):
  80. return "<a>"
  81. def b(self, children):
  82. return "<b>"
  83. def c(self, children):
  84. return "<c>"
  85. # Test regular
  86. g = Lark("""start: a
  87. a : "x"
  88. """, parser='lalr')
  89. r = T().transform(g.parse("x"))
  90. self.assertEqual( r.children, ["<a>"] )
  91. g = Lark("""start: a
  92. a : "x"
  93. """, parser='lalr', transformer=T())
  94. r = g.parse("x")
  95. self.assertEqual( r.children, ["<a>"] )
  96. # Test Expand1
  97. g = Lark("""start: a
  98. ?a : b
  99. b : "x"
  100. """, parser='lalr')
  101. r = T().transform(g.parse("x"))
  102. self.assertEqual( r.children, ["<b>"] )
  103. g = Lark("""start: a
  104. ?a : b
  105. b : "x"
  106. """, parser='lalr', transformer=T())
  107. r = g.parse("x")
  108. self.assertEqual( r.children, ["<b>"] )
  109. # Test Expand1 -> Alias
  110. g = Lark("""start: a
  111. ?a : b b -> c
  112. b : "x"
  113. """, parser='lalr')
  114. r = T().transform(g.parse("xx"))
  115. self.assertEqual( r.children, ["<c>"] )
  116. g = Lark("""start: a
  117. ?a : b b -> c
  118. b : "x"
  119. """, parser='lalr', transformer=T())
  120. r = g.parse("xx")
  121. self.assertEqual( r.children, ["<c>"] )
  122. def test_embedded_transformer_inplace(self):
  123. class T1(Transformer_InPlace):
  124. def a(self, tree):
  125. assert isinstance(tree, Tree)
  126. tree.children.append("tested")
  127. @v_args(tree=True)
  128. class T2(Transformer):
  129. def a(self, tree):
  130. assert isinstance(tree, Tree)
  131. tree.children.append("tested")
  132. class T3(Transformer):
  133. @v_args(tree=True)
  134. def a(self, tree):
  135. assert isinstance(tree, Tree)
  136. tree.children.append("tested")
  137. for t in [T1(), T2(), T3()]:
  138. g = Lark("""start: a
  139. a : "x"
  140. """, parser='lalr', transformer=t)
  141. r = g.parse("x")
  142. first, = r.children
  143. self.assertEqual(first.children, ["tested"])
  144. def test_alias(self):
  145. Lark("""start: ["a"] "b" ["c"] "e" ["f"] ["g"] ["h"] "x" -> d """)
  146. def _make_full_earley_test(LEXER):
  147. def _Lark(grammar, **kwargs):
  148. return Lark(grammar, lexer=LEXER, parser='earley', propagate_positions=True, **kwargs)
  149. class _TestFullEarley(unittest.TestCase):
  150. def test_anon(self):
  151. # Fails an Earley implementation without special handling for empty rules,
  152. # or re-processing of already completed rules.
  153. g = Lark(r"""start: B
  154. B: ("ab"|/[^b]/)+
  155. """, lexer=LEXER)
  156. self.assertEqual( g.parse('abc').children[0], 'abc')
  157. def test_earley(self):
  158. g = Lark("""start: A "b" c
  159. A: "a"+
  160. c: "abc"
  161. """, parser="earley", lexer=LEXER)
  162. x = g.parse('aaaababc')
  163. def test_earley2(self):
  164. grammar = """
  165. start: statement+
  166. statement: "r"
  167. | "c" /[a-z]/+
  168. %ignore " "
  169. """
  170. program = """c b r"""
  171. l = Lark(grammar, parser='earley', lexer=LEXER)
  172. l.parse(program)
  173. @unittest.skipIf(LEXER=='dynamic', "Only relevant for the dynamic_complete parser")
  174. def test_earley3(self):
  175. """Tests prioritization and disambiguation for pseudo-terminals (there should be only one result)
  176. By default, `+` should immitate regexp greedy-matching
  177. """
  178. grammar = """
  179. start: A A
  180. A: "a"+
  181. """
  182. l = Lark(grammar, parser='earley', lexer=LEXER)
  183. res = l.parse("aaa")
  184. self.assertEqual(set(res.children), {'aa', 'a'})
  185. # XXX TODO fix Earley to maintain correct order
  186. # i.e. terminals it imitate greedy search for terminals, but lazy search for rules
  187. # self.assertEqual(res.children, ['aa', 'a'])
  188. def test_earley4(self):
  189. grammar = """
  190. start: A A?
  191. A: "a"+
  192. """
  193. l = Lark(grammar, parser='earley', lexer=LEXER)
  194. res = l.parse("aaa")
  195. assert set(res.children) == {'aa', 'a'} or res.children == ['aaa']
  196. # XXX TODO fix Earley to maintain correct order
  197. # i.e. terminals it imitate greedy search for terminals, but lazy search for rules
  198. # self.assertEqual(res.children, ['aaa'])
  199. def test_earley_repeating_empty(self):
  200. # This was a sneaky bug!
  201. grammar = """
  202. !start: "a" empty empty "b"
  203. empty: empty2
  204. empty2:
  205. """
  206. parser = Lark(grammar, parser='earley', lexer=LEXER)
  207. res = parser.parse('ab')
  208. empty_tree = Tree('empty', [Tree('empty2', [])])
  209. self.assertSequenceEqual(res.children, ['a', empty_tree, empty_tree, 'b'])
  210. @unittest.skipIf(LEXER=='standard', "Requires dynamic lexer")
  211. def test_earley_explicit_ambiguity(self):
  212. # This was a sneaky bug!
  213. grammar = """
  214. start: a b | ab
  215. a: "a"
  216. b: "b"
  217. ab: "ab"
  218. """
  219. parser = Lark(grammar, parser='earley', lexer=LEXER, ambiguity='explicit')
  220. ambig_tree = parser.parse('ab')
  221. self.assertEqual( ambig_tree.data, '_ambig')
  222. self.assertEqual( len(ambig_tree.children), 2)
  223. @unittest.skipIf(LEXER=='standard', "Requires dynamic lexer")
  224. def test_ambiguity1(self):
  225. grammar = """
  226. start: cd+ "e"
  227. !cd: "c"
  228. | "d"
  229. | "cd"
  230. """
  231. l = Lark(grammar, parser='earley', ambiguity='explicit', lexer=LEXER)
  232. ambig_tree = l.parse('cde')
  233. assert ambig_tree.data == '_ambig', ambig_tree
  234. assert len(ambig_tree.children) == 2
  235. @unittest.skipIf(LEXER=='standard', "Requires dynamic lexer")
  236. def test_ambiguity2(self):
  237. grammar = """
  238. ANY: /[a-zA-Z0-9 ]+/
  239. a.2: "A" b+
  240. b.2: "B"
  241. c: ANY
  242. start: (a|c)*
  243. """
  244. l = Lark(grammar, parser='earley', lexer=LEXER)
  245. res = l.parse('ABX')
  246. expected = Tree('start', [
  247. Tree('a', [
  248. Tree('b', [])
  249. ]),
  250. Tree('c', [
  251. 'X'
  252. ])
  253. ])
  254. self.assertEqual(res, expected)
  255. def test_fruitflies_ambig(self):
  256. grammar = """
  257. start: noun verb noun -> simple
  258. | noun verb "like" noun -> comparative
  259. noun: adj? NOUN
  260. verb: VERB
  261. adj: ADJ
  262. NOUN: "flies" | "bananas" | "fruit"
  263. VERB: "like" | "flies"
  264. ADJ: "fruit"
  265. %import common.WS
  266. %ignore WS
  267. """
  268. parser = Lark(grammar, ambiguity='explicit', lexer=LEXER)
  269. tree = parser.parse('fruit flies like bananas')
  270. expected = Tree('_ambig', [
  271. Tree('comparative', [
  272. Tree('noun', ['fruit']),
  273. Tree('verb', ['flies']),
  274. Tree('noun', ['bananas'])
  275. ]),
  276. Tree('simple', [
  277. Tree('noun', [Tree('adj', ['fruit']), 'flies']),
  278. Tree('verb', ['like']),
  279. Tree('noun', ['bananas'])
  280. ])
  281. ])
  282. # self.assertEqual(tree, expected)
  283. self.assertEqual(tree.data, expected.data)
  284. self.assertEqual(set(tree.children), set(expected.children))
  285. @unittest.skipIf(LEXER!='dynamic_complete', "Only relevant for the dynamic_complete parser")
  286. def test_explicit_ambiguity2(self):
  287. grammar = r"""
  288. start: NAME+
  289. NAME: /\w+/
  290. %ignore " "
  291. """
  292. text = """cat"""
  293. parser = _Lark(grammar, start='start', ambiguity='explicit')
  294. tree = parser.parse(text)
  295. self.assertEqual(tree.data, '_ambig')
  296. combinations = {tuple(str(s) for s in t.children) for t in tree.children}
  297. self.assertEqual(combinations, {
  298. ('cat',),
  299. ('ca', 't'),
  300. ('c', 'at'),
  301. ('c', 'a' ,'t')
  302. })
  303. def test_term_ambig_resolve(self):
  304. grammar = r"""
  305. !start: NAME+
  306. NAME: /\w+/
  307. %ignore " "
  308. """
  309. text = """foo bar"""
  310. parser = Lark(grammar)
  311. tree = parser.parse(text)
  312. self.assertEqual(tree.children, ['foo', 'bar'])
  313. # @unittest.skipIf(LEXER=='dynamic', "Not implemented in Dynamic Earley yet") # TODO
  314. # def test_not_all_derivations(self):
  315. # grammar = """
  316. # start: cd+ "e"
  317. # !cd: "c"
  318. # | "d"
  319. # | "cd"
  320. # """
  321. # l = Lark(grammar, parser='earley', ambiguity='explicit', lexer=LEXER, earley__all_derivations=False)
  322. # x = l.parse('cde')
  323. # assert x.data != '_ambig', x
  324. # assert len(x.children) == 1
  325. _NAME = "TestFullEarley" + LEXER.capitalize()
  326. _TestFullEarley.__name__ = _NAME
  327. globals()[_NAME] = _TestFullEarley
  328. def _make_parser_test(LEXER, PARSER):
  329. def _Lark(grammar, **kwargs):
  330. return Lark(grammar, lexer=LEXER, parser=PARSER, propagate_positions=True, **kwargs)
  331. def _Lark_open(gfilename, **kwargs):
  332. return Lark.open(gfilename, lexer=LEXER, parser=PARSER, propagate_positions=True, **kwargs)
  333. class _TestParser(unittest.TestCase):
  334. def test_basic1(self):
  335. g = _Lark("""start: a+ b a* "b" a*
  336. b: "b"
  337. a: "a"
  338. """)
  339. r = g.parse('aaabaab')
  340. self.assertEqual( ''.join(x.data for x in r.children), 'aaabaa' )
  341. r = g.parse('aaabaaba')
  342. self.assertEqual( ''.join(x.data for x in r.children), 'aaabaaa' )
  343. self.assertRaises(ParseError, g.parse, 'aaabaa')
  344. def test_basic2(self):
  345. # Multiple parsers and colliding tokens
  346. g = _Lark("""start: B A
  347. B: "12"
  348. A: "1" """)
  349. g2 = _Lark("""start: B A
  350. B: "12"
  351. A: "2" """)
  352. x = g.parse('121')
  353. assert x.data == 'start' and x.children == ['12', '1'], x
  354. x = g2.parse('122')
  355. assert x.data == 'start' and x.children == ['12', '2'], x
  356. @unittest.skipIf(cStringIO is None, "cStringIO not available")
  357. def test_stringio_bytes(self):
  358. """Verify that a Lark can be created from file-like objects other than Python's standard 'file' object"""
  359. _Lark(cStringIO(b'start: a+ b a* "b" a*\n b: "b"\n a: "a" '))
  360. def test_stringio_unicode(self):
  361. """Verify that a Lark can be created from file-like objects other than Python's standard 'file' object"""
  362. _Lark(uStringIO(u'start: a+ b a* "b" a*\n b: "b"\n a: "a" '))
  363. def test_unicode(self):
  364. g = _Lark(u"""start: UNIA UNIB UNIA
  365. UNIA: /\xa3/
  366. UNIB: /\u0101/
  367. """)
  368. g.parse(u'\xa3\u0101\u00a3')
  369. def test_unicode2(self):
  370. g = _Lark(r"""start: UNIA UNIB UNIA UNIC
  371. UNIA: /\xa3/
  372. UNIB: "a\u0101b\ "
  373. UNIC: /a?\u0101c\n/
  374. """)
  375. g.parse(u'\xa3a\u0101b\\ \u00a3\u0101c\n')
  376. def test_unicode3(self):
  377. g = _Lark(r"""start: UNIA UNIB UNIA UNIC
  378. UNIA: /\xa3/
  379. UNIB: "\u0101"
  380. UNIC: /\u0203/ /\n/
  381. """)
  382. g.parse(u'\xa3\u0101\u00a3\u0203\n')
  383. def test_hex_escape(self):
  384. g = _Lark(r"""start: A B C
  385. A: "\x01"
  386. B: /\x02/
  387. C: "\xABCD"
  388. """)
  389. g.parse('\x01\x02\xABCD')
  390. def test_unicode_literal_range_escape(self):
  391. g = _Lark(r"""start: A+
  392. A: "\u0061".."\u0063"
  393. """)
  394. g.parse('abc')
  395. def test_hex_literal_range_escape(self):
  396. g = _Lark(r"""start: A+
  397. A: "\x01".."\x03"
  398. """)
  399. g.parse('\x01\x02\x03')
  400. @unittest.skipIf(PARSER == 'cyk', "Takes forever")
  401. def test_stack_for_ebnf(self):
  402. """Verify that stack depth isn't an issue for EBNF grammars"""
  403. g = _Lark(r"""start: a+
  404. a : "a" """)
  405. g.parse("a" * (sys.getrecursionlimit()*2 ))
  406. def test_expand1_lists_with_one_item(self):
  407. g = _Lark(r"""start: list
  408. ?list: item+
  409. item : A
  410. A: "a"
  411. """)
  412. r = g.parse("a")
  413. # because 'list' is an expand-if-contains-one rule and we only provided one element it should have expanded to 'item'
  414. self.assertSequenceEqual([subtree.data for subtree in r.children], ('item',))
  415. # regardless of the amount of items: there should be only *one* child in 'start' because 'list' isn't an expand-all rule
  416. self.assertEqual(len(r.children), 1)
  417. def test_expand1_lists_with_one_item_2(self):
  418. g = _Lark(r"""start: list
  419. ?list: item+ "!"
  420. item : A
  421. A: "a"
  422. """)
  423. r = g.parse("a!")
  424. # because 'list' is an expand-if-contains-one rule and we only provided one element it should have expanded to 'item'
  425. self.assertSequenceEqual([subtree.data for subtree in r.children], ('item',))
  426. # regardless of the amount of items: there should be only *one* child in 'start' because 'list' isn't an expand-all rule
  427. self.assertEqual(len(r.children), 1)
  428. def test_dont_expand1_lists_with_multiple_items(self):
  429. g = _Lark(r"""start: list
  430. ?list: item+
  431. item : A
  432. A: "a"
  433. """)
  434. r = g.parse("aa")
  435. # because 'list' is an expand-if-contains-one rule and we've provided more than one element it should *not* have expanded
  436. self.assertSequenceEqual([subtree.data for subtree in r.children], ('list',))
  437. # regardless of the amount of items: there should be only *one* child in 'start' because 'list' isn't an expand-all rule
  438. self.assertEqual(len(r.children), 1)
  439. # Sanity check: verify that 'list' contains the two 'item's we've given it
  440. [list] = r.children
  441. self.assertSequenceEqual([item.data for item in list.children], ('item', 'item'))
  442. def test_dont_expand1_lists_with_multiple_items_2(self):
  443. g = _Lark(r"""start: list
  444. ?list: item+ "!"
  445. item : A
  446. A: "a"
  447. """)
  448. r = g.parse("aa!")
  449. # because 'list' is an expand-if-contains-one rule and we've provided more than one element it should *not* have expanded
  450. self.assertSequenceEqual([subtree.data for subtree in r.children], ('list',))
  451. # regardless of the amount of items: there should be only *one* child in 'start' because 'list' isn't an expand-all rule
  452. self.assertEqual(len(r.children), 1)
  453. # Sanity check: verify that 'list' contains the two 'item's we've given it
  454. [list] = r.children
  455. self.assertSequenceEqual([item.data for item in list.children], ('item', 'item'))
  456. @unittest.skipIf(PARSER == 'cyk', "No empty rules")
  457. def test_empty_expand1_list(self):
  458. g = _Lark(r"""start: list
  459. ?list: item*
  460. item : A
  461. A: "a"
  462. """)
  463. r = g.parse("")
  464. # because 'list' is an expand-if-contains-one rule and we've provided less than one element (i.e. none) it should *not* have expanded
  465. self.assertSequenceEqual([subtree.data for subtree in r.children], ('list',))
  466. # regardless of the amount of items: there should be only *one* child in 'start' because 'list' isn't an expand-all rule
  467. self.assertEqual(len(r.children), 1)
  468. # Sanity check: verify that 'list' contains no 'item's as we've given it none
  469. [list] = r.children
  470. self.assertSequenceEqual([item.data for item in list.children], ())
  471. @unittest.skipIf(PARSER == 'cyk', "No empty rules")
  472. def test_empty_expand1_list_2(self):
  473. g = _Lark(r"""start: list
  474. ?list: item* "!"?
  475. item : A
  476. A: "a"
  477. """)
  478. r = g.parse("")
  479. # because 'list' is an expand-if-contains-one rule and we've provided less than one element (i.e. none) it should *not* have expanded
  480. self.assertSequenceEqual([subtree.data for subtree in r.children], ('list',))
  481. # regardless of the amount of items: there should be only *one* child in 'start' because 'list' isn't an expand-all rule
  482. self.assertEqual(len(r.children), 1)
  483. # Sanity check: verify that 'list' contains no 'item's as we've given it none
  484. [list] = r.children
  485. self.assertSequenceEqual([item.data for item in list.children], ())
  486. @unittest.skipIf(PARSER == 'cyk', "No empty rules")
  487. def test_empty_flatten_list(self):
  488. g = _Lark(r"""start: list
  489. list: | item "," list
  490. item : A
  491. A: "a"
  492. """)
  493. r = g.parse("")
  494. # Because 'list' is a flatten rule it's top-level element should *never* be expanded
  495. self.assertSequenceEqual([subtree.data for subtree in r.children], ('list',))
  496. # Sanity check: verify that 'list' contains no 'item's as we've given it none
  497. [list] = r.children
  498. self.assertSequenceEqual([item.data for item in list.children], ())
  499. @unittest.skipIf(True, "Flattening list isn't implemented (and may never be)")
  500. def test_single_item_flatten_list(self):
  501. g = _Lark(r"""start: list
  502. list: | item "," list
  503. item : A
  504. A: "a"
  505. """)
  506. r = g.parse("a,")
  507. # Because 'list' is a flatten rule it's top-level element should *never* be expanded
  508. self.assertSequenceEqual([subtree.data for subtree in r.children], ('list',))
  509. # Sanity check: verify that 'list' contains exactly the one 'item' we've given it
  510. [list] = r.children
  511. self.assertSequenceEqual([item.data for item in list.children], ('item',))
  512. @unittest.skipIf(True, "Flattening list isn't implemented (and may never be)")
  513. def test_multiple_item_flatten_list(self):
  514. g = _Lark(r"""start: list
  515. #list: | item "," list
  516. item : A
  517. A: "a"
  518. """)
  519. r = g.parse("a,a,")
  520. # Because 'list' is a flatten rule it's top-level element should *never* be expanded
  521. self.assertSequenceEqual([subtree.data for subtree in r.children], ('list',))
  522. # Sanity check: verify that 'list' contains exactly the two 'item's we've given it
  523. [list] = r.children
  524. self.assertSequenceEqual([item.data for item in list.children], ('item', 'item'))
  525. @unittest.skipIf(True, "Flattening list isn't implemented (and may never be)")
  526. def test_recurse_flatten(self):
  527. """Verify that stack depth doesn't get exceeded on recursive rules marked for flattening."""
  528. g = _Lark(r"""start: a | start a
  529. a : A
  530. A : "a" """)
  531. # Force PLY to write to the debug log, but prevent writing it to the terminal (uses repr() on the half-built
  532. # STree data structures, which uses recursion).
  533. g.parse("a" * (sys.getrecursionlimit() // 4))
  534. def test_token_collision(self):
  535. g = _Lark(r"""start: "Hello" NAME
  536. NAME: /\w/+
  537. %ignore " "
  538. """)
  539. x = g.parse('Hello World')
  540. self.assertSequenceEqual(x.children, ['World'])
  541. x = g.parse('Hello HelloWorld')
  542. self.assertSequenceEqual(x.children, ['HelloWorld'])
  543. def test_token_collision_WS(self):
  544. g = _Lark(r"""start: "Hello" NAME
  545. NAME: /\w/+
  546. %import common.WS
  547. %ignore WS
  548. """)
  549. x = g.parse('Hello World')
  550. self.assertSequenceEqual(x.children, ['World'])
  551. x = g.parse('Hello HelloWorld')
  552. self.assertSequenceEqual(x.children, ['HelloWorld'])
  553. def test_token_collision2(self):
  554. g = _Lark("""
  555. !start: "starts"
  556. %import common.LCASE_LETTER
  557. """)
  558. x = g.parse("starts")
  559. self.assertSequenceEqual(x.children, ['starts'])
  560. # def test_string_priority(self):
  561. # g = _Lark("""start: (A | /a?bb/)+
  562. # A: "a" """)
  563. # x = g.parse('abb')
  564. # self.assertEqual(len(x.children), 2)
  565. # # This parse raises an exception because the lexer will always try to consume
  566. # # "a" first and will never match the regular expression
  567. # # This behavior is subject to change!!
  568. # # Thie won't happen with ambiguity handling.
  569. # g = _Lark("""start: (A | /a?ab/)+
  570. # A: "a" """)
  571. # self.assertRaises(LexError, g.parse, 'aab')
  572. def test_undefined_rule(self):
  573. self.assertRaises(GrammarError, _Lark, """start: a""")
  574. def test_undefined_token(self):
  575. self.assertRaises(GrammarError, _Lark, """start: A""")
  576. def test_rule_collision(self):
  577. g = _Lark("""start: "a"+ "b"
  578. | "a"+ """)
  579. x = g.parse('aaaa')
  580. x = g.parse('aaaab')
  581. def test_rule_collision2(self):
  582. g = _Lark("""start: "a"* "b"
  583. | "a"+ """)
  584. x = g.parse('aaaa')
  585. x = g.parse('aaaab')
  586. x = g.parse('b')
  587. def test_token_not_anon(self):
  588. """Tests that "a" is matched as an anonymous token, and not A.
  589. """
  590. g = _Lark("""start: "a"
  591. A: "a" """)
  592. x = g.parse('a')
  593. self.assertEqual(len(x.children), 0, '"a" should be considered anonymous')
  594. g = _Lark("""start: "a" A
  595. A: "a" """)
  596. x = g.parse('aa')
  597. self.assertEqual(len(x.children), 1, 'only "a" should be considered anonymous')
  598. self.assertEqual(x.children[0].type, "A")
  599. g = _Lark("""start: /a/
  600. A: /a/ """)
  601. x = g.parse('a')
  602. self.assertEqual(len(x.children), 1)
  603. self.assertEqual(x.children[0].type, "A", "A isn't associated with /a/")
  604. @unittest.skipIf(PARSER == 'cyk', "No empty rules")
  605. def test_maybe(self):
  606. g = _Lark("""start: ["a"] """)
  607. x = g.parse('a')
  608. x = g.parse('')
  609. def test_start(self):
  610. g = _Lark("""a: "a" a? """, start='a')
  611. x = g.parse('a')
  612. x = g.parse('aa')
  613. x = g.parse('aaa')
  614. def test_alias(self):
  615. g = _Lark("""start: "a" -> b """)
  616. x = g.parse('a')
  617. self.assertEqual(x.data, "b")
  618. def test_token_ebnf(self):
  619. g = _Lark("""start: A
  620. A: "a"* ("b"? "c".."e")+
  621. """)
  622. x = g.parse('abcde')
  623. x = g.parse('dd')
  624. def test_backslash(self):
  625. g = _Lark(r"""start: "\\" "a"
  626. """)
  627. x = g.parse(r'\a')
  628. g = _Lark(r"""start: /\\/ /a/
  629. """)
  630. x = g.parse(r'\a')
  631. def test_backslash2(self):
  632. g = _Lark(r"""start: "\"" "-"
  633. """)
  634. x = g.parse('"-')
  635. g = _Lark(r"""start: /\// /-/
  636. """)
  637. x = g.parse('/-')
  638. def test_special_chars(self):
  639. g = _Lark(r"""start: "\n"
  640. """)
  641. x = g.parse('\n')
  642. g = _Lark(r"""start: /\n/
  643. """)
  644. x = g.parse('\n')
  645. # def test_token_recurse(self):
  646. # g = _Lark("""start: A
  647. # A: B
  648. # B: A
  649. # """)
  650. @unittest.skipIf(PARSER == 'cyk', "No empty rules")
  651. def test_empty(self):
  652. # Fails an Earley implementation without special handling for empty rules,
  653. # or re-processing of already completed rules.
  654. g = _Lark(r"""start: _empty a "B"
  655. a: _empty "A"
  656. _empty:
  657. """)
  658. x = g.parse('AB')
  659. def test_regex_quote(self):
  660. g = r"""
  661. start: SINGLE_QUOTED_STRING | DOUBLE_QUOTED_STRING
  662. SINGLE_QUOTED_STRING : /'[^']*'/
  663. DOUBLE_QUOTED_STRING : /"[^"]*"/
  664. """
  665. g = _Lark(g)
  666. self.assertEqual( g.parse('"hello"').children, ['"hello"'])
  667. self.assertEqual( g.parse("'hello'").children, ["'hello'"])
  668. def test_lexer_token_limit(self):
  669. "Python has a stupid limit of 100 groups in a regular expression. Test that we handle this limitation"
  670. tokens = {'A%d'%i:'"%d"'%i for i in range(300)}
  671. g = _Lark("""start: %s
  672. %s""" % (' '.join(tokens), '\n'.join("%s: %s"%x for x in tokens.items())))
  673. def test_float_without_lexer(self):
  674. expected_error = UnexpectedCharacters if LEXER.startswith('dynamic') else UnexpectedToken
  675. if PARSER == 'cyk':
  676. expected_error = ParseError
  677. g = _Lark("""start: ["+"|"-"] float
  678. float: digit* "." digit+ exp?
  679. | digit+ exp
  680. exp: ("e"|"E") ["+"|"-"] digit+
  681. digit: "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
  682. """)
  683. g.parse("1.2")
  684. g.parse("-.2e9")
  685. g.parse("+2e-9")
  686. self.assertRaises( expected_error, g.parse, "+2e-9e")
  687. def test_keep_all_tokens(self):
  688. l = _Lark("""start: "a"+ """, keep_all_tokens=True)
  689. tree = l.parse('aaa')
  690. self.assertEqual(tree.children, ['a', 'a', 'a'])
  691. def test_token_flags(self):
  692. l = _Lark("""!start: "a"i+
  693. """
  694. )
  695. tree = l.parse('aA')
  696. self.assertEqual(tree.children, ['a', 'A'])
  697. l = _Lark("""!start: /a/i+
  698. """
  699. )
  700. tree = l.parse('aA')
  701. self.assertEqual(tree.children, ['a', 'A'])
  702. # g = """!start: "a"i "a"
  703. # """
  704. # self.assertRaises(GrammarError, _Lark, g)
  705. # g = """!start: /a/i /a/
  706. # """
  707. # self.assertRaises(GrammarError, _Lark, g)
  708. g = """start: NAME "," "a"
  709. NAME: /[a-z_]/i /[a-z0-9_]/i*
  710. """
  711. l = _Lark(g)
  712. tree = l.parse('ab,a')
  713. self.assertEqual(tree.children, ['ab'])
  714. tree = l.parse('AB,a')
  715. self.assertEqual(tree.children, ['AB'])
  716. def test_token_flags3(self):
  717. l = _Lark("""!start: ABC+
  718. ABC: "abc"i
  719. """
  720. )
  721. tree = l.parse('aBcAbC')
  722. self.assertEqual(tree.children, ['aBc', 'AbC'])
  723. def test_token_flags2(self):
  724. g = """!start: ("a"i | /a/ /b/?)+
  725. """
  726. l = _Lark(g)
  727. tree = l.parse('aA')
  728. self.assertEqual(tree.children, ['a', 'A'])
  729. @unittest.skipIf(PARSER == 'cyk', "No empty rules")
  730. def test_twice_empty(self):
  731. g = """!start: [["A"]]
  732. """
  733. l = _Lark(g)
  734. tree = l.parse('A')
  735. self.assertEqual(tree.children, ['A'])
  736. tree = l.parse('')
  737. self.assertEqual(tree.children, [])
  738. def test_undefined_ignore(self):
  739. g = """!start: "A"
  740. %ignore B
  741. """
  742. self.assertRaises( GrammarError, _Lark, g)
  743. def test_alias_in_terminal(self):
  744. g = """start: TERM
  745. TERM: "a" -> alias
  746. """
  747. self.assertRaises( GrammarError, _Lark, g)
  748. def test_line_and_column(self):
  749. g = r"""!start: "A" bc "D"
  750. !bc: "B\nC"
  751. """
  752. l = _Lark(g)
  753. a, bc, d = l.parse("AB\nCD").children
  754. self.assertEqual(a.line, 1)
  755. self.assertEqual(a.column, 1)
  756. bc ,= bc.children
  757. self.assertEqual(bc.line, 1)
  758. self.assertEqual(bc.column, 2)
  759. self.assertEqual(d.line, 2)
  760. self.assertEqual(d.column, 2)
  761. if LEXER != 'dynamic':
  762. self.assertEqual(a.end_line, 1)
  763. self.assertEqual(a.end_column, 2)
  764. self.assertEqual(bc.end_line, 2)
  765. self.assertEqual(bc.end_column, 2)
  766. self.assertEqual(d.end_line, 2)
  767. self.assertEqual(d.end_column, 3)
  768. def test_reduce_cycle(self):
  769. """Tests an edge-condition in the LALR parser, in which a transition state looks exactly like the end state.
  770. It seems that the correct solution is to explicitely distinguish finalization in the reduce() function.
  771. """
  772. l = _Lark("""
  773. term: A
  774. | term term
  775. A: "a"
  776. """, start='term')
  777. tree = l.parse("aa")
  778. self.assertEqual(len(tree.children), 2)
  779. @unittest.skipIf(LEXER != 'standard', "Only standard lexers care about token priority")
  780. def test_lexer_prioritization(self):
  781. "Tests effect of priority on result"
  782. grammar = """
  783. start: A B | AB
  784. A.2: "a"
  785. B: "b"
  786. AB: "ab"
  787. """
  788. l = _Lark(grammar)
  789. res = l.parse("ab")
  790. self.assertEqual(res.children, ['a', 'b'])
  791. self.assertNotEqual(res.children, ['ab'])
  792. grammar = """
  793. start: A B | AB
  794. A: "a"
  795. B: "b"
  796. AB.3: "ab"
  797. """
  798. l = _Lark(grammar)
  799. res = l.parse("ab")
  800. self.assertNotEqual(res.children, ['a', 'b'])
  801. self.assertEqual(res.children, ['ab'])
  802. def test_import(self):
  803. grammar = """
  804. start: NUMBER WORD
  805. %import common.NUMBER
  806. %import common.WORD
  807. %import common.WS
  808. %ignore WS
  809. """
  810. l = _Lark(grammar)
  811. x = l.parse('12 elephants')
  812. self.assertEqual(x.children, ['12', 'elephants'])
  813. def test_import_rename(self):
  814. grammar = """
  815. start: N W
  816. %import common.NUMBER -> N
  817. %import common.WORD -> W
  818. %import common.WS
  819. %ignore WS
  820. """
  821. l = _Lark(grammar)
  822. x = l.parse('12 elephants')
  823. self.assertEqual(x.children, ['12', 'elephants'])
  824. def test_relative_import(self):
  825. l = _Lark_open('test_relative_import.lark', rel_to=__file__)
  826. x = l.parse('12 lions')
  827. self.assertEqual(x.children, ['12', 'lions'])
  828. def test_relative_import_rename(self):
  829. l = _Lark_open('test_relative_import_rename.lark', rel_to=__file__)
  830. x = l.parse('12 lions')
  831. self.assertEqual(x.children, ['12', 'lions'])
  832. def test_relative_rule_import(self):
  833. l = _Lark_open('test_relative_rule_import.lark', rel_to=__file__)
  834. x = l.parse('xaabby')
  835. self.assertEqual(x.children, [
  836. 'x',
  837. Tree('expr', ['a', Tree('expr', ['a', 'b']), 'b']),
  838. 'y'])
  839. def test_relative_rule_import_drop_ignore(self):
  840. # %ignore rules are dropped on import
  841. l = _Lark_open('test_relative_rule_import_drop_ignore.lark',
  842. rel_to=__file__)
  843. self.assertRaises((ParseError, UnexpectedInput),
  844. l.parse, 'xa abby')
  845. def test_relative_rule_import_subrule(self):
  846. l = _Lark_open('test_relative_rule_import_subrule.lark',
  847. rel_to=__file__)
  848. x = l.parse('xaabby')
  849. self.assertEqual(x.children, [
  850. 'x',
  851. Tree('startab', [
  852. Tree('grammars__ab__expr', [
  853. 'a', Tree('grammars__ab__expr', ['a', 'b']), 'b',
  854. ]),
  855. ]),
  856. 'y'])
  857. def test_relative_rule_import_subrule_no_conflict(self):
  858. l = _Lark_open(
  859. 'test_relative_rule_import_subrule_no_conflict.lark',
  860. rel_to=__file__)
  861. x = l.parse('xaby')
  862. self.assertEqual(x.children, [Tree('expr', [
  863. 'x',
  864. Tree('startab', [
  865. Tree('grammars__ab__expr', ['a', 'b']),
  866. ]),
  867. 'y'])])
  868. self.assertRaises((ParseError, UnexpectedInput),
  869. l.parse, 'xaxabyby')
  870. def test_relative_rule_import_rename(self):
  871. l = _Lark_open('test_relative_rule_import_rename.lark',
  872. rel_to=__file__)
  873. x = l.parse('xaabby')
  874. self.assertEqual(x.children, [
  875. 'x',
  876. Tree('ab', ['a', Tree('ab', ['a', 'b']), 'b']),
  877. 'y'])
  878. def test_multi_import(self):
  879. grammar = """
  880. start: NUMBER WORD
  881. %import common (NUMBER, WORD, WS)
  882. %ignore WS
  883. """
  884. l = _Lark(grammar)
  885. x = l.parse('12 toucans')
  886. self.assertEqual(x.children, ['12', 'toucans'])
  887. def test_relative_multi_import(self):
  888. l = _Lark_open("test_relative_multi_import.lark", rel_to=__file__)
  889. x = l.parse('12 capybaras')
  890. self.assertEqual(x.children, ['12', 'capybaras'])
  891. def test_relative_import_preserves_leading_underscore(self):
  892. l = _Lark_open("test_relative_import_preserves_leading_underscore.lark", rel_to=__file__)
  893. x = l.parse('Ax')
  894. self.assertEqual(next(x.find_data('c')).children, ['A'])
  895. def test_relative_import_of_nested_grammar(self):
  896. l = _Lark_open("grammars/test_relative_import_of_nested_grammar.lark", rel_to=__file__)
  897. x = l.parse('N')
  898. self.assertEqual(next(x.find_data('rule_to_import')).children, ['N'])
  899. def test_relative_import_rules_dependencies_imported_only_once(self):
  900. l = _Lark_open("test_relative_import_rules_dependencies_imported_only_once.lark", rel_to=__file__)
  901. x = l.parse('AAA')
  902. self.assertEqual(next(x.find_data('a')).children, ['A'])
  903. self.assertEqual(next(x.find_data('b')).children, ['A'])
  904. self.assertEqual(next(x.find_data('d')).children, ['A'])
  905. def test_import_errors(self):
  906. grammar = """
  907. start: NUMBER WORD
  908. %import .grammars.bad_test.NUMBER
  909. """
  910. self.assertRaises(IOError, _Lark, grammar)
  911. grammar = """
  912. start: NUMBER WORD
  913. %import bad_test.NUMBER
  914. """
  915. self.assertRaises(IOError, _Lark, grammar)
  916. @unittest.skipIf(PARSER != 'earley', "Currently only Earley supports priority in rules")
  917. def test_earley_prioritization(self):
  918. "Tests effect of priority on result"
  919. grammar = """
  920. start: a | b
  921. a.1: "a"
  922. b.2: "a"
  923. """
  924. # l = Lark(grammar, parser='earley', lexer='standard')
  925. l = _Lark(grammar)
  926. res = l.parse("a")
  927. self.assertEqual(res.children[0].data, 'b')
  928. grammar = """
  929. start: a | b
  930. a.2: "a"
  931. b.1: "a"
  932. """
  933. l = _Lark(grammar)
  934. # l = Lark(grammar, parser='earley', lexer='standard')
  935. res = l.parse("a")
  936. self.assertEqual(res.children[0].data, 'a')
  937. @unittest.skipIf(PARSER != 'earley', "Currently only Earley supports priority in rules")
  938. def test_earley_prioritization_sum(self):
  939. "Tests effect of priority on result"
  940. grammar = """
  941. start: ab_ b_ a_ | indirection
  942. indirection: a_ bb_ a_
  943. a_: "a"
  944. b_: "b"
  945. ab_: "ab"
  946. bb_.1: "bb"
  947. """
  948. l = Lark(grammar, priority="invert")
  949. res = l.parse('abba')
  950. self.assertEqual(''.join(child.data for child in res.children), 'ab_b_a_')
  951. grammar = """
  952. start: ab_ b_ a_ | indirection
  953. indirection: a_ bb_ a_
  954. a_: "a"
  955. b_: "b"
  956. ab_.1: "ab"
  957. bb_: "bb"
  958. """
  959. l = Lark(grammar, priority="invert")
  960. res = l.parse('abba')
  961. self.assertEqual(''.join(child.data for child in res.children), 'indirection')
  962. grammar = """
  963. start: ab_ b_ a_ | indirection
  964. indirection: a_ bb_ a_
  965. a_.2: "a"
  966. b_.1: "b"
  967. ab_.3: "ab"
  968. bb_.3: "bb"
  969. """
  970. l = Lark(grammar, priority="invert")
  971. res = l.parse('abba')
  972. self.assertEqual(''.join(child.data for child in res.children), 'ab_b_a_')
  973. grammar = """
  974. start: ab_ b_ a_ | indirection
  975. indirection: a_ bb_ a_
  976. a_.1: "a"
  977. b_.1: "b"
  978. ab_.4: "ab"
  979. bb_.3: "bb"
  980. """
  981. l = Lark(grammar, priority="invert")
  982. res = l.parse('abba')
  983. self.assertEqual(''.join(child.data for child in res.children), 'indirection')
  984. def test_utf8(self):
  985. g = u"""start: a
  986. a: "±a"
  987. """
  988. l = _Lark(g)
  989. self.assertEqual(l.parse(u'±a'), Tree('start', [Tree('a', [])]))
  990. g = u"""start: A
  991. A: "±a"
  992. """
  993. l = _Lark(g)
  994. self.assertEqual(l.parse(u'±a'), Tree('start', [u'\xb1a']))
  995. @unittest.skipIf(PARSER == 'cyk', "No empty rules")
  996. def test_ignore(self):
  997. grammar = r"""
  998. COMMENT: /(!|(\/\/))[^\n]*/
  999. %ignore COMMENT
  1000. %import common.WS -> _WS
  1001. %import common.INT
  1002. start: "INT"i _WS+ INT _WS*
  1003. """
  1004. parser = _Lark(grammar)
  1005. tree = parser.parse("int 1 ! This is a comment\n")
  1006. self.assertEqual(tree.children, ['1'])
  1007. tree = parser.parse("int 1 ! This is a comment") # A trailing ignore token can be tricky!
  1008. self.assertEqual(tree.children, ['1'])
  1009. parser = _Lark(r"""
  1010. start : "a"*
  1011. %ignore "b"
  1012. """)
  1013. tree = parser.parse("bb")
  1014. self.assertEqual(tree.children, [])
  1015. def test_regex_escaping(self):
  1016. g = _Lark("start: /[ab]/")
  1017. g.parse('a')
  1018. g.parse('b')
  1019. self.assertRaises( UnexpectedInput, g.parse, 'c')
  1020. _Lark(r'start: /\w/').parse('a')
  1021. g = _Lark(r'start: /\\w/')
  1022. self.assertRaises( UnexpectedInput, g.parse, 'a')
  1023. g.parse(r'\w')
  1024. _Lark(r'start: /\[/').parse('[')
  1025. _Lark(r'start: /\//').parse('/')
  1026. _Lark(r'start: /\\/').parse('\\')
  1027. _Lark(r'start: /\[ab]/').parse('[ab]')
  1028. _Lark(r'start: /\\[ab]/').parse('\\a')
  1029. _Lark(r'start: /\t/').parse('\t')
  1030. _Lark(r'start: /\\t/').parse('\\t')
  1031. _Lark(r'start: /\\\t/').parse('\\\t')
  1032. _Lark(r'start: "\t"').parse('\t')
  1033. _Lark(r'start: "\\t"').parse('\\t')
  1034. _Lark(r'start: "\\\t"').parse('\\\t')
  1035. def test_ranged_repeat_rules(self):
  1036. g = u"""!start: "A"~3
  1037. """
  1038. l = _Lark(g)
  1039. self.assertEqual(l.parse(u'AAA'), Tree('start', ["A", "A", "A"]))
  1040. self.assertRaises(ParseError, l.parse, u'AA')
  1041. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAAA')
  1042. g = u"""!start: "A"~0..2
  1043. """
  1044. if PARSER != 'cyk': # XXX CYK currently doesn't support empty grammars
  1045. l = _Lark(g)
  1046. self.assertEqual(l.parse(u''), Tree('start', []))
  1047. self.assertEqual(l.parse(u'A'), Tree('start', ['A']))
  1048. self.assertEqual(l.parse(u'AA'), Tree('start', ['A', 'A']))
  1049. self.assertRaises((UnexpectedToken, UnexpectedInput), l.parse, u'AAA')
  1050. g = u"""!start: "A"~3..2
  1051. """
  1052. self.assertRaises(GrammarError, _Lark, g)
  1053. g = u"""!start: "A"~2..3 "B"~2
  1054. """
  1055. l = _Lark(g)
  1056. self.assertEqual(l.parse(u'AABB'), Tree('start', ['A', 'A', 'B', 'B']))
  1057. self.assertEqual(l.parse(u'AAABB'), Tree('start', ['A', 'A', 'A', 'B', 'B']))
  1058. self.assertRaises(ParseError, l.parse, u'AAAB')
  1059. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAABBB')
  1060. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'ABB')
  1061. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAAABB')
  1062. def test_ranged_repeat_terms(self):
  1063. g = u"""!start: AAA
  1064. AAA: "A"~3
  1065. """
  1066. l = _Lark(g)
  1067. self.assertEqual(l.parse(u'AAA'), Tree('start', ["AAA"]))
  1068. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AA')
  1069. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAAA')
  1070. g = u"""!start: AABB CC
  1071. AABB: "A"~0..2 "B"~2
  1072. CC: "C"~1..2
  1073. """
  1074. l = _Lark(g)
  1075. self.assertEqual(l.parse(u'AABBCC'), Tree('start', ['AABB', 'CC']))
  1076. self.assertEqual(l.parse(u'BBC'), Tree('start', ['BB', 'C']))
  1077. self.assertEqual(l.parse(u'ABBCC'), Tree('start', ['ABB', 'CC']))
  1078. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAAB')
  1079. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAABBB')
  1080. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'ABB')
  1081. self.assertRaises((ParseError, UnexpectedInput), l.parse, u'AAAABB')
  1082. @unittest.skipIf(PARSER=='earley', "Priority not handled correctly right now") # TODO XXX
  1083. def test_priority_vs_embedded(self):
  1084. g = """
  1085. A.2: "a"
  1086. WORD: ("a".."z")+
  1087. start: (A | WORD)+
  1088. """
  1089. l = _Lark(g)
  1090. t = l.parse('abc')
  1091. self.assertEqual(t.children, ['a', 'bc'])
  1092. self.assertEqual(t.children[0].type, 'A')
  1093. def test_line_counting(self):
  1094. p = _Lark("start: /[^x]+/")
  1095. text = 'hello\nworld'
  1096. t = p.parse(text)
  1097. tok = t.children[0]
  1098. self.assertEqual(tok, text)
  1099. self.assertEqual(tok.line, 1)
  1100. self.assertEqual(tok.column, 1)
  1101. if _LEXER != 'dynamic':
  1102. self.assertEqual(tok.end_line, 2)
  1103. self.assertEqual(tok.end_column, 6)
  1104. @unittest.skipIf(PARSER=='cyk', "Empty rules")
  1105. def test_empty_end(self):
  1106. p = _Lark("""
  1107. start: b c d
  1108. b: "B"
  1109. c: | "C"
  1110. d: | "D"
  1111. """)
  1112. res = p.parse('B')
  1113. self.assertEqual(len(res.children), 3)
  1114. @unittest.skipIf(PARSER=='cyk', "Empty rules")
  1115. def test_maybe_placeholders(self):
  1116. # Anonymous tokens shouldn't count
  1117. p = _Lark("""start: ["a"] ["b"] ["c"] """, maybe_placeholders=True)
  1118. self.assertEqual(p.parse("").children, [])
  1119. # All invisible constructs shouldn't count
  1120. p = _Lark("""start: [A] ["b"] [_c] ["e" "f" _c]
  1121. A: "a"
  1122. _c: "c" """, maybe_placeholders=True)
  1123. self.assertEqual(p.parse("").children, [None])
  1124. self.assertEqual(p.parse("c").children, [None])
  1125. self.assertEqual(p.parse("aefc").children, ['a'])
  1126. # ? shouldn't apply
  1127. p = _Lark("""!start: ["a"] "b"? ["c"] """, maybe_placeholders=True)
  1128. self.assertEqual(p.parse("").children, [None, None])
  1129. self.assertEqual(p.parse("b").children, [None, 'b', None])
  1130. p = _Lark("""!start: ["a"] ["b"] ["c"] """, maybe_placeholders=True)
  1131. self.assertEqual(p.parse("").children, [None, None, None])
  1132. self.assertEqual(p.parse("a").children, ['a', None, None])
  1133. self.assertEqual(p.parse("b").children, [None, 'b', None])
  1134. self.assertEqual(p.parse("c").children, [None, None, 'c'])
  1135. self.assertEqual(p.parse("ab").children, ['a', 'b', None])
  1136. self.assertEqual(p.parse("ac").children, ['a', None, 'c'])
  1137. self.assertEqual(p.parse("bc").children, [None, 'b', 'c'])
  1138. self.assertEqual(p.parse("abc").children, ['a', 'b', 'c'])
  1139. p = _Lark("""!start: (["a"] "b" ["c"])+ """, maybe_placeholders=True)
  1140. self.assertEqual(p.parse("b").children, [None, 'b', None])
  1141. self.assertEqual(p.parse("bb").children, [None, 'b', None, None, 'b', None])
  1142. self.assertEqual(p.parse("abbc").children, ['a', 'b', None, None, 'b', 'c'])
  1143. self.assertEqual(p.parse("babbcabcb").children,
  1144. [None, 'b', None,
  1145. 'a', 'b', None,
  1146. None, 'b', 'c',
  1147. 'a', 'b', 'c',
  1148. None, 'b', None])
  1149. p = _Lark("""!start: ["a"] ["c"] "b"+ ["a"] ["d"] """, maybe_placeholders=True)
  1150. self.assertEqual(p.parse("bb").children, [None, None, 'b', 'b', None, None])
  1151. self.assertEqual(p.parse("bd").children, [None, None, 'b', None, 'd'])
  1152. self.assertEqual(p.parse("abba").children, ['a', None, 'b', 'b', 'a', None])
  1153. self.assertEqual(p.parse("cbbbb").children, [None, 'c', 'b', 'b', 'b', 'b', None, None])
  1154. def test_escaped_string(self):
  1155. "Tests common.ESCAPED_STRING"
  1156. grammar = r"""
  1157. start: ESCAPED_STRING+
  1158. %import common (WS_INLINE, ESCAPED_STRING)
  1159. %ignore WS_INLINE
  1160. """
  1161. parser = _Lark(grammar)
  1162. parser.parse(r'"\\" "b" "c"')
  1163. parser.parse(r'"That" "And a \"b"')
  1164. @unittest.skipIf(PARSER!='lalr', "Serialize currently only works for LALR parsers (though it should be easy to extend)")
  1165. def test_serialize(self):
  1166. grammar = """
  1167. start: _ANY b "C"
  1168. _ANY: /./
  1169. b: "B"
  1170. """
  1171. parser = _Lark(grammar)
  1172. d = parser.serialize()
  1173. parser2 = Lark.deserialize(d, {}, {})
  1174. self.assertEqual(parser2.parse('ABC'), Tree('start', [Tree('b', [])]) )
  1175. namespace = {'Rule': Rule, 'TerminalDef': TerminalDef}
  1176. d, m = parser.memo_serialize(namespace.values())
  1177. parser3 = Lark.deserialize(d, namespace, m)
  1178. self.assertEqual(parser3.parse('ABC'), Tree('start', [Tree('b', [])]) )
  1179. _NAME = "Test" + PARSER.capitalize() + LEXER.capitalize()
  1180. _TestParser.__name__ = _NAME
  1181. globals()[_NAME] = _TestParser
  1182. # Note: You still have to import them in __main__ for the tests to run
  1183. _TO_TEST = [
  1184. ('standard', 'earley'),
  1185. ('standard', 'cyk'),
  1186. ('dynamic', 'earley'),
  1187. ('dynamic_complete', 'earley'),
  1188. ('standard', 'lalr'),
  1189. ('contextual', 'lalr'),
  1190. # (None, 'earley'),
  1191. ]
  1192. for _LEXER, _PARSER in _TO_TEST:
  1193. _make_parser_test(_LEXER, _PARSER)
  1194. for _LEXER in ('dynamic', 'dynamic_complete'):
  1195. _make_full_earley_test(_LEXER)
  1196. if __name__ == '__main__':
  1197. unittest.main()