Skip to content

Commit 7cb006c

Browse files
committed
Add forest.get_first_tree() for unpacking tree 0
1 parent 57606c9 commit 7cb006c

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

docs/parse_forest_trees.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ string/dot.
6363
6464
For smaller inputs you can also use `to_dot` to display a forest/tree as a graph.
6565

66+
There is also `forest.get_tree(idx)` which is the same as `forest[idx]`, i.e. it
67+
returns lazy tree. To get non-lazy tree, i.e. tree whose proxies are
68+
pre-initialized, call `forest.get_nonlazy_tree(idx)`. If you just need the first
69+
tree, call `forest.get_first_tree()` to get an unpacked tree which consists only
70+
of `NodeTerm` and `NodeNonTerm`. This tree is the fastest to navigate but only
71+
tree 0 is supported in this form.
6672

6773
# Parse trees
6874

parglare/trees.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,32 @@ def get_tree(self, idx=0):
292292
def get_nonlazy_tree(self, idx=0):
293293
return Tree(self.result, idx)
294294

295+
def get_first_tree(self):
296+
"""
297+
Gets tree 0 fully unpacked. May be used for optimization purposes where
298+
it doesn't matter which tree we get. The unpacked tree is faster to iterate.
299+
"""
300+
from parglare.glr import Parent
301+
302+
def tree_iterator(n):
303+
if isinstance(n, Parent):
304+
return iter([n.possibilities[0]])
305+
elif n.is_nonterm():
306+
return iter(n.children)
307+
else:
308+
return iter([])
309+
310+
def visit(n, subresults):
311+
if isinstance(n, Parent):
312+
return subresults[0]
313+
elif n.is_nonterm():
314+
# Clone NodeNonTerm to preserve the forest
315+
return NodeNonTerm(n.context, subresults, n.production)
316+
else:
317+
return n
318+
319+
return visitor(self.result.possibilities[0], tree_iterator, visit)
320+
295321
@property
296322
def solutions(self):
297323
return self.result.solutions

tests/func/parsing/test_glr_forest.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,11 @@ def test_multiple_iteration(parser):
185185

186186
for tree in forest.nonlazy_iter():
187187
assert tree.to_str() == tree.to_str()
188+
189+
190+
def test_get_first_tree(parser):
191+
"""
192+
Test that unpacked tree is the same as lazy tree 0.
193+
"""
194+
forest = parser.parse('2 + 3 * 5 + 4 * 1 * 7 + 9 + 10')
195+
assert forest.get_first_tree().to_str() == forest[0].to_str()

0 commit comments

Comments
 (0)