diff --git a/askama_parser/src/expr.rs b/askama_parser/src/expr.rs index fb825305..5d59edd2 100644 --- a/askama_parser/src/expr.rs +++ b/askama_parser/src/expr.rs @@ -33,11 +33,11 @@ fn expr_prec_layer<'a>( let start = *i; let mut expr = inner(i, level)?; - let mut i_before = *i; let mut level_guard = level.guard(); - while let Some((op, rhs)) = opt((ws(op), |i: &mut _| inner(i, level))).parse_next(i)? { + while let Some(((op, rhs), i_before)) = + opt((ws(op), |i: &mut _| inner(i, level)).with_taken()).parse_next(i)? + { level_guard.nest(i_before)?; - i_before = *i; expr = WithSpan::new(Expr::BinOp(Box::new(BinOp { op, lhs: expr, rhs })), start); } @@ -480,12 +480,12 @@ impl<'a> Expr<'a> { let mut res = Self::prefix(i, level)?; let mut level_guard = level.guard(); - let mut i_before = *i; - while let Some(mut filter) = opt(|i: &mut _| filter(i, level)).parse_next(i)? { + while let Some((mut filter, i_before)) = + opt(ws((|i: &mut _| filter(i, level)).with_taken())).parse_next(i)? + { level_guard.nest(i_before)?; filter.arguments.insert(0, res); res = WithSpan::new(Self::Filter(Box::new(filter)), i_before); - i_before = *i; } Ok(res) } @@ -498,11 +498,11 @@ impl<'a> Expr<'a> { // to stack overflows in drop glue when the AST is very deep. let mut level_guard = level.guard(); let mut ops = vec![]; - let mut i_before = *i; - while let Some(op) = opt(ws(alt(("!", "-", "*", "&")))).parse_next(i)? { + while let Some((op, i_before)) = + opt(ws(alt(("!", "-", "*", "&")).with_taken())).parse_next(i)? + { level_guard.nest(i_before)?; ops.push(op); - i_before = *i; } let mut expr = Suffix::parse(i, level)?; @@ -706,30 +706,22 @@ impl<'a> Suffix<'a> { fn parse(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, WithSpan<'a, Expr<'a>>> { let mut level_guard = level.guard(); let mut expr = Expr::single(i, level)?; - let mut right = opt(alt(( + let mut right = alt(( |i: &mut _| Self::associated_item(i, level), |i: &mut _| Self::index(i, level), |i: &mut _| Self::call(i, level), Self::r#try, Self::r#macro, - ))); - loop { - let before_suffix = *i; - let suffix = right.parse_next(i)?; - let Some(suffix) = suffix else { - break; - }; - level_guard.nest(before_suffix)?; - + )); + while let Some((suffix, i_before)) = opt(right.by_ref().with_taken()).parse_next(i)? { + level_guard.nest(i_before)?; match suffix { Self::AssociatedItem(associated_item) => { - expr = WithSpan::new( - Expr::AssociatedItem(expr.into(), associated_item), - before_suffix, - ) + expr = + WithSpan::new(Expr::AssociatedItem(expr.into(), associated_item), i_before) } Self::Index(index) => { - expr = WithSpan::new(Expr::Index(expr.into(), index.into()), before_suffix); + expr = WithSpan::new(Expr::Index(expr.into(), index.into()), i_before); } Self::Call { args, generics } => { expr = WithSpan::new( @@ -738,21 +730,21 @@ impl<'a> Suffix<'a> { args, generics, })), - before_suffix, + i_before, ) } - Self::Try => expr = WithSpan::new(Expr::Try(expr.into()), before_suffix), + Self::Try => expr = WithSpan::new(Expr::Try(expr.into()), i_before), Self::MacroCall(args) => match expr.inner { Expr::Path(path) => { ensure_macro_name(path.last().unwrap())?; - expr = WithSpan::new(Expr::RustMacro(path, args), before_suffix) + expr = WithSpan::new(Expr::RustMacro(path, args), i_before) } Expr::Var(name) => { ensure_macro_name(name)?; - expr = WithSpan::new(Expr::RustMacro(vec![name], args), before_suffix) + expr = WithSpan::new(Expr::RustMacro(vec![name], args), i_before) } _ => { - return Err(ErrMode::from_input(&before_suffix).cut()); + return Err(ErrMode::from_input(&i_before).cut()); } }, } diff --git a/askama_parser/src/lib.rs b/askama_parser/src/lib.rs index 280d669c..ec61fc56 100644 --- a/askama_parser/src/lib.rs +++ b/askama_parser/src/lib.rs @@ -1163,7 +1163,7 @@ impl LevelGuard<'_> { fn filter<'a>(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, Filter<'a>> { preceded( - ws(('|', not('|'))), + ('|', not('|')), cut_err(|i: &mut _| Filter::parse(i, level)), ) .parse_next(i) diff --git a/askama_parser/src/node.rs b/askama_parser/src/node.rs index 2820e5f3..9802fbbf 100644 --- a/askama_parser/src/node.rs +++ b/askama_parser/src/node.rs @@ -771,14 +771,14 @@ impl<'a> FilterBlock<'a> { .insert(0, WithSpan::new(Expr::FilterSource, start)); let mut level_guard = s.level.guard(); - let mut i_before = *i; - while let Some(mut filter) = opt(|i: &mut _| filter(i, s.level)).parse_next(i)? { + while let Some((mut filter, i_before)) = + opt(ws((|i: &mut _| filter(i, s.level)).with_taken())).parse_next(i)? + { level_guard.nest(i_before)?; filter .arguments .insert(0, WithSpan::new(Expr::Filter(Box::new(res)), i_before)); res = filter; - i_before = *i; } Ok(res) } diff --git a/testing/tests/ui/custom-filter-with-named-arg.stderr b/testing/tests/ui/custom-filter-with-named-arg.stderr index 98efb341..3ea7cc27 100644 --- a/testing/tests/ui/custom-filter-with-named-arg.stderr +++ b/testing/tests/ui/custom-filter-with-named-arg.stderr @@ -1,6 +1,6 @@ error: `do_nothing` filter cannot accept named arguments - --> CustomFiltersCannotTakeNamedArguments.txt:1:3 - "a | do_nothing(absolutely = \"nothing\") }}" + --> CustomFiltersCannotTakeNamedArguments.txt:1:5 + "| do_nothing(absolutely = \"nothing\") }}" --> tests/ui/custom-filter-with-named-arg.rs:12:21 | 12 | #[template(source = r#"{{ a | do_nothing(absolutely = "nothing") }}"#, ext = "txt")] diff --git a/testing/tests/ui/filter-recursion.stderr b/testing/tests/ui/filter-recursion.stderr index bab7ea16..912287ae 100644 --- a/testing/tests/ui/filter-recursion.stderr +++ b/testing/tests/ui/filter-recursion.stderr @@ -1,6 +1,6 @@ error: your template code is too deeply nested, or the last expression is too complex - --> testing/templates/filter-recursion.html:1:275 - "|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A||A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A"... + --> testing/templates/filter-recursion.html:1:277 + "|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A||A|A|AA|A|A|A|A|AA|A|A|A|A|AA|A|A|A"... --> tests/ui/filter-recursion.rs:4:19 | 4 | #[template(path = "filter-recursion.html")] diff --git a/testing/tests/ui/no-such-escaper.stderr b/testing/tests/ui/no-such-escaper.stderr index 315b375c..df362f90 100644 --- a/testing/tests/ui/no-such-escaper.stderr +++ b/testing/tests/ui/no-such-escaper.stderr @@ -1,6 +1,6 @@ error: invalid escaper `latex` for `escape` filter. The available extensions are: "", "askama", "htm", "html", "j2", "jinja", "jinja2", "md", "none", "rinja", "svg", "txt", "xml", "yml" - --> LocalEscaper.html:1:38 - "text|escape(\"latex\")}}`." + --> LocalEscaper.html:1:42 + "|escape(\"latex\")}}`." --> tests/ui/no-such-escaper.rs:6:14 | 6 | source = r#"In LaTeX you write `{{text}}` like `{{text|escape("latex")}}`."#, diff --git a/testing/tests/ui/truncate.stderr b/testing/tests/ui/truncate.stderr index fe946dfd..ce53fd36 100644 --- a/testing/tests/ui/truncate.stderr +++ b/testing/tests/ui/truncate.stderr @@ -1,6 +1,6 @@ error: `length` argument is missing when calling `truncate` filter; its arguments are: (length) - --> NoArgument.html:1:3 - "text | truncate }}" + --> NoArgument.html:1:8 + "| truncate }}" --> tests/ui/truncate.rs:4:21 | 4 | #[template(source = r#"{{ text | truncate }}"#, ext = "html")] diff --git a/testing/tests/ui/values.stderr b/testing/tests/ui/values.stderr index 059b1721..0d83a14a 100644 --- a/testing/tests/ui/values.stderr +++ b/testing/tests/ui/values.stderr @@ -1,14 +1,14 @@ error: `value` filter expects one generic, found 0 - --> A.html:1:18 - "\"a\"|value %}{% endif %}" + --> A.html:1:21 + "|value %}{% endif %}" --> tests/ui/values.rs:6:14 | 6 | source = r#"{% if let Ok(x) = "a"|value %}{% endif %}"#, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `value` filter expects one generic, found 2 - --> B.html:1:18 - "\"a\"|value:: %}{% endif %}" + --> B.html:1:21 + "|value:: %}{% endif %}" --> tests/ui/values.rs:13:14 | 13 | source = r#"{% if let Ok(x) = "a"|value:: %}{% endif %}"#,