diff options
Diffstat (limited to 'askama_derive')
-rw-r--r-- | askama_derive/src/generator.rs | 10 | ||||
-rw-r--r-- | askama_derive/src/parser.rs | 63 |
2 files changed, 63 insertions, 10 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index 047e975..95a7d17 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -1,6 +1,8 @@ use super::{get_template_source, Context, Heritage}; use crate::input::TemplateInput; -use crate::parser::{Cond, Expr, MatchParameter, MatchParameters, MatchVariant, Node, Target, When, WS}; +use crate::parser::{ + Cond, Expr, MatchParameter, MatchParameters, MatchVariant, Node, Target, When, WS, +}; use askama_shared::filters; use proc_macro2::Span; @@ -773,14 +775,14 @@ impl<'a> Generator<'a> { Expr::MethodCall(ref obj, method, ref args) => { self.visit_method_call(buf, obj, method, args) } - Expr::RustMacro(name, ref args) => self.visit_rust_macro(buf, name, args), + Expr::RustMacro(name, args) => self.visit_rust_macro(buf, name, args), } } - fn visit_rust_macro(&mut self, buf: &mut Buffer, name: &str, args: &[Expr]) -> DisplayWrap { + fn visit_rust_macro(&mut self, buf: &mut Buffer, name: &str, args: &str) -> DisplayWrap { buf.write(name); buf.write("!("); - self._visit_args(buf, args); + buf.write(args); buf.write(")"); DisplayWrap::Unwrapped diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs index 7968ac1..81935f6 100644 --- a/askama_derive/src/parser.rs +++ b/askama_derive/src/parser.rs @@ -21,7 +21,7 @@ pub enum Expr<'a> { Range(&'a str, Option<Box<Expr<'a>>>, Option<Box<Expr<'a>>>), Group(Box<Expr<'a>>), MethodCall(Box<Expr<'a>>, &'a str, Vec<Expr<'a>>), - RustMacro(&'a str, Vec<Expr<'a>>), + RustMacro(&'a str, &'a str), } #[derive(Debug)] @@ -302,6 +302,60 @@ named!(arguments<Input, Vec<Expr>>, do_parse!( (args.unwrap_or_default()) )); +named!(macro_arguments<Input, &str>, + delimited!(char!('('), nested_parenthesis, char!(')')) +); + +fn nested_parenthesis(i: Input) -> Result<(Input, &str), nom::Err<Input>> { + let mut nested = 0; + let mut last = 0; + let mut in_str = false; + let mut escaped = false; + + for (i, b) in i.iter().enumerate() { + if !(*b == b'(' || *b == b')') || !in_str { + match *b { + b'(' => { + nested += 1 + }, + b')' => { + if nested == 0 { + last = i; + break; + } + nested -= 1; + }, + b'"' => { + if in_str { + if !escaped { + in_str = false; + } + } else { + in_str = true; + } + }, + b'\\' => { + escaped = !escaped; + }, + _ => (), + } + } + + if escaped && *b != b'\\' { + escaped = false; + } + } + + if nested == 0 { + Ok((Input(&i[last..]), str::from_utf8(&i[..last]).unwrap())) + } else { + Err(nom::Err::Error(error_position!( + i, + nom::ErrorKind::Custom(0) + ))) + } +} + named!(parameters<Input, Vec<&str>>, do_parse!( tag!("(") >> vals: opt!(do_parse!( @@ -477,11 +531,10 @@ named!(expr_unary<Input, Expr>, do_parse!( named!(rust_macro<Input, Expr>, do_parse!( mname: identifier >> tag!("!") >> - args: arguments >> + args: macro_arguments >> (Expr::RustMacro(mname, args)) )); - macro_rules! expr_prec_layer { ( $name:ident, $inner:ident, $( $op:expr ),* ) => { named!($name<Input, Expr>, do_parse!( @@ -503,9 +556,7 @@ expr_prec_layer!(expr_shifts, expr_addsub, ">>", "<<"); expr_prec_layer!(expr_band, expr_shifts, "&"); expr_prec_layer!(expr_bxor, expr_band, "^"); expr_prec_layer!(expr_bor, expr_bxor, "|"); -expr_prec_layer!(expr_compare, expr_bor, - "==", "!=", ">=", ">", "<=", "<" -); +expr_prec_layer!(expr_compare, expr_bor, "==", "!=", ">=", ">", "<=", "<"); expr_prec_layer!(expr_and, expr_compare, "&&"); expr_prec_layer!(expr_or, expr_and, "||"); |