From cc51d201ab9e7ba958363d1f74b7bfd4dd12fecf Mon Sep 17 00:00:00 2001 From: Anthony Nowell Date: Thu, 5 Oct 2017 02:47:36 -0600 Subject: support literals in match arms --- askama_shared/src/generator.rs | 24 +++++++++++++++---- askama_shared/src/parser.rs | 54 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 67 insertions(+), 11 deletions(-) (limited to 'askama_shared/src') diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs index 6fca3fb..0c8b1e2 100644 --- a/askama_shared/src/generator.rs +++ b/askama_shared/src/generator.rs @@ -1,6 +1,6 @@ use filters; use input::TemplateInput; -use parser::{self, Cond, Expr, Macro, Node, Target, When, WS}; +use parser::{self, Cond, Expr, Macro, MatchParameter, Node, Target, When, WS}; use path; use quote::{Tokens, ToTokens}; @@ -445,15 +445,20 @@ impl<'a> Generator<'a> { for arm in arms { let &(ref ws, ref variant, ref params, ref body) = arm; self.locals.push(); - self.write(variant); + match *variant { + Some(ref param) => { self.visit_match_param(param); }, + None => self.write("_"), + }; if params.len() > 0 { self.write("("); for (i, param) in params.iter().enumerate() { - self.locals.insert(param); + if let MatchParameter::Name(ref p) = *param { + self.locals.insert(p); + } if i > 0 { self.write(", "); } - self.write(param); + self.visit_match_param(param); } self.write(")"); } @@ -624,6 +629,17 @@ impl<'a> Generator<'a> { } } + fn visit_match_param(&mut self, param: &MatchParameter) -> DisplayWrap { + match *param { + MatchParameter::NumLit(s) => self.visit_num_lit(s), + MatchParameter::StrLit(s) => self.visit_str_lit(s), + MatchParameter::Name(s) => { + self.write(s); + DisplayWrap::Unwrapped + } + } + } + fn visit_filter(&mut self, name: &str, args: &[Expr]) -> DisplayWrap { if name == "format" { self._visit_format_filter(args); diff --git a/askama_shared/src/parser.rs b/askama_shared/src/parser.rs index 6ea5ffd..76125ef 100644 --- a/askama_shared/src/parser.rs +++ b/askama_shared/src/parser.rs @@ -15,6 +15,13 @@ pub enum Expr<'a> { MethodCall(Box>, &'a str, Vec>), } +#[derive(Debug)] +pub enum MatchParameter<'a> { + Name(&'a str), + NumLit(&'a str), + StrLit(&'a str), +} + #[derive(Debug)] pub enum Target<'a> { Name(&'a str), @@ -50,7 +57,7 @@ pub enum Node<'a> { } pub type Cond<'a> = (WS, Option>, Vec>); -pub type When<'a> = (WS, &'a str, Vec<&'a str>, Vec>); +pub type When<'a> = (WS, Option>, Vec>, Vec>); fn split_ws_parts(s: &[u8]) -> Node { if s.is_empty() { @@ -147,11 +154,20 @@ named!(expr_array_lit, do_parse!( }) )); +named!(param_num_lit, map!(num_lit, + |s| MatchParameter::NumLit(s) +)); + named!(expr_str_lit, map!( delimited!(char!('"'), take_until!("\""), char!('"')), |s| Expr::StrLit(str::from_utf8(s).unwrap()) )); +named!(param_str_lit, map!( + delimited!(char!('"'), is_not!("\""), char!('"')), + |s| MatchParameter::StrLit(str::from_utf8(s).unwrap()) +)); + named!(expr_var, map!(identifier, |s| Expr::Var(s)) ); @@ -174,6 +190,10 @@ named!(target_single, map!(identifier, |s| Target::Name(s) )); +named!(param_name, map!(identifier, + |s| MatchParameter::Name(s) +)); + named!(arguments>, do_parse!( tag_s!("(") >> args: opt!(do_parse!( @@ -212,10 +232,24 @@ named!(parameters>, do_parse!( (vals.unwrap_or_default()) )); -named!(with_parameters>, do_parse!( +named!(with_parameters>, do_parse!( tag_s!("with") >> - params: ws!(parameters) >> - (params) + ws!(tag_s!("(")) >> + vals: opt!(do_parse!( + arg0: ws!(match_parameter) >> + args: many0!(do_parse!( + tag_s!(",") >> + argn: ws!(match_parameter) >> + (argn) + )) >> + ({ + let mut res = vec![arg0]; + res.extend(args); + res + }) + )) >> + tag_s!(")") >> + (vals.unwrap_or_default()) )); named!(expr_group, map!( @@ -232,6 +266,12 @@ named!(expr_single, alt!( expr_group )); +named!(match_parameter, alt!( + param_name | + param_num_lit | + param_str_lit +)); + named!(attr<(&str, Option>)>, do_parse!( tag_s!(".") >> attr: alt!(num_lit | identifier) >> @@ -374,19 +414,19 @@ named!(match_else_block, do_parse!( nws: opt!(tag_s!("-")) >> tag_s!("%}") >> block: parse_template >> - (WS(pws.is_some(), nws.is_some()), "_", vec![], block) + (WS(pws.is_some(), nws.is_some()), None, vec![], block) )); named!(when_block, do_parse!( tag_s!("{%") >> pws: opt!(tag_s!("-")) >> ws!(tag_s!("when")) >> - variant: ws!(identifier) >> + variant: ws!(match_parameter) >> params: opt!(ws!(with_parameters)) >> nws: opt!(tag_s!("-")) >> tag_s!("%}") >> block: parse_template >> - (WS(pws.is_some(), nws.is_some()), variant, params.unwrap_or_default(), block) + (WS(pws.is_some(), nws.is_some()), Some(variant), params.unwrap_or_default(), block) )); named!(block_match, do_parse!( -- cgit