aboutsummaryrefslogtreecommitdiffstats
path: root/askama_parser/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'askama_parser/src/expr.rs')
-rw-r--r--askama_parser/src/expr.rs142
1 files changed, 71 insertions, 71 deletions
diff --git a/askama_parser/src/expr.rs b/askama_parser/src/expr.rs
index 7896981..415b8f4 100644
--- a/askama_parser/src/expr.rs
+++ b/askama_parser/src/expr.rs
@@ -11,6 +11,39 @@ use nom::{error_position, IResult};
use super::{bool_lit, char_lit, identifier, not_ws, num_lit, path, str_lit, ws};
+macro_rules! expr_prec_layer {
+ ( $name:ident, $inner:ident, $op:expr ) => {
+ fn $name(i: &'a str) -> IResult<&'a str, Self> {
+ let (i, left) = Self::$inner(i)?;
+ let (i, right) = many0(pair(
+ ws(tag($op)),
+ Self::$inner,
+ ))(i)?;
+ Ok((
+ i,
+ right.into_iter().fold(left, |left, (op, right)| {
+ Self::BinOp(op, Box::new(left), Box::new(right))
+ }),
+ ))
+ }
+ };
+ ( $name:ident, $inner:ident, $( $op:expr ),+ ) => {
+ fn $name(i: &'a str) -> IResult<&'a str, Self> {
+ let (i, left) = Self::$inner(i)?;
+ let (i, right) = many0(pair(
+ ws(alt(($( tag($op) ),+,))),
+ Self::$inner,
+ ))(i)?;
+ Ok((
+ i,
+ right.into_iter().fold(left, |left, (op, right)| {
+ Self::BinOp(op, Box::new(left), Box::new(right))
+ }),
+ ))
+ }
+ }
+}
+
#[derive(Debug, PartialEq)]
pub enum Expr<'a> {
BoolLit(&'a str),
@@ -43,13 +76,13 @@ impl<'a> Expr<'a> {
}
pub(super) fn parse(i: &'a str) -> IResult<&'a str, Self> {
- let range_right = |i| pair(ws(alt((tag("..="), tag("..")))), opt(expr_or))(i);
+ let range_right = |i| pair(ws(alt((tag("..="), tag("..")))), opt(Self::or))(i);
alt((
map(range_right, |(op, right)| {
Self::Range(op, None, right.map(Box::new))
}),
map(
- pair(expr_or, opt(range_right)),
+ pair(Self::or, opt(range_right)),
|(left, right)| match right {
Some((op, right)) => Self::Range(op, Some(Box::new(left)), right.map(Box::new)),
None => left,
@@ -57,6 +90,42 @@ impl<'a> Expr<'a> {
),
))(i)
}
+
+ expr_prec_layer!(or, and, "||");
+ expr_prec_layer!(and, compare, "&&");
+ expr_prec_layer!(compare, bor, "==", "!=", ">=", ">", "<=", "<");
+ expr_prec_layer!(bor, bxor, "|");
+ expr_prec_layer!(bxor, band, "^");
+ expr_prec_layer!(band, shifts, "&");
+ expr_prec_layer!(shifts, addsub, ">>", "<<");
+ expr_prec_layer!(addsub, muldivmod, "+", "-");
+ expr_prec_layer!(muldivmod, filtered, "*", "/", "%");
+
+ fn filtered(i: &'a str) -> IResult<&'a str, Self> {
+ let (i, (obj, filters)) = tuple((Self::prefix, many0(filter)))(i)?;
+
+ let mut res = obj;
+ for (fname, args) in filters {
+ res = Self::Filter(fname, {
+ let mut args = match args {
+ Some(inner) => inner,
+ None => Vec::new(),
+ };
+ args.insert(0, res);
+ args
+ });
+ }
+
+ Ok((i, res))
+ }
+
+ fn prefix(i: &'a str) -> IResult<&'a str, Self> {
+ let (i, (ops, mut expr)) = pair(many0(ws(alt((tag("!"), tag("-"))))), Suffix::parse)(i)?;
+ for op in ops.iter().rev() {
+ expr = Self::Unary(op, Box::new(expr));
+ }
+ Ok((i, expr))
+ }
}
fn expr_bool_lit(i: &str) -> IResult<&str, Expr<'_>> {
@@ -260,72 +329,3 @@ fn filter(i: &str) -> IResult<&str, (&str, Option<Vec<Expr<'_>>>)> {
let (i, (_, fname, args)) = tuple((char('|'), ws(identifier), opt(Expr::arguments)))(i)?;
Ok((i, (fname, args)))
}
-
-fn expr_filtered(i: &str) -> IResult<&str, Expr<'_>> {
- let (i, (obj, filters)) = tuple((expr_prefix, many0(filter)))(i)?;
-
- let mut res = obj;
- for (fname, args) in filters {
- res = Expr::Filter(fname, {
- let mut args = match args {
- Some(inner) => inner,
- None => Vec::new(),
- };
- args.insert(0, res);
- args
- });
- }
-
- Ok((i, res))
-}
-
-fn expr_prefix(i: &str) -> IResult<&str, Expr<'_>> {
- let (i, (ops, mut expr)) = pair(many0(ws(alt((tag("!"), tag("-"))))), Suffix::parse)(i)?;
- for op in ops.iter().rev() {
- expr = Expr::Unary(op, Box::new(expr));
- }
- Ok((i, expr))
-}
-
-macro_rules! expr_prec_layer {
- ( $name:ident, $inner:ident, $op:expr ) => {
- fn $name(i: &str) -> IResult<&str, Expr<'_>> {
- let (i, left) = $inner(i)?;
- let (i, right) = many0(pair(
- ws(tag($op)),
- $inner,
- ))(i)?;
- Ok((
- i,
- right.into_iter().fold(left, |left, (op, right)| {
- Expr::BinOp(op, Box::new(left), Box::new(right))
- }),
- ))
- }
- };
- ( $name:ident, $inner:ident, $( $op:expr ),+ ) => {
- fn $name(i: &str) -> IResult<&str, Expr<'_>> {
- let (i, left) = $inner(i)?;
- let (i, right) = many0(pair(
- ws(alt(($( tag($op) ),+,))),
- $inner,
- ))(i)?;
- Ok((
- i,
- right.into_iter().fold(left, |left, (op, right)| {
- Expr::BinOp(op, Box::new(left), Box::new(right))
- }),
- ))
- }
- }
-}
-
-expr_prec_layer!(expr_muldivmod, expr_filtered, "*", "/", "%");
-expr_prec_layer!(expr_addsub, expr_muldivmod, "+", "-");
-expr_prec_layer!(expr_shifts, expr_addsub, ">>", "<<");
-expr_prec_layer!(expr_band, expr_shifts, "&");
-expr_prec_layer!(expr_bxor, expr_band, "^");
-expr_prec_layer!(expr_bor, expr_bxor, "|");
-expr_prec_layer!(expr_compare, expr_bor, "==", "!=", ">=", ">", "<=", "<");
-expr_prec_layer!(expr_and, expr_compare, "&&");
-expr_prec_layer!(expr_or, expr_and, "||");