aboutsummaryrefslogtreecommitdiffstats
path: root/askama_derive
diff options
context:
space:
mode:
Diffstat (limited to 'askama_derive')
-rw-r--r--askama_derive/src/generator.rs18
-rw-r--r--askama_derive/src/parser.rs22
2 files changed, 39 insertions, 1 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index 0e86a27..5ec2238 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -598,6 +598,7 @@ impl<'a> Generator<'a> {
Expr::Filter(name, ref args) => self.visit_filter(name, args, code),
Expr::Unary(op, ref inner) => self.visit_unary(op, inner, code),
Expr::BinOp(op, ref left, ref right) => self.visit_binop(op, left, right, code),
+ Expr::Range(op, ref left, ref right) => self.visit_range(op, left, right, code),
Expr::Group(ref inner) => self.visit_group(inner, code),
Expr::MethodCall(ref obj, method, ref args) => {
self.visit_method_call(obj, method, args, code)
@@ -762,6 +763,23 @@ impl<'a> Generator<'a> {
DisplayWrap::Unwrapped
}
+ fn visit_range(
+ &mut self,
+ op: &str,
+ left: &Option<Box<Expr>>,
+ right: &Option<Box<Expr>>,
+ code: &mut String,
+ ) -> DisplayWrap {
+ if let Some(left) = left {
+ self.visit_expr(left, code);
+ }
+ code.push_str(op);
+ if let Some(right) = right {
+ self.visit_expr(right, code);
+ }
+ DisplayWrap::Unwrapped
+ }
+
fn visit_binop(
&mut self,
op: &str,
diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs
index c8bbb96..5694d4e 100644
--- a/askama_derive/src/parser.rs
+++ b/askama_derive/src/parser.rs
@@ -16,6 +16,7 @@ pub enum Expr<'a> {
Filter(&'a str, Vec<Expr<'a>>),
Unary(&'a str, Box<Expr<'a>>),
BinOp(&'a str, Box<Expr<'a>>, Box<Expr<'a>>),
+ Range(&'a str, Option<Box<Expr<'a>>>, Option<Box<Expr<'a>>>),
Group(Box<Expr<'a>>),
MethodCall(Box<Expr<'a>>, &'a str, Vec<Expr<'a>>),
}
@@ -422,7 +423,26 @@ expr_prec_layer!(expr_compare, expr_bor,
"==", "!=", ">=", ">", "<=", "<"
);
expr_prec_layer!(expr_and, expr_compare, "&&");
-expr_prec_layer!(expr_any, expr_and, "||");
+expr_prec_layer!(expr_or, expr_and, "||");
+
+named!(range_right<Input, Expr>, do_parse!(
+ ws!(tag_s!("..")) >>
+ incl: opt!(ws!(tag_s!("="))) >>
+ right: opt!(expr_or) >>
+ (Expr::Range(if incl.is_some() { "..=" } else { ".." }, None, right.map(|v| Box::new(v))))
+));
+
+named!(expr_any<Input, Expr>, alt!(
+ range_right |
+ do_parse!(
+ left: expr_or >>
+ rest: range_right >> (match rest {
+ Expr::Range(op, _, right) => Expr::Range(op, Some(Box::new(left)), right),
+ _ => unreachable!(),
+ })
+ ) |
+ expr_or
+));
named!(expr_node<Input, Node>, do_parse!(
tag_s!("{{") >>