diff --git a/lark/parsers/xearley.py b/lark/parsers/xearley.py index f334ed199..a015bb492 100644 --- a/lark/parsers/xearley.py +++ b/lark/parsers/xearley.py @@ -112,10 +112,10 @@ def scan(i, to_scan): else: # Handle items carried over due to ignores new_item = Item(item.rule, item.ptr, item.start) - label = (new_item.s, new_item.start, i + 1) - new_item.node = node_cache[label] if label in node_cache else node_cache.setdefault(label, self.SymbolNode(*label)) - if item.node: + if item.node is not None: # new_item.node and item.node both represent the same symbol, so merge their children + label = (new_item.s, new_item.start, i + 1) + new_item.node = node_cache[label] if label in node_cache else node_cache.setdefault(label, self.SymbolNode(*label)) for child in item.node.children: new_item.node.add_family(new_item.s, child.rule, new_item.start, child.left, child.right) diff --git a/tests/test_parser.py b/tests/test_parser.py index 533ae7890..721e8693a 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -905,6 +905,21 @@ def test_multiple_start_solutions(self): tree = l.parse('x') assert tree == Tree('start', [Tree('a', ['x'])]) + @unittest.skipIf(LEXER=='basic', 'Ignore carry-over is dynamic-lexer-specific') + def test_ignore_carryover_with_priority(self): + """Items in to_scan with item.node=None must not produce an empty SPPF + node when carried over past an ignored sequence (issue #1598).""" + grammar = r""" + start: a + a.1: NAME + NAME: /[a-z]+/ + %import common.WS + %ignore WS + """ + l = Lark(grammar, parser='earley', lexer=LEXER) + tree = l.parse(' hello') + self.assertEqual(tree, Tree('start', [Tree('a', ['hello'])])) + @unittest.skipIf(LEXER=='basic', 'This scenario only occurs with the dynamic lexers') def test_multiple_start_solutions2(self): grammar = r"""