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.

1705 lines
58 KiB

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