Skip to content

Commit

Permalink
Add forest.get_first_tree() for unpacking tree 0
Browse files Browse the repository at this point in the history
  • Loading branch information
igordejanovic committed Jul 10, 2021
1 parent 57606c9 commit 7cb006c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
6 changes: 6 additions & 0 deletions docs/parse_forest_trees.md
Expand Up @@ -63,6 +63,12 @@ string/dot.
For smaller inputs you can also use `to_dot` to display a forest/tree as a graph.

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

# Parse trees

Expand Down
26 changes: 26 additions & 0 deletions parglare/trees.py
Expand Up @@ -292,6 +292,32 @@ def get_tree(self, idx=0):
def get_nonlazy_tree(self, idx=0):
return Tree(self.result, idx)

def get_first_tree(self):
"""
Gets tree 0 fully unpacked. May be used for optimization purposes where
it doesn't matter which tree we get. The unpacked tree is faster to iterate.
"""
from parglare.glr import Parent

def tree_iterator(n):
if isinstance(n, Parent):
return iter([n.possibilities[0]])
elif n.is_nonterm():
return iter(n.children)
else:
return iter([])

def visit(n, subresults):
if isinstance(n, Parent):
return subresults[0]
elif n.is_nonterm():
# Clone NodeNonTerm to preserve the forest
return NodeNonTerm(n.context, subresults, n.production)
else:
return n

return visitor(self.result.possibilities[0], tree_iterator, visit)

@property
def solutions(self):
return self.result.solutions
Expand Down
8 changes: 8 additions & 0 deletions tests/func/parsing/test_glr_forest.py
Expand Up @@ -185,3 +185,11 @@ def test_multiple_iteration(parser):

for tree in forest.nonlazy_iter():
assert tree.to_str() == tree.to_str()


def test_get_first_tree(parser):
"""
Test that unpacked tree is the same as lazy tree 0.
"""
forest = parser.parse('2 + 3 * 5 + 4 * 1 * 7 + 9 + 10')
assert forest.get_first_tree().to_str() == forest[0].to_str()

0 comments on commit 7cb006c

Please sign in to comment.