utterance 0.1.2

A parser library for creating readable, natural-language-inspired domain-specific languages.
Documentation
use crate::lexer::Lexer;
use crate::parser::ParseError;
use crate::parser::tree::{ParseContext, ParseTree};
use crate::syntax::Highlights;

pub(crate) struct MatchFrame<'tree, 'input, C, const H: usize, const P: usize>
where
    C: ParseContext,
{
    tree: &'tree ParseTree<C>,
    child_index: usize,

    lexer: Lexer<'input, P>,
    highlights: Highlights<H>,
    context: C,

    depth: usize,
    error: Option<ParseError>,

    matched: bool,
}

impl<'tree, 'input, C, const H: usize, const P: usize> MatchFrame<'tree, 'input, C, H, P>
where
    C: ParseContext,
{
    pub(crate) fn new(
        tree: &'tree ParseTree<C>,
        lexer: Lexer<'input, P>,
        context: C,
        depth: usize,
    ) -> Self {
        Self {
            tree,
            child_index: 0,
            lexer,
            highlights: Highlights::new(),
            context,
            depth,
            error: None,
            matched: false,
        }
    }

    pub(crate) fn next_child(&mut self) -> Option<&'tree ParseTree<C>> {
        let child = self.tree.children().nth(self.child_index)?;
        self.child_index += 1;

        Some(child)
    }

    pub(crate) fn take_error(&mut self) -> Option<ParseError> {
        self.error.take()
    }

    pub(crate) fn merge_error(&mut self, error: ParseError) {
        error.merge_from_option(&mut self.error);
    }

    pub(crate) fn try_match(&mut self) -> Result<(), ParseError> {
        if self.matched {
            return Ok(());
        }

        self.tree.try_match(
            &mut self.lexer,
            &mut self.highlights,
            &mut self.context,
            self.depth,
        )?;

        self.matched = true;

        Ok(())
    }

    pub(crate) fn is_end(&self) -> bool {
        self.tree.is_end()
    }

    pub(crate) fn into_result(self) -> (Lexer<'input, P>, Highlights<H>, C) {
        (self.lexer, self.highlights, self.context)
    }

    pub(crate) fn child_from(
        parent: &MatchFrame<'tree, 'input, C, H, P>,
        tree: &'tree ParseTree<C>,
    ) -> Self {
        Self {
            tree,
            child_index: 0,

            lexer: parent.lexer.clone(),
            highlights: Highlights::new(),
            context: parent.context.clone(),

            depth: parent.depth + 1,
            error: None,

            matched: false,
        }
    }
}