Я работаю над механизмом создания шаблонов, синтаксис которого может быть таким:
{{ somevar|filter }}
Вместо somevar
может быть произвольное «выражение», то есть либо имя переменной, например somevar
, либо вложенное выражение фильтра (например, {{ somevar|filter|anotherfilter }}
). Я пытаюсь разобрать это, используя библиотеку комбинатора синтаксического анализатора Rust nom, но пока не могу заставить ее работать.
Вот синтаксический анализатор, который я придумал:
#[macro_use]
extern crate nom;
use std::str;
#[derive(Debug)]
pub enum Expr<'a> {
Var(&'a [u8]),
Filter(&'a str, Box<Expr<'a>>),
}
#[derive(Debug)]
pub enum Node<'a> {
Lit(&'a [u8]),
Expr(Expr<'a>),
}
named!(expr_var<Expr>, dbg_dmp!(map!(nom::alphanumeric, Expr::Var)));
named!(expr_filter<Expr>,
dbg_dmp!(do_parse!(
val: any_expr >>
tag_s!("|") >>
name: map_res!(nom::alphanumeric, str::from_utf8) >>
(Expr::Filter(name, Box::new(val)))
))
);
named!(any_expr<Expr>, dbg_dmp!(ws!(
alt_complete!(
expr_filter |
expr_var
))));
named!(expr_node<Node>, dbg_dmp!(map!(
delimited!(tag_s!("{{"), any_expr, tag_s!("}}")),
Node::Expr)));
named!(parse_template< Vec<Node> >, many1!(expr_node));
С игровой площадкой. Текущая версия вызывает панику из-за переполнения стека. Я могу исправить это, изменив порядок expr_var | expr_filter
в any_expr
, но затем я снова вернусь к той же ошибке, что и раньше.