mod builder;
mod kind_scan;
pub use builder::TreeBuilder;
pub use kind_scan::KindScan;
use crate::{SyntaxKind, TextRange, TextSize};
pub type ElementId = u32;
const NONE: u32 = u32::MAX;
const TOKEN_BIT: u16 = 0x8000;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Tree {
text: Box<str>,
kinds: Vec<u16>,
starts: Vec<u32>,
ends: Vec<u32>,
parents: Vec<u32>,
prev_sibs: Vec<u32>,
}
impl Tree {
pub const ROOT: ElementId = 0;
pub fn text(&self) -> &str {
&self.text
}
pub fn len(&self) -> usize {
self.kinds.len()
}
pub fn is_empty(&self) -> bool {
self.kinds.is_empty()
}
pub fn kind(&self, e: ElementId) -> SyntaxKind {
SyntaxKind::from_raw(self.kinds[e as usize] & !TOKEN_BIT)
}
pub fn is_token(&self, e: ElementId) -> bool {
self.kinds[e as usize] & TOKEN_BIT != 0
}
pub fn subtree_end(&self, e: ElementId) -> ElementId {
self.ends[e as usize]
}
pub fn parent(&self, e: ElementId) -> Option<ElementId> {
some(self.parents[e as usize])
}
pub fn first_child(&self, e: ElementId) -> Option<ElementId> {
(self.ends[e as usize] > e + 1).then_some(e + 1)
}
pub fn last_child(&self, e: ElementId) -> Option<ElementId> {
let mut last = self.first_child(e)?;
let mut cur = self.ends[e as usize] - 1;
while let Some(p) = self.parent(cur) {
if p == e {
last = cur;
break;
}
cur = p;
}
Some(last)
}
pub fn next_sibling(&self, e: ElementId) -> Option<ElementId> {
let parent = self.parent(e)?;
let next = self.ends[e as usize];
(next < self.ends[parent as usize]).then_some(next)
}
pub fn prev_sibling(&self, e: ElementId) -> Option<ElementId> {
some(self.prev_sibs[e as usize])
}
pub fn children(&self, e: ElementId) -> Children<'_> {
Children { tree: self, next: self.first_child(e) }
}
pub fn text_range(&self, e: ElementId) -> TextRange {
let start = self.starts[e as usize];
let end = self.starts.get(self.ends[e as usize] as usize).copied().unwrap_or(self.text.len() as u32);
TextRange::new(TextSize::from(start), TextSize::from(end))
}
pub fn text_of(&self, e: ElementId) -> &str {
&self.text[self.text_range(e)]
}
pub fn has_descendant_of_kind(&self, e: ElementId, kind: SyntaxKind) -> bool {
let raw = kind as u16;
self.kinds[e as usize + 1..self.ends[e as usize] as usize].iter().any(|&k| k & !TOKEN_BIT == raw)
}
pub fn find_kinds<const N: usize, const M: usize>(
&self,
e: ElementId,
nodes: [SyntaxKind; N],
tokens: [SyntaxKind; M],
) -> KindScan<'_> {
const { assert!(N + M <= kind_scan::MAX_WANTED) };
let mut wanted = [kind_scan::NEVER; kind_scan::MAX_WANTED];
for (slot, k) in wanted.iter_mut().zip(nodes.map(|k| k as u16).into_iter().chain(tokens.map(|k| k as u16 | TOKEN_BIT))) {
*slot = k;
}
let start = e as usize;
KindScan::new(&self.kinds[start..self.ends[start] as usize], start, wanted)
}
}
pub struct Children<'t> {
tree: &'t Tree,
next: Option<ElementId>,
}
impl Iterator for Children<'_> {
type Item = ElementId;
fn next(&mut self) -> Option<ElementId> {
let cur = self.next?;
self.next = self.tree.next_sibling(cur);
Some(cur)
}
}
fn some(index: u32) -> Option<ElementId> {
(index != NONE).then_some(index)
}
#[cfg(test)]
mod tests;