moduforge-rules-template 0.5.0

moduforge 模板规则
Documentation
use crate::error::{ParserError, TemplateRenderError};
use crate::lexer::Token;
use std::iter::Peekable;
use std::slice::Iter;

#[derive(Debug, PartialOrd, PartialEq)]
pub(crate) enum Node<'a> {
    Text(&'a str),
    Expression(&'a str),
}

#[derive(Debug, PartialOrd, PartialEq)]
enum ParserState {
    Text,
    Expression,
}

pub(crate) struct Parser<'source, 'tokens> {
    cursor: Peekable<Iter<'tokens, Token<'source>>>,
    state: ParserState,
    nodes: Vec<Node<'source>>,
}

impl<'source, 'tokens, T> From<T> for Parser<'source, 'tokens>
where
    T: Into<&'tokens [Token<'source>]>,
{
    fn from(value: T) -> Self {
        let tokens = value.into();
        let cursor = tokens.iter().peekable();

        Self { cursor, nodes: Default::default(), state: ParserState::Text }
    }
}

impl<'source, 'tokens> Parser<'source, 'tokens> {
    pub(crate) fn collect(
        mut self
    ) -> Result<Vec<Node<'source>>, TemplateRenderError> {
        while let Some(token) = self.cursor.next() {
            match token {
                Token::Text(text) => self.text(text),
                Token::OpenBracket => self.open_bracket()?,
                Token::CloseBracket => self.close_bracket()?,
            }
        }

        Ok(self.nodes)
    }

    fn text(
        &mut self,
        data: &'source str,
    ) {
        match self.state {
            ParserState::Text => self.nodes.push(Node::Text(data)),
            ParserState::Expression => self.nodes.push(Node::Expression(data)),
        }
    }

    fn open_bracket(&mut self) -> Result<(), ParserError> {
        if self.state == ParserState::Expression {
            return Err(ParserError::OpenBracket);
        }

        self.state = ParserState::Expression;
        Ok(())
    }

    fn close_bracket(&mut self) -> Result<(), ParserError> {
        if self.state != ParserState::Expression {
            return Err(ParserError::CloseBracket);
        }

        self.state = ParserState::Text;
        Ok(())
    }
}