56 lines
1.5 KiB
Rust
56 lines
1.5 KiB
Rust
use kiutils_sexpr::{Atom, Node};
|
|
|
|
pub fn head(node: &Node) -> Option<&str> {
|
|
let Node::List { items, .. } = node else { return None; };
|
|
items.first().and_then(symbol)
|
|
}
|
|
|
|
pub fn symbol(node: &Node) -> Option<&str> {
|
|
match node {
|
|
Node::Atom { atom: Atom::Symbol(s), .. } => Some(s.as_str()),
|
|
Node::Atom { atom: Atom::Quoted(s), .. } => Some(s.as_str()),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn children<'a>(node: &'a Node) -> &'a [Node] {
|
|
match node {
|
|
Node::List { items, .. } => items,
|
|
_ => &[],
|
|
}
|
|
}
|
|
|
|
pub fn find_list<'a>(parent: &'a Node, head_name: &str) -> Option<&'a Node> {
|
|
children(parent)
|
|
.iter()
|
|
.find(|n| head(n) == Some(head_name))
|
|
}
|
|
|
|
pub fn find_lists<'a>(parent: &'a Node, head_name: &str) -> Vec<&'a Node> {
|
|
children(parent)
|
|
.iter()
|
|
.filter(|n| head(n) == Some(head_name))
|
|
.collect()
|
|
}
|
|
|
|
pub fn arg<'a>(list_node: &'a Node, index: usize) -> Option<&'a Node> {
|
|
children(list_node).get(index + 1)
|
|
}
|
|
|
|
pub fn arg_f64(list_node: &Node, index: usize) -> Option<f64> {
|
|
arg(list_node, index).and_then(as_f64)
|
|
}
|
|
|
|
pub fn arg_str<'a>(list_node: &'a Node, index: usize) -> Option<&'a str> {
|
|
arg(list_node, index).and_then(symbol)
|
|
}
|
|
|
|
pub fn as_f64(node: &Node) -> Option<f64> {
|
|
symbol(node).and_then(|s| s.parse::<f64>().ok())
|
|
}
|
|
|
|
pub fn xy_from<'a>(list_node: &'a Node, head_name: &str) -> Option<(f64, f64)> {
|
|
let l = find_list(list_node, head_name)?;
|
|
Some((arg_f64(l, 0)?, arg_f64(l, 1)?))
|
|
}
|