diff options
Diffstat (limited to 'askama_derive')
| -rw-r--r-- | askama_derive/src/generator.rs | 6 | ||||
| -rw-r--r-- | askama_derive/src/parser/expr.rs | 38 | ||||
| -rw-r--r-- | askama_derive/src/parser/tests.rs | 45 | 
3 files changed, 72 insertions, 17 deletions
| diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index d9ddfc8..f990330 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -1373,7 +1373,7 @@ impl<'a> Generator<'a> {              }              Expr::Group(ref inner) => self.visit_group(buf, inner)?,              Expr::Call(ref obj, ref args) => self.visit_call(buf, obj, args)?, -            Expr::RustMacro(name, args) => self.visit_rust_macro(buf, name, args), +            Expr::RustMacro(ref path, args) => self.visit_rust_macro(buf, path, args),              Expr::Try(ref expr) => self.visit_try(buf, expr.as_ref())?,              Expr::Tuple(ref exprs) => self.visit_tuple(buf, exprs)?,          }) @@ -1390,8 +1390,8 @@ impl<'a> Generator<'a> {          Ok(DisplayWrap::Unwrapped)      } -    fn visit_rust_macro(&mut self, buf: &mut Buffer, name: &str, args: &str) -> DisplayWrap { -        buf.write(name); +    fn visit_rust_macro(&mut self, buf: &mut Buffer, path: &[&str], args: &str) -> DisplayWrap { +        self.visit_path(buf, path);          buf.write("!(");          buf.write(args);          buf.write(")"); diff --git a/askama_derive/src/parser/expr.rs b/askama_derive/src/parser/expr.rs index fabaa34..1d4ea89 100644 --- a/askama_derive/src/parser/expr.rs +++ b/askama_derive/src/parser/expr.rs @@ -4,9 +4,10 @@ use nom::branch::alt;  use nom::bytes::complete::{tag, take_till};  use nom::character::complete::char;  use nom::combinator::{cut, map, not, opt, peek, recognize}; +use nom::error::ErrorKind;  use nom::multi::{fold_many0, many0, separated_list0, separated_list1};  use nom::sequence::{delimited, pair, preceded, terminated, tuple}; -use nom::IResult; +use nom::{error_position, IResult};  use super::{      bool_lit, char_lit, identifier, nested_parenthesis, not_ws, num_lit, path, str_lit, ws, @@ -30,7 +31,7 @@ pub(crate) enum Expr<'a> {      Group(Box<Expr<'a>>),      Tuple(Vec<Expr<'a>>),      Call(Box<Expr<'a>>, Vec<Expr<'a>>), -    RustMacro(&'a str, &'a str), +    RustMacro(Vec<&'a str>, &'a str),      Try(Box<Expr<'a>>),  } @@ -183,7 +184,6 @@ fn expr_single(i: &str) -> IResult<&str, Expr<'_>> {          expr_str_lit,          expr_char_lit,          expr_path, -        expr_rust_macro,          expr_array_lit,          expr_var,          expr_group, @@ -194,6 +194,8 @@ enum Suffix<'a> {      Attr(&'a str),      Index(Expr<'a>),      Call(Vec<Expr<'a>>), +    // The value is the arguments of the macro call. +    MacroCall(&'a str),      Try,  } @@ -218,6 +220,16 @@ fn expr_call(i: &str) -> IResult<&str, Suffix<'_>> {      map(arguments, Suffix::Call)(i)  } +fn expr_macro(i: &str) -> IResult<&str, Suffix<'_>> { +    preceded( +        pair(ws(char('!')), char('(')), +        cut(terminated( +            map(recognize(nested_parenthesis), Suffix::MacroCall), +            char(')'), +        )), +    )(i) +} +  fn expr_try(i: &str) -> IResult<&str, Suffix<'_>> {      map(preceded(take_till(not_ws), char('?')), |_| Suffix::Try)(i)  } @@ -256,28 +268,26 @@ fn expr_prefix(i: &str) -> IResult<&str, Expr<'_>> {  fn expr_suffix(i: &str) -> IResult<&str, Expr<'_>> {      let (mut i, mut expr) = expr_single(i)?;      loop { -        let (j, suffix) = opt(alt((expr_attr, expr_index, expr_call, expr_try)))(i)?; -        i = j; +        let (j, suffix) = opt(alt(( +            expr_attr, expr_index, expr_call, expr_try, expr_macro, +        )))(i)?;          match suffix {              Some(Suffix::Attr(attr)) => expr = Expr::Attr(expr.into(), attr),              Some(Suffix::Index(index)) => expr = Expr::Index(expr.into(), index.into()),              Some(Suffix::Call(args)) => expr = Expr::Call(expr.into(), args),              Some(Suffix::Try) => expr = Expr::Try(expr.into()), +            Some(Suffix::MacroCall(args)) => match expr { +                Expr::Path(path) => expr = Expr::RustMacro(path, args), +                Expr::Var(name) => expr = Expr::RustMacro(vec![name], args), +                _ => return Err(nom::Err::Failure(error_position!(i, ErrorKind::Tag))), +            },              None => break,          } +        i = j;      }      Ok((i, expr))  } -fn macro_arguments(i: &str) -> IResult<&str, &str> { -    delimited(char('('), recognize(nested_parenthesis), char(')'))(i) -} - -fn expr_rust_macro(i: &str) -> IResult<&str, Expr<'_>> { -    let (i, (mname, _, args)) = tuple((identifier, char('!'), macro_arguments))(i)?; -    Ok((i, Expr::RustMacro(mname, args))) -} -  macro_rules! expr_prec_layer {      ( $name:ident, $inner:ident, $op:expr ) => {          fn $name(i: &str) -> IResult<&str, Expr<'_>> { diff --git a/askama_derive/src/parser/tests.rs b/askama_derive/src/parser/tests.rs index 91bb09b..801e787 100644 --- a/askama_derive/src/parser/tests.rs +++ b/askama_derive/src/parser/tests.rs @@ -222,6 +222,51 @@ fn test_parse_root_path() {  }  #[test] +fn test_rust_macro() { +    let syntax = Syntax::default(); +    assert_eq!( +        super::parse("{{ vec!(1, 2, 3) }}", &syntax).unwrap(), +        vec![Node::Expr( +            Ws(None, None), +            Expr::RustMacro(vec!["vec"], "1, 2, 3",), +        )], +    ); +    assert_eq!( +        super::parse("{{ alloc::vec!(1, 2, 3) }}", &syntax).unwrap(), +        vec![Node::Expr( +            Ws(None, None), +            Expr::RustMacro(vec!["alloc", "vec"], "1, 2, 3",), +        )], +    ); +    assert_eq!( +        super::parse("{{a!()}}", &syntax).unwrap(), +        [Node::Expr(Ws(None, None), Expr::RustMacro(vec!["a"], ""))], +    ); +    assert_eq!( +        super::parse("{{a !()}}", &syntax).unwrap(), +        [Node::Expr(Ws(None, None), Expr::RustMacro(vec!["a"], ""))], +    ); +    assert_eq!( +        super::parse("{{a! ()}}", &syntax).unwrap(), +        [Node::Expr(Ws(None, None), Expr::RustMacro(vec!["a"], ""))], +    ); +    assert_eq!( +        super::parse("{{a ! ()}}", &syntax).unwrap(), +        [Node::Expr(Ws(None, None), Expr::RustMacro(vec!["a"], ""))], +    ); +    assert_eq!( +        super::parse("{{A!()}}", &syntax).unwrap(), +        [Node::Expr(Ws(None, None), Expr::RustMacro(vec!["A"], ""),)], +    ); +    assert_eq!( +        &*super::parse("{{a.b.c!( hello )}}", &syntax) +            .unwrap_err() +            .msg, +        "problems parsing template source at row 1, column 7 near:\n\"!( hello )}}\"", +    ); +} + +#[test]  fn change_delimiters_parse_filter() {      let syntax = Syntax {          expr_start: "{=", | 
