aboutsummaryrefslogtreecommitdiffstats
path: root/askama_derive
diff options
context:
space:
mode:
Diffstat (limited to 'askama_derive')
-rw-r--r--askama_derive/src/generator.rs10
-rw-r--r--askama_derive/src/parser.rs63
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, "||");