Coverage for src/m6rclib/metaphor_ast_node.py: 100%
45 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-14 17:03 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-14 17:03 +0000
1# Copyright 2024 M6R Ltd.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
15"""
16Types and classes for representing the AST (Abstract Syntax Tree)
17of a Metaphor document.
18"""
20from typing import List, Optional
21from enum import IntEnum
23class MetaphorASTNodeType(IntEnum):
24 """
25 Types of nodes that can appear in a Metaphor AST.
26 """
27 ROOT: int = 0
28 TEXT: int = 1
29 ROLE: int = 2
30 CONTEXT: int = 3
31 ACTION: int = 4
34class MetaphorASTNode:
35 """
36 Represents a node in the Abstract Syntax Tree (AST).
38 Attributes:
39 node_type (MetaphorASTNodeType): The type of the token the node represents.
40 value (str): The value associated with the node.
41 """
42 def __init__(self, node_type: MetaphorASTNodeType, value: str) -> None:
43 self._node_type: MetaphorASTNodeType = node_type
44 self._value: str = value
45 self._parent: Optional['MetaphorASTNode'] = None
46 self._children: List['MetaphorASTNode'] = []
48 def __str__(self, indent: int = 0) -> str:
49 """
50 Returns a string representation of the node and its children in a tree format.
52 Args:
53 indent (int): The current indentation level (used recursively)
55 Returns:
56 str: A formatted string showing the node's type, value, and children
57 """
58 # Create the indentation string
59 indent_str = " " * indent
61 # Start with this node's information
62 result = f"{indent_str}{self.node_type.name}: {self.value}"
64 # Add all children with increased indentation
65 for child in self._children:
66 result += "\n" + child.__str__(indent + 1)
68 return result
70 def __repr__(self) -> str:
71 """
72 Returns a concise representation of the node for debugging.
74 Returns:
75 str: A string in format 'NodeType(value)[num_children]'
76 """
77 return f"{self.node_type.name}({self.value})[{len(self._children)}]"
79 def attach_child(self, child: 'MetaphorASTNode') -> None:
80 """Add a child node to this MetaphorASTNode."""
81 child.parent = self
82 self._children.append(child)
84 def detach_child(self, child: 'MetaphorASTNode') -> None:
85 """Detach a child node from this node in the AST."""
86 if child not in self.children:
87 raise ValueError("Node is not a child of this node")
89 self._children.remove(child)
90 child.parent = None
92 @property
93 def node_type(self) -> MetaphorASTNodeType:
94 """The type of this node."""
95 return self._node_type
97 @property
98 def value(self) -> str:
99 """The raw text value of this node."""
100 return self._value
102 @property
103 def parent(self) -> Optional['MetaphorASTNode']:
104 """The parent node, if any."""
105 return self._parent
107 @parent.setter
108 def parent(self, new_parent: Optional['MetaphorASTNode']) -> None:
109 self._parent = new_parent
111 @property
112 def children(self) -> List['MetaphorASTNode']:
113 """The node's children (returns a shallow copy to prevent direct list modification)."""
114 return self._children.copy()
116 def get_children_of_type(self, node_type: MetaphorASTNodeType) -> List['MetaphorASTNode']:
117 """
118 Returns a list of all immediate children that match the specified node type.
120 Args:
121 node_type (MetaphorASTNodeType): The type of nodes to filter for
123 Returns:
124 List[MetaphorASTNode]: List of child nodes matching the specified type
125 """
126 return [child for child in self._children if child.node_type == node_type]