Build a tree from the flat block list using ``"<"`` / ``">"`` markers.
(blocks: List[List[str]])
| 98 | |
| 99 | |
| 100 | def _parse_tree(blocks: List[List[str]]) -> SchemaNode: |
| 101 | """Build a tree from the flat block list using ``"<"`` / ``">"`` markers.""" |
| 102 | root = SchemaNode(name="__root__") |
| 103 | # Each entry on the stack is (parent_node, last_added_child_under_it). |
| 104 | # When we see ``"<"`` we recurse INTO the last child of the current top. |
| 105 | # When we see ``">"`` we pop back out. |
| 106 | stack: List[SchemaNode] = [root] |
| 107 | for block in blocks: |
| 108 | head = block[0] |
| 109 | if head == "<": |
| 110 | # Open scope on the last-added child of the current top. |
| 111 | top = stack[-1] |
| 112 | if not top.children: |
| 113 | # Defensive: malformed input. Fall back to treating the |
| 114 | # current top itself as the scope. |
| 115 | stack.append(top) |
| 116 | else: |
| 117 | stack.append(top.children[-1]) |
| 118 | continue |
| 119 | if head == ">": |
| 120 | stack.pop() |
| 121 | continue |
| 122 | # Element declaration: ("name", "occurrence", "attr1", "attr2", ...) |
| 123 | occ = block[1] if len(block) > 1 else "*" |
| 124 | attrs = block[2:] |
| 125 | node = SchemaNode(name=head, occurrence=occ, attrs=list(attrs)) |
| 126 | stack[-1].children.append(node) |
| 127 | return root |
| 128 | |
| 129 | |
| 130 | def _find_child(parent: SchemaNode, name: str) -> Optional[SchemaNode]: |