regast-syntax 0.1.0

Lossless syntax tree for the regast regular expression engine
Documentation
use crate::{AstKind, NodeId, Pattern, Span};

#[derive(Clone, Copy, Debug)]
pub struct Cursor<'p> {
    pat: &'p Pattern,
    id: NodeId,
}

impl<'p> Cursor<'p> {
    pub(crate) const fn new(pat: &'p Pattern, id: NodeId) -> Self {
        Self { pat, id }
    }

    #[must_use]
    pub const fn id(self) -> NodeId {
        self.id
    }

    #[must_use]
    pub fn kind(self) -> &'p AstKind {
        &self.pat.node(self.id).kind
    }

    #[must_use]
    pub fn span(self) -> Span {
        self.pat.node(self.id).span
    }

    #[must_use]
    pub fn text(self) -> &'p str {
        self.pat.text(self.span())
    }

    #[must_use]
    pub fn parent(self) -> Option<Self> {
        self.pat
            .node(self.id)
            .parent
            .map(|id| Self::new(self.pat, id))
    }

    #[must_use]
    pub fn children(self) -> Children<'p> {
        Children {
            pat: self.pat,
            inner: self.kind().children().iter(),
        }
    }

    #[must_use]
    pub fn next_sibling(self) -> Option<Self> {
        self.sibling(1)
    }

    #[must_use]
    pub fn prev_sibling(self) -> Option<Self> {
        self.sibling(-1)
    }

    fn sibling(self, delta: isize) -> Option<Self> {
        let parent = self.parent()?;
        let children = parent.kind().children();
        let index = children
            .iter()
            .position(|id| *id == self.id)?
            .checked_add_signed(delta)?;
        let id = *children.get(index)?;
        Some(Self::new(self.pat, id))
    }

    #[must_use]
    pub fn ancestors(self) -> Ancestors<'p> {
        Ancestors {
            next: self.parent(),
        }
    }

    #[must_use]
    pub fn walk(self) -> Walk<'p> {
        Walk { stack: vec![self] }
    }
}

pub struct Children<'p> {
    pat: &'p Pattern,
    inner: std::slice::Iter<'p, NodeId>,
}

impl<'p> Iterator for Children<'p> {
    type Item = Cursor<'p>;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner
            .next()
            .copied()
            .map(|id| Cursor::new(self.pat, id))
    }
}

pub struct Ancestors<'p> {
    next: Option<Cursor<'p>>,
}

impl<'p> Iterator for Ancestors<'p> {
    type Item = Cursor<'p>;

    fn next(&mut self) -> Option<Self::Item> {
        let current = self.next?;
        self.next = current.parent();
        Some(current)
    }
}

pub struct Walk<'p> {
    stack: Vec<Cursor<'p>>,
}

impl<'p> Iterator for Walk<'p> {
    type Item = Cursor<'p>;

    fn next(&mut self) -> Option<Self::Item> {
        let node = self.stack.pop()?;
        self.stack.extend(node.children().rev());
        Some(node)
    }
}

impl DoubleEndedIterator for Children<'_> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.inner
            .next_back()
            .copied()
            .map(|id| Cursor::new(self.pat, id))
    }
}