phml.utilities.travel.travel

utilities.travel

Collection of utilities that hep with traversing an ast or node tree.

 1"""utilities.travel
 2
 3Collection of utilities that hep with traversing an ast or node tree.
 4"""
 5
 6from typing import Iterator
 7
 8from phml.nodes import Element, Node, Parent, AST
 9
10__all__ = ["path", "path_names", "walk", "visit_all_after"]
11
12
13def path(node: Node) -> list[Element]:
14    """Get a list of nodes where each one is a child of
15    the other leading to the node passed in. This gives a
16    path to the node.
17
18    Does not include given node.
19
20    Args:
21        node (Node): Node to find ancestors of.
22
23    Returns:
24        list[Node]: List of nodes leading to the given node
25        starting from the root.
26    """
27    ancestors = []
28    while node.parent is not None and isinstance(node.parent, Element):
29        ancestors = [node.parent, *ancestors]
30        node = node.parent
31
32    return ancestors
33
34
35def path_names(node: Node) -> list[str]:
36    """Get a list of nodes where each one is a child of
37    the other leading to the node passed in. This gives a
38    path to the node.
39
40    Does not include given node.
41
42    Args:
43        node (Node): Node to find ancestors of.
44
45    Returns:
46        list[str]: List of nodes leading to the given node
47        starting from the root.
48    """
49    ancestors = []
50    while node.parent is not None and isinstance(node.parent, Element):
51        ancestors = [node.parent.tag, *ancestors]
52        node = node.parent
53
54    return ancestors
55
56
57def walk(node: Parent) -> Iterator:
58    """Recursively traverse the node and it's chidlren as an iterator.
59    Left to right depth first.
60    """
61
62    def get_children(n: Node) -> Iterator:
63        yield n
64        if isinstance(n, Parent):
65            for child in n:
66                yield from get_children(child)
67
68    yield node
69    if isinstance(node, Parent):
70        for child in node:
71            yield from get_children(child)
72
73
74def visit_all_after(start: Node) -> Iterator:
75    """Recursively traverse the tree starting at given node."""
76
77    def get_children(parent) -> Iterator:
78        yield parent
79        if parent.type in ["root", "element"]:
80            for child in parent:
81                yield from get_children(child)
82
83    parent = start.parent
84    if parent is not None:
85        idx = parent.index(start)
86        if idx < len(parent) - 1:
87            for child in parent[idx + 1 :]:
88                yield from get_children(child)
def path(node: phml.nodes.Node) -> list[phml.nodes.Element]:
14def path(node: Node) -> list[Element]:
15    """Get a list of nodes where each one is a child of
16    the other leading to the node passed in. This gives a
17    path to the node.
18
19    Does not include given node.
20
21    Args:
22        node (Node): Node to find ancestors of.
23
24    Returns:
25        list[Node]: List of nodes leading to the given node
26        starting from the root.
27    """
28    ancestors = []
29    while node.parent is not None and isinstance(node.parent, Element):
30        ancestors = [node.parent, *ancestors]
31        node = node.parent
32
33    return ancestors

Get a list of nodes where each one is a child of the other leading to the node passed in. This gives a path to the node.

Does not include given node.

Args
  • node (Node): Node to find ancestors of.
Returns

list[Node]: List of nodes leading to the given node starting from the root.

def path_names(node: phml.nodes.Node) -> list[str]:
36def path_names(node: Node) -> list[str]:
37    """Get a list of nodes where each one is a child of
38    the other leading to the node passed in. This gives a
39    path to the node.
40
41    Does not include given node.
42
43    Args:
44        node (Node): Node to find ancestors of.
45
46    Returns:
47        list[str]: List of nodes leading to the given node
48        starting from the root.
49    """
50    ancestors = []
51    while node.parent is not None and isinstance(node.parent, Element):
52        ancestors = [node.parent.tag, *ancestors]
53        node = node.parent
54
55    return ancestors

Get a list of nodes where each one is a child of the other leading to the node passed in. This gives a path to the node.

Does not include given node.

Args
  • node (Node): Node to find ancestors of.
Returns

list[str]: List of nodes leading to the given node starting from the root.

def walk(node: phml.nodes.Parent) -> Iterator:
58def walk(node: Parent) -> Iterator:
59    """Recursively traverse the node and it's chidlren as an iterator.
60    Left to right depth first.
61    """
62
63    def get_children(n: Node) -> Iterator:
64        yield n
65        if isinstance(n, Parent):
66            for child in n:
67                yield from get_children(child)
68
69    yield node
70    if isinstance(node, Parent):
71        for child in node:
72            yield from get_children(child)

Recursively traverse the node and it's chidlren as an iterator. Left to right depth first.

def visit_all_after(start: phml.nodes.Node) -> Iterator:
75def visit_all_after(start: Node) -> Iterator:
76    """Recursively traverse the tree starting at given node."""
77
78    def get_children(parent) -> Iterator:
79        yield parent
80        if parent.type in ["root", "element"]:
81            for child in parent:
82                yield from get_children(child)
83
84    parent = start.parent
85    if parent is not None:
86        idx = parent.index(start)
87        if idx < len(parent) - 1:
88            for child in parent[idx + 1 :]:
89                yield from get_children(child)

Recursively traverse the tree starting at given node.