diff options
author | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-01-07 22:12:25 +0100 |
---|---|---|
committer | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-01-07 22:12:25 +0100 |
commit | f5ecfda679667c9f90a8819cd51a32dbdbec4189 (patch) | |
tree | 59a1f8f4bb8c561544708e8405e3d6f0647a70af | |
parent | fa651a7350d338e9a5d3a52e277c76d288310a63 (diff) | |
download | askama-f5ecfda679667c9f90a8819cd51a32dbdbec4189.tar.gz askama-f5ecfda679667c9f90a8819cd51a32dbdbec4189.tar.bz2 askama-f5ecfda679667c9f90a8819cd51a32dbdbec4189.zip |
Extend parser and generator to handle else blocks
Diffstat (limited to '')
-rw-r--r-- | askama/src/generator.rs | 31 | ||||
-rw-r--r-- | 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<Node>) { - 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<Node<'a>>), + Cond(Vec<(Option<Expr<'a>>, Vec<Node<'a>>)>), } +pub type Nodes<'a> = Vec<Node<'a>>; +pub type Conds<'a> = Vec<(Option<Expr<'a>>, 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<Node>, map!( delimited!(tag_s!("{{"), ws!(expr_filtered), tag_s!("}}")), Node::Expr)); +named!(cond_blocks<Conds>, do_parse!( + tag_s!("{%") >> + ws!(tag_s!("else")) >> + tag_s!("%}") >> + block: parse_template >> + (vec![(None, block)]))); + named!(block_if<Node>, 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<Node> >, many1!(alt!( take_content | |