use crate::source::token::{Punct, Span, Tok, Token};
#[derive(Clone)]
pub(crate) enum Tree {
Leaf(Token),
Group {
open: Token,
inner: Vec<Tree>,
close: Token,
},
}
pub(crate) fn closer(open: &Tok) -> Option<Punct> {
match open {
Tok::Punct(Punct::LParen) => Some(Punct::RParen),
Tok::Punct(Punct::LBracket) => Some(Punct::RBracket),
Tok::Punct(Punct::LBrace) => Some(Punct::RBrace),
_ => None,
}
}
pub(crate) fn tree_at(tokens: &[Token], i: usize) -> (Tree, usize) {
let open = tokens[i].clone();
let Some(close) = closer(&open.tok) else {
return (Tree::Leaf(open), i + 1);
};
let mut inner = Vec::new();
let mut j = i + 1;
while j < tokens.len() {
if tokens[j].tok == Tok::Punct(close) {
let close = tokens[j].clone();
return (Tree::Group { open, inner, close }, j + 1);
}
let (tree, next) = tree_at(tokens, j);
inner.push(tree);
j = next;
}
let close = Token {
tok: Tok::Punct(close),
span: Span::new(open.span.end as usize, open.span.end as usize),
};
(Tree::Group { open, inner, close }, j)
}
pub(crate) fn flatten(trees: &[Tree], out: &mut Vec<Token>) {
for t in trees {
match t {
Tree::Leaf(tok) => out.push(tok.clone()),
Tree::Group { open, inner, close } => {
out.push(open.clone());
flatten(inner, out);
out.push(close.clone());
}
}
}
}
pub(crate) fn size(t: &Tree) -> usize {
match t {
Tree::Leaf(_) => 1,
Tree::Group { inner, .. } => 2 + inner.iter().map(size).sum::<usize>(),
}
}