diff options
Diffstat (limited to '')
| -rw-r--r-- | askama_derive/src/generator.rs | 7 | ||||
| -rw-r--r-- | askama_derive/src/parser.rs | 34 | 
2 files changed, 37 insertions, 4 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index 3fa5b9f..0e80265 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -54,9 +54,16 @@ impl Generator {          self.write(&format!("self.{}", str::from_utf8(s).unwrap()));      } +    fn visit_filter(&mut self, name: &str, val: &Expr) { +        self.write(&format!("askama::filters::{}(&", name)); +        self.visit_expr(val); +        self.write(")"); +    } +      fn visit_expr(&mut self, expr: &Expr) {          match expr {              &Expr::Var(s) => self.visit_var(s), +            &Expr::Filter(name, ref val) => self.visit_filter(name, &val),          }      } diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs index 5f3f8c5..cd93971 100644 --- a/askama_derive/src/parser.rs +++ b/askama_derive/src/parser.rs @@ -1,7 +1,9 @@  use nom::{self, IResult}; +use std::str;  pub enum Expr<'a> {       Var(&'a [u8]), +     Filter(&'a str, Box<Expr<'a>>),  }  pub enum Node<'a> { @@ -27,17 +29,41 @@ fn take_content(i: &[u8]) -> IResult<&[u8], Node> {      IResult::Done(&i[..0], Node::Lit(&i[..]))  } -named!(expr_var<Expr>, map!(ws!(nom::alphanumeric), Expr::Var)); +named!(expr_var<Expr>, map!(nom::alphanumeric, Expr::Var)); -named!(any_expr<Expr>, delimited!(tag!("{{"), expr_var, tag!("}}"))); +fn expr_filtered(i: &[u8]) -> IResult<&[u8], Expr> { +    let (mut left, mut expr) = match expr_var(i) { +        IResult::Error(err) => { return IResult::Error(err); }, +        IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, +        IResult::Done(left, res) => (left, res), +    }; +    while left[0] == b'|' { +        match nom::alphanumeric(&left[1..]) { +            IResult::Error(err) => { +                return IResult::Error(err); +            }, +            IResult::Incomplete(needed) => { +                return IResult::Incomplete(needed); +            }, +            IResult::Done(new_left, res) => { +                left = new_left; +                expr = Expr::Filter(str::from_utf8(res).unwrap(), Box::new(expr)); +            }, +        }; +    } +    return IResult::Done(left, expr); +} -named!(expr_node<Node>, map!(any_expr, Node::Expr)); +named!(expr_node<Node>, map!( +    delimited!(tag_s!("{{"), ws!(expr_filtered), tag_s!("}}")), +    Node::Expr));  named!(parse_template< Vec<Node> >, many1!(alt!(take_content | expr_node)));  pub fn parse<'a>(src: &'a str) -> Vec<Node> {      match parse_template(src.as_bytes()) {          IResult::Done(_, res) => res, -        _ => panic!("problems parsing template source"), +        IResult::Error(err) => panic!("problems parsing template source: {}", err), +        IResult::Incomplete(_) => panic!("parsing incomplete"),      }  }  | 
