aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2017-01-07 22:12:25 +0100
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2017-01-07 22:12:25 +0100
commitf5ecfda679667c9f90a8819cd51a32dbdbec4189 (patch)
tree59a1f8f4bb8c561544708e8405e3d6f0647a70af
parentfa651a7350d338e9a5d3a52e277c76d288310a63 (diff)
downloadaskama-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.rs31
-rw-r--r--askama/src/parser.rs22
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 |