use std::mem;
use std::num::NonZeroU32;
use crate::diagnostic::ParseDiagnostic;
use crate::tree_sink::TreeSink;
use biome_rowan::{SyntaxKind, TextSize};
#[derive(Debug, Clone)]
pub enum Event<K: SyntaxKind> {
Start {
kind: K,
forward_parent: Option<NonZeroU32>,
},
Finish,
Token {
kind: K,
end: TextSize,
},
}
impl<K: SyntaxKind> Event<K> {
pub fn tombstone() -> Self {
Event::Start {
kind: K::TOMBSTONE,
forward_parent: None,
}
}
}
#[inline]
pub fn process<K: SyntaxKind + PartialEq>(
sink: &mut impl TreeSink<Kind = K>,
mut events: Vec<Event<K>>,
errors: Vec<ParseDiagnostic>,
) {
sink.errors(errors);
let mut forward_parents = Vec::new();
for i in 0..events.len() {
match &mut events[i] {
Event::Start {
kind,
forward_parent,
..
} => {
if *kind == K::TOMBSTONE {
continue;
}
forward_parents.push(*kind);
let mut idx = i;
let mut fp = *forward_parent;
while let Some(fwd) = fp {
idx += u32::from(fwd) as usize;
fp = match mem::replace(&mut events[idx], Event::tombstone()) {
Event::Start {
kind,
forward_parent,
..
} => {
if kind != K::TOMBSTONE {
forward_parents.push(kind);
}
forward_parent
}
_ => unreachable!(),
};
}
for kind in forward_parents.drain(..).rev() {
sink.start_node(kind);
}
}
Event::Finish { .. } => sink.finish_node(),
Event::Token { kind, end } => {
sink.token(*kind, *end);
}
}
}
}