Skip to content

Commit 0bab6be

Browse files
committed
Bugfix Earley: handle ambiguity from strings ending in ignored tokens
1 parent 52ef09d commit 0bab6be

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

lark/parsers/xearley.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from ..lexer import Token
2323
from ..grammar import Terminal
2424
from .earley import Parser as BaseParser
25+
from .earley_common import Item
2526
from .earley_forest import TokenNode
2627

2728
if TYPE_CHECKING:
@@ -108,6 +109,14 @@ def scan(i, to_scan):
108109
token_node = TokenNode(token, terminals[token.type])
109110
new_item.node = node_cache[label] if label in node_cache else node_cache.setdefault(label, self.SymbolNode(*label))
110111
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
114+
new_item = Item(item.rule, item.ptr, item.start)
115+
label = (new_item.s, new_item.start, i + 1)
116+
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)
111120
else:
112121
new_item = item
113122

tests/test_parser.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,26 @@ def test_multiple_start_solutions(self):
876876
tree = l.parse('x')
877877
assert tree == Tree('start', [Tree('a', ['x'])])
878878

879+
@unittest.skipIf(LEXER=='basic', 'This scenario only occurs with the dynamic lexers')
880+
def test_multiple_start_solutions2(self):
881+
grammar = r"""
882+
!start: "foo1" | "foo" | "foo12"
883+
%ignore "1"
884+
%ignore "2"
885+
"""
886+
l = Lark(grammar, ambiguity='explicit', lexer=LEXER)
887+
tree = l.parse('foo12')
888+
889+
expected = Tree('_ambig', [
890+
Tree('start', ['foo1']),
891+
Tree('start', ['foo']),
892+
Tree('start', ['foo12']),
893+
])
894+
self.assertEqual(tree, expected)
895+
896+
l = Lark(grammar, ambiguity='resolve', lexer=LEXER)
897+
tree = l.parse('foo12')
898+
self.assertEqual(tree, Tree('start', ['foo1']))
879899

880900
def test_cycle(self):
881901
grammar = """

0 commit comments

Comments
 (0)