Files
zen/core/template/src/parser.rs
T
stefan-gorules daecf901e6 feat: custom node (#138)
* feat: custom node

* add zen template, expose $nodes and $root

* add custom handler to go and nodejs

* add support for python, improve bindings, add error to zen template

* fix: correct binding exports for nodejs and python

* fix benchmark

* improve rust api, trim template in zen templates

* update cargo action

* update expression version

* compile action

* fix action format
2024-04-03 16:09:51 +02:00

78 lines
2.0 KiB
Rust

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(())
}
}