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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! Tree metrics: depth and node count.
use crate::ast::Expression;
use super::walker::for_each_child;
fn depth_core(expr: &Expression) -> usize {
let mut max_child = 0usize;
for_each_child(expr, |child| {
max_child = max_child.max(depth_core(child));
});
1 + max_child
}
fn nc_core(expr: &Expression) -> usize {
let mut total = 0usize;
for_each_child(expr, |child| {
total += nc_core(child);
});
1 + total
}
impl Expression {
/// Calculates the maximum depth of the expression tree.
///
/// The depth is defined as the longest path from the root to a leaf node.
/// Leaf nodes (integers, floats, variables, constants) have depth 1.
///
/// # Examples
///
/// ```
/// use mathlex::ast::{ExprKind, Expression, BinaryOp};
///
/// // Simple leaf: x
/// let leaf = Expression::variable("x".to_string());
/// assert_eq!(leaf.depth(), 1);
///
/// // Binary expression: (x + y)
/// let binary: Expression = ExprKind::Binary {
/// op: BinaryOp::Add,
/// left: Box::new(Expression::variable("x".to_string())),
/// right: Box::new(Expression::variable("y".to_string())),
/// }.into();
/// assert_eq!(binary.depth(), 2);
///
/// // Nested: ((x + y) * z)
/// let nested: Expression = ExprKind::Binary {
/// op: BinaryOp::Mul,
/// left: Box::new(binary),
/// right: Box::new(Expression::variable("z".to_string())),
/// }.into();
/// assert_eq!(nested.depth(), 3);
/// ```
pub fn depth(&self) -> usize {
depth_core(self)
}
/// Counts the total number of nodes in the expression tree.
///
/// Every AST node is counted, including the root node. This provides
/// a measure of expression complexity.
///
/// # Examples
///
/// ```
/// use mathlex::ast::{ExprKind, Expression, BinaryOp};
///
/// // Simple leaf: x
/// let leaf = Expression::variable("x".to_string());
/// assert_eq!(leaf.node_count(), 1);
///
/// // Binary expression: (x + y)
/// let binary: Expression = ExprKind::Binary {
/// op: BinaryOp::Add,
/// left: Box::new(Expression::variable("x".to_string())),
/// right: Box::new(Expression::variable("y".to_string())),
/// }.into();
/// assert_eq!(binary.node_count(), 3); // Add node + x + y
///
/// // Nested: ((x + y) * z)
/// let nested: Expression = ExprKind::Binary {
/// op: BinaryOp::Mul,
/// left: Box::new(binary),
/// right: Box::new(Expression::variable("z".to_string())),
/// }.into();
/// assert_eq!(nested.node_count(), 5); // Mul + (Add + x + y) + z
/// ```
pub fn node_count(&self) -> usize {
nc_core(self)
}
}