Extend parser and generator to handle else blocks

This commit is contained in:
Dirkjan Ochtman 2017-01-07 22:12:25 +01:00
parent fa651a7350
commit f5ecfda679
2 changed files with 40 additions and 13 deletions

View File

@ -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); },
}
}
}

View File

@ -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 |