-
Notifications
You must be signed in to change notification settings - Fork 111
/
utils.py
33 lines (27 loc) · 1.26 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from collections import namedtuple
TraverseResult = namedtuple('TraverseResult', ['node', 'parent', 'depth'])
def traverse(source, klass=None, depth=None, include_source=False):
"""Traverse the syntax tree, recursively yielding children.
Args:
source: The source syntax token
klass: filter children by a certain token class
depth (int): The depth to recurse into the tree
include_source (bool): whether to first yield the source element
(provided it passes any given ``klass`` filter)
Yields:
A container for an element, its parent and depth
"""
current_depth = 0
if include_source and (klass is None or isinstance(source, klass)):
yield TraverseResult(source, None, current_depth)
next_children = [(source, c) for c in source.children or []]
while next_children and (depth is None or current_depth < depth):
current_depth += 1
new_children = []
for parent, child in next_children:
if klass is None or isinstance(child, klass):
yield TraverseResult(child, parent, current_depth)
new_children.extend(
[(child, c) for c in child.children or []]
)
next_children = new_children