From 447aab0f105a71f44891751f94a5cc9f508f774d Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 3 Jul 2023 10:14:23 +0200 Subject: parser: move Expr parser helpers into callers --- askama_parser/src/expr.rs | 107 +++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 53 deletions(-) (limited to 'askama_parser') diff --git a/askama_parser/src/expr.rs b/askama_parser/src/expr.rs index 4bed4af..ef5c5e2 100644 --- a/askama_parser/src/expr.rs +++ b/askama_parser/src/expr.rs @@ -102,6 +102,12 @@ impl<'a> Expr<'a> { expr_prec_layer!(muldivmod, filtered, "*", "/", "%"); fn filtered(i: &'a str) -> IResult<&'a str, Self> { + fn filter(i: &str) -> IResult<&str, (&str, Option>>)> { + let (i, (_, fname, args)) = + tuple((char('|'), ws(identifier), opt(Expr::arguments)))(i)?; + Ok((i, (fname, args))) + } + let (i, (obj, filters)) = tuple((Self::prefix, many0(filter)))(i)?; let mut res = obj; @@ -242,6 +248,54 @@ impl<'a> Suffix<'a> { } fn r#macro(i: &'a str) -> IResult<&'a str, Self> { + 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 + ))) + } + } + preceded( pair(ws(char('!')), char('(')), cut(terminated( @@ -276,56 +330,3 @@ impl<'a> Suffix<'a> { map(preceded(take_till(not_ws), char('?')), |_| Self::Try)(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 filter(i: &str) -> IResult<&str, (&str, Option>>)> { - let (i, (_, fname, args)) = tuple((char('|'), ws(identifier), opt(Expr::arguments)))(i)?; - Ok((i, (fname, args))) -} -- cgit