diff options
Diffstat (limited to '')
-rw-r--r-- | askama_parser/src/expr.rs | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/askama_parser/src/expr.rs b/askama_parser/src/expr.rs index 03620e7..c5c2351 100644 --- a/askama_parser/src/expr.rs +++ b/askama_parser/src/expr.rs @@ -9,9 +9,7 @@ use nom::multi::{fold_many0, many0, separated_list0, separated_list1}; use nom::sequence::{delimited, pair, preceded, terminated, tuple}; use nom::{error_position, IResult}; -use super::{ - bool_lit, char_lit, identifier, nested_parenthesis, not_ws, num_lit, path, str_lit, ws, -}; +use super::{bool_lit, char_lit, identifier, not_ws, num_lit, path, str_lit, ws}; #[derive(Debug, PartialEq)] pub enum Expr<'a> { @@ -159,6 +157,54 @@ fn expr_macro(i: &str) -> IResult<&str, Suffix<'_>> { )(i) } +fn nested_parenthesis(i: &str) -> IResult<&str, ()> { + let mut nested = 0; + let mut last = 0; + let mut in_str = false; + let mut escaped = false; + + for (i, b) in i.chars().enumerate() { + if !(b == '(' || b == ')') || !in_str { + match b { + '(' => nested += 1, + ')' => { + if nested == 0 { + last = i; + break; + } + nested -= 1; + } + '"' => { + if in_str { + if !escaped { + in_str = false; + } + } else { + in_str = true; + } + } + '\\' => { + escaped = !escaped; + } + _ => (), + } + } + + if escaped && b != '\\' { + escaped = false; + } + } + + if nested == 0 { + Ok((&i[last..], ())) + } else { + Err(nom::Err::Error(error_position!( + i, + ErrorKind::SeparatedNonEmptyList + ))) + } +} + fn expr_try(i: &str) -> IResult<&str, Suffix<'_>> { map(preceded(take_till(not_ws), char('?')), |_| Suffix::Try)(i) } |