aboutsummaryrefslogtreecommitdiffstats
path: root/askama_parser/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--askama_parser/src/expr.rs52
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)
}