use std::cell::RefCell;
use tree_sitter::{Parser, Tree};
thread_local! {
static R_PARSER: RefCell<Parser> = RefCell::new({
let mut parser = Parser::new();
parser
.set_language(&tree_sitter_r::LANGUAGE.into())
.expect("Failed to set tree-sitter-r language");
parser
});
}
pub fn parse_r(source: &str) -> Option<Tree> {
R_PARSER.with(|parser| parser.borrow_mut().parse(source.as_bytes(), None))
}
pub fn is_atomic_node(kind: &str) -> bool {
matches!(
kind,
"string"
| "comment"
| "integer"
| "float"
| "complex"
| "true"
| "false"
| "null"
| "inf"
| "nan"
| "na"
| "dots"
| "dot_dot_i"
| "special" )
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_r_simple() {
let tree = parse_r("x <- 1");
assert!(tree.is_some());
let tree = tree.unwrap();
assert_eq!(tree.root_node().kind(), "program");
}
#[test]
fn test_parse_r_empty() {
let tree = parse_r("");
assert!(tree.is_some());
}
#[test]
fn test_parse_r_complex() {
let tree = parse_r("function(x) { x |> filter(y > 0) %>% select(-z) }");
assert!(tree.is_some());
}
#[test]
fn test_is_atomic_node_string() {
assert!(is_atomic_node("string"));
}
#[test]
fn test_is_atomic_node_comment() {
assert!(is_atomic_node("comment"));
}
#[test]
fn test_is_atomic_node_numbers() {
assert!(is_atomic_node("integer"));
assert!(is_atomic_node("float"));
assert!(is_atomic_node("complex"));
}
#[test]
fn test_is_atomic_node_constants() {
assert!(is_atomic_node("true"));
assert!(is_atomic_node("false"));
assert!(is_atomic_node("null"));
assert!(is_atomic_node("na"));
}
#[test]
fn test_is_atomic_node_special() {
assert!(is_atomic_node("special"));
assert!(is_atomic_node("dots"));
assert!(is_atomic_node("dot_dot_i"));
}
#[test]
fn test_is_atomic_node_non_atomic() {
assert!(!is_atomic_node("identifier"));
assert!(!is_atomic_node("program"));
assert!(!is_atomic_node("call"));
assert!(!is_atomic_node("binary_operator"));
}
}