parser: introduce askama_parser::expr::Range

This commit is contained in:
René Kijewski 2025-06-23 18:11:28 +02:00 committed by René Kijewski
parent 9f882e2ca7
commit 49d4397f51
3 changed files with 30 additions and 17 deletions

View File

@ -76,8 +76,8 @@ impl<'a> Generator<'a, '_> {
}) => self.visit_filter(ctx, buf, name, arguments, generics, expr.span())?,
Expr::Unary(op, ref inner) => self.visit_unary(ctx, buf, op, inner)?,
Expr::BinOp(ref v) => self.visit_binop(ctx, buf, v.op, &v.lhs, &v.rhs)?,
Expr::Range(op, ref left, ref right) => {
self.visit_range(ctx, buf, op, left.as_deref(), right.as_deref())?
Expr::Range(ref v) => {
self.visit_range(ctx, buf, v.op, v.lhs.as_ref(), v.rhs.as_ref())?
}
Expr::Group(ref inner) => self.visit_group(ctx, buf, inner)?,
Expr::Call {

View File

@ -199,7 +199,7 @@ impl<'a> Generator<'a, '_> {
| Expr::Attr(_, _)
| Expr::Index(_, _)
| Expr::Filter(_)
| Expr::Range(_, _, _)
| Expr::Range(_)
| Expr::Call { .. }
| Expr::RustMacro(_, _)
| Expr::Try(_)
@ -1649,9 +1649,8 @@ fn is_cacheable(expr: &WithSpan<'_, Expr<'_>>) -> bool {
Expr::Unary(_, arg) => is_cacheable(arg),
Expr::BinOp(v) => is_cacheable(&v.lhs) && is_cacheable(&v.rhs),
Expr::IsDefined(_) | Expr::IsNotDefined(_) => true,
Expr::Range(_, lhs, rhs) => {
lhs.as_ref().is_none_or(|v| is_cacheable(v))
&& rhs.as_ref().is_none_or(|v| is_cacheable(v))
Expr::Range(v) => {
v.lhs.as_ref().is_none_or(is_cacheable) && v.rhs.as_ref().is_none_or(is_cacheable)
}
Expr::Group(arg) => is_cacheable(arg),
Expr::Tuple(args) => args.iter().all(is_cacheable),

View File

@ -101,11 +101,11 @@ fn check_expr<'a>(expr: &WithSpan<'a, Expr<'a>>, allowed: Allowed) -> Result<(),
check_expr(&v.lhs, Allowed::default())?;
check_expr(&v.rhs, Allowed::default())
}
Expr::Range(_, elem1, elem2) => {
if let Some(elem1) = elem1 {
Expr::Range(v) => {
if let Some(elem1) = v.lhs.as_ref() {
check_expr(elem1, Allowed::default())?;
}
if let Some(elem2) = elem2 {
if let Some(elem2) = v.rhs.as_ref() {
check_expr(elem2, Allowed::default())?;
}
Ok(())
@ -170,11 +170,7 @@ pub enum Expr<'a> {
NamedArgument(&'a str, Box<WithSpan<'a, Expr<'a>>>),
Unary(&'a str, Box<WithSpan<'a, Expr<'a>>>),
BinOp(Box<BinOp<'a>>),
Range(
&'a str,
Option<Box<WithSpan<'a, Expr<'a>>>>,
Option<Box<WithSpan<'a, Expr<'a>>>>,
),
Range(Box<Range<'a>>),
Group(Box<WithSpan<'a, Expr<'a>>>),
Tuple(Vec<WithSpan<'a, Expr<'a>>>),
Call {
@ -196,6 +192,13 @@ pub enum Expr<'a> {
ArgumentPlaceholder,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Range<'a> {
pub op: &'a str,
pub lhs: Option<WithSpan<'a, Expr<'a>>>,
pub rhs: Option<WithSpan<'a, Expr<'a>>>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct BinOp<'a> {
pub op: &'a str,
@ -300,12 +303,23 @@ impl<'a> Expr<'a> {
};
let expr = alt((
range_right.map(move |(op, right)| {
WithSpan::new(Self::Range(op, None, right.map(Box::new)), start)
WithSpan::new(
Self::Range(Box::new(Range {
op,
lhs: None,
rhs: right,
})),
start,
)
}),
(move |i: &mut _| Self::or(i, level), opt(range_right)).map(move |(left, right)| {
match right {
Some((op, right)) => WithSpan::new(
Self::Range(op, Some(Box::new(left)), right.map(Box::new)),
Self::Range(Box::new(Range {
op,
lhs: Some(left),
rhs: right,
})),
start,
),
None => left,
@ -611,7 +625,7 @@ impl<'a> Expr<'a> {
| Self::RustMacro(_, _)
| Self::As(_, _)
| Self::Call { .. }
| Self::Range(_, _, _)
| Self::Range(_)
| Self::Try(_)
| Self::NamedArgument(_, _)
| Self::Filter(_)