Skip to content

Commit d6dae10

Browse files
committed
Bugfix Earley: handle general ambiguity from ignored tokens
1 parent 0bab6be commit d6dae10

2 files changed

Lines changed: 24 additions & 7 deletions

File tree

lark/parsers/xearley.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,15 @@ def scan(i, to_scan):
109109
token_node = TokenNode(token, terminals[token.type])
110110
new_item.node = node_cache[label] if label in node_cache else node_cache.setdefault(label, self.SymbolNode(*label))
111111
new_item.node.add_family(new_item.s, item.rule, new_item.start, item.node, token_node)
112-
elif item.is_complete and item.s == start_symbol:
113-
# Handle completed start symbols
112+
else:
113+
# Handle items carried over due to ignores
114114
new_item = Item(item.rule, item.ptr, item.start)
115115
label = (new_item.s, new_item.start, i + 1)
116116
new_item.node = node_cache[label] if label in node_cache else node_cache.setdefault(label, self.SymbolNode(*label))
117-
# new_item.node and item.node both represent the start symbol, so merge their children
118-
for child in item.node.children:
119-
new_item.node.add_family(new_item.s, child.rule, new_item.start, child.left, child.right)
120-
else:
121-
new_item = item
117+
if item.node:
118+
# new_item.node and item.node both represent the same symbol, so merge their children
119+
for child in item.node.children:
120+
new_item.node.add_family(new_item.s, child.rule, new_item.start, child.left, child.right)
122121

123122
if new_item.expect in self.TERMINALS:
124123
# add (B ::= Aai+1.B, h, y) to Q'

tests/test_parser.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,24 @@ def test_ambiguous_intermediate_node_conditionally_inlined_rule(self):
784784
self.assertEqual(ambig_tree.data, '_ambig')
785785
self.assertEqual(set(ambig_tree.children), expected)
786786

787+
@unittest.skipIf(LEXER=='basic', 'This ambiguity only occurs with the dynamic lexers')
788+
def test_ambiguous_ignores(self):
789+
grammar = """
790+
!start: a "b"
791+
!a: "a" | "a1" | "a12"
792+
%ignore "1"
793+
%ignore "2"
794+
"""
795+
796+
l = Lark(grammar, ambiguity='explicit', lexer=LEXER)
797+
tree = l.parse('a12b')
798+
799+
expected = Tree('_ambig', [
800+
Tree('start', [Tree('a', ['a']), 'b']),
801+
Tree('start', [Tree('a', ['a1']), 'b']),
802+
Tree('start', [Tree('a', ['a12']), 'b']),
803+
])
804+
self.assertEqual(tree, expected)
787805

788806
@unittest.skipIf(LEXER=='basic', "Requires dynamic lexer")
789807
def test_fruitflies_ambig(self):

0 commit comments

Comments
 (0)