use crate::{tree_sitter, Extract};
pub fn extract_struct_or_variant<T>(
node: tree_sitter::Node,
construct_expr: impl Fn(&mut Option<tree_sitter::TreeCursor>, &mut usize) -> T,
) -> T {
let mut parent_cursor = node.walk();
construct_expr(
&mut if parent_cursor.goto_first_child() {
Some(parent_cursor)
} else {
None
},
&mut node.start_byte(),
)
}
pub fn extract_field<LT: Extract<T>, T>(
cursor_opt: &mut Option<tree_sitter::TreeCursor>,
source: &[u8],
last_idx: &mut usize,
field_name: &str,
closure_ref: Option<<::LeafFn>,
) -> T {
if let Some(cursor) = cursor_opt.as_mut() {
loop {
let n = cursor.node();
if let Some(name) = cursor.field_name() {
if name == field_name {
let out = LT::extract(Some(n), source, *last_idx, closure_ref);
if !cursor.goto_next_sibling() {
*cursor_opt = None;
};
*last_idx = n.end_byte();
return out;
} else {
return LT::extract(None, source, *last_idx, closure_ref);
}
} else {
*last_idx = n.end_byte();
}
if !cursor.goto_next_sibling() {
return LT::extract(None, source, *last_idx, closure_ref);
}
}
} else {
LT::extract(None, source, *last_idx, closure_ref)
}
}
pub fn parse<T: Extract<T>>(
input: &str,
language: impl Fn() -> tree_sitter::Language,
) -> core::result::Result<T, Vec<crate::errors::ParseError>> {
let mut parser = crate::tree_sitter::Parser::new();
parser.set_language(&language()).unwrap();
let tree = parser.parse(input, None).unwrap();
let root_node = tree.root_node();
if root_node.has_error() {
let mut errors = vec![];
crate::errors::collect_parsing_errors(&root_node, input.as_bytes(), &mut errors);
Err(errors)
} else {
Ok(<T as crate::Extract<_>>::extract(
Some(root_node),
input.as_bytes(),
0,
None,
))
}
}