Siphon/src/parse/sexpr.rs

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)?))
}