syncat-stylesheet 3.6.0

Parser for Syncat Stylesheets.
Documentation
use super::{Node, NodeModifier, helper::*};
use crate::{Matches, Query, QuerySlice};
use tree_sitter::TreeCursor;

#[derive(Clone, Debug)]
pub(crate) struct Selector {
    pub(crate) nodes: Vec<Node>,
}

impl Selector {
    pub(crate) fn matches<'k, 's, 'a: 's>(
        &'k self,
        query: &'a Query<'s>,
    ) -> Option<Matches<'k, 's>> {
        if self.nodes.is_empty() {
            return Some(Matches::default());
        }
        Self::matches2(
            &self.nodes[..],
            &QuerySlice::new(query, self.nodes.last().unwrap().modifier),
        )
    }

    fn matches2<'k, 's, 'a: 's>(
        nodes: &'k [Node],
        query: &QuerySlice<'a, 's>,
    ) -> Option<Matches<'k, 's>> {
        if nodes.is_empty() {
            return Some(Matches::default());
        }
        let (subquery, new_matches) = query.find(nodes.last().unwrap())?;
        if let Some(mut matches) = Self::matches2(&nodes[..nodes.len() - 1], &subquery) {
            matches.merge(new_matches);
            Some(matches)
        } else if nodes.last().unwrap().can_try_again() {
            Self::matches2(nodes, &subquery)
        } else {
            None
        }
    }
}

impl FromSource for Selector {
    fn from_source(tree: &mut TreeCursor, source: &[u8]) -> crate::Result<Self> {
        children!(tree, "selector");
        let mut nodes = vec![];
        while {
            if tree.node().is_named() && !tree.node().is_extra() {
                match tree.node().kind() {
                    "node" => nodes.push(Node::from_source(tree, source)?),
                    "node_modifier" => {
                        nodes.last_mut().unwrap().modifier =
                            NodeModifier::from_source(tree, source)?
                    }
                    name => return Err(crate::Error::invalid("node/node_modifier", name)),
                }
            }
            tree.goto_next_sibling()
        } {}
        tree.goto_parent();
        Ok(Self { nodes })
    }
}