From f5ecfda679667c9f90a8819cd51a32dbdbec4189 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 7 Jan 2017 22:12:25 +0100 Subject: Extend parser and generator to handle else blocks --- askama/src/generator.rs | 31 ++++++++++++++++++++----------- askama/src/parser.rs | 22 ++++++++++++++++++++-- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/askama/src/generator.rs b/askama/src/generator.rs index adfa278..95e4dcb 100644 --- a/askama/src/generator.rs +++ b/askama/src/generator.rs @@ -1,4 +1,4 @@ -use parser::{Expr, Node}; +use parser::{Conds, Expr, Node}; use std::str; struct Generator { @@ -79,13 +79,24 @@ impl Generator { self.writeln(")).unwrap();"); } - fn write_cond(&mut self, cond: &Expr, nodes: &Vec) { - self.write("if "); - self.visit_expr(cond); - self.writeln(" {"); - self.indent(); - self.handle(nodes); - self.dedent(); + fn write_cond(&mut self, conds: &Conds) { + for (i, &(ref cond, ref nodes)) in conds.iter().enumerate() { + match cond { + &Some(ref expr) => { + if i == 0 { + self.write("if "); + } else { + self.write("} else if "); + } + self.visit_expr(expr); + }, + &None => { self.writeln("} else"); }, + } + self.writeln(" {"); + self.indent(); + self.handle(nodes); + self.dedent(); + } self.writeln("}"); } @@ -94,9 +105,7 @@ impl Generator { match n { &Node::Lit(val) => { self.write_lit(val); }, &Node::Expr(ref val) => { self.write_expr(&val); }, - &Node::Cond(ref cond, ref nodes) => { - self.write_cond(&cond, &nodes); - }, + &Node::Cond(ref conds) => { self.write_cond(&conds); }, } } } diff --git a/askama/src/parser.rs b/askama/src/parser.rs index 48bcf15..4759472 100644 --- a/askama/src/parser.rs +++ b/askama/src/parser.rs @@ -9,9 +9,12 @@ pub enum Expr<'a> { pub enum Node<'a> { Lit(&'a [u8]), Expr(Expr<'a>), - Cond(Expr<'a>, Vec>), + Cond(Vec<(Option>, Vec>)>), } +pub type Nodes<'a> = Vec>; +pub type Conds<'a> = Vec<(Option>, Nodes<'a>)>; + fn take_content(i: &[u8]) -> IResult<&[u8], Node> { if i.len() < 1 || i[0] == b'{' { return IResult::Error(error_position!(nom::ErrorKind::TakeUntil, i)); @@ -59,16 +62,31 @@ named!(expr_node, map!( delimited!(tag_s!("{{"), ws!(expr_filtered), tag_s!("}}")), Node::Expr)); +named!(cond_blocks, do_parse!( + tag_s!("{%") >> + ws!(tag_s!("else")) >> + tag_s!("%}") >> + block: parse_template >> + (vec![(None, block)]))); + named!(block_if, do_parse!( tag_s!("{%") >> ws!(tag_s!("if")) >> cond: ws!(expr_filtered) >> tag_s!("%}") >> block: parse_template >> + rest: opt!(cond_blocks) >> tag_s!("{%") >> ws!(tag_s!("endif")) >> tag_s!("%}") >> - (Node::Cond(cond, block)))); + ({ + let mut res = Vec::new(); + res.push((Some(cond), block)); + if let Some(blocks) = rest { + res.extend(blocks); + } + Node::Cond(res) + }))); named!(parse_template< Vec >, many1!(alt!( take_content | -- cgit