From add77cf6a52bb5c66db709d8d46aa9362c2faf9e Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 30 May 2020 14:39:31 -0400 Subject: [PATCH] Get rid of the concept of NamedBlock and replace it with a ParameterizedBlock special case that does not support an else block. --- src/parser/parser.rs | 188 ++++++++++++++-------------- src/renderer/inline_partial_tree.rs | 2 +- src/renderer/renderer.rs | 2 +- 3 files changed, 95 insertions(+), 97 deletions(-) diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 9451372..3e0696a 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -32,8 +32,8 @@ pub enum DustTag<'a> { DTSection(ParameterizedBlock<'a>), DTExists(ParameterizedBlock<'a>), DTNotExists(ParameterizedBlock<'a>), - DTBlock(NamedBlock<'a>), - DTInlinePartial(NamedBlock<'a>), + DTBlock(ParameterizedBlock<'a>), + DTInlinePartial(ParameterizedBlock<'a>), DTPartial(Partial<'a>), DTHelperEquals(ParameterizedBlock<'a>), DTHelperNotEquals(ParameterizedBlock<'a>), @@ -92,13 +92,6 @@ pub struct Span<'a> { pub contents: &'a str, } -#[derive(Clone, Debug, PartialEq)] -pub struct NamedBlock<'a> { - pub name: &'a str, - pub explicit_context: Option>, - pub contents: Option>, -} - #[derive(Clone, Debug, PartialEq)] pub struct ParameterizedBlock<'a> { pub path: Path<'a>, @@ -213,8 +206,14 @@ fn dust_tag(i: &str) -> IResult<&str, DustTag> { map(parameterized_block("{#", path), DustTag::DTSection), map(parameterized_block("{?", path), DustTag::DTExists), map(parameterized_block("{^", path), DustTag::DTNotExists), - named_block("{+", DustTag::DTBlock), - named_block("{<", DustTag::DTInlinePartial), + map( + parameterized_block_without_else("{+", key_to_path), + DustTag::DTBlock, + ), + map( + parameterized_block_without_else("{<", key_to_path), + DustTag::DTInlinePartial, + ), partial("{>", DustTag::DTPartial), map( parameterized_block("{@", &tag_to_path("gte")), @@ -342,72 +341,6 @@ fn reference(i: &str) -> IResult<&str, Reference> { )) } -fn named_block<'a, F>( - open_matcher: &'static str, - constructor: F, -) -> impl FnMut(&'a str) -> IResult<&'a str, DustTag<'a>> -where - F: Copy + Fn(NamedBlock<'a>) -> DustTag<'a>, -{ - alt(( - named_block_with_body(open_matcher, constructor), - self_closing_named_block(open_matcher, constructor), - )) -} - -fn named_block_with_body<'a, F>( - open_matcher: &'static str, - constructor: F, -) -> impl Fn(&'a str) -> IResult<&'a str, DustTag<'a>> -where - F: Fn(NamedBlock<'a>) -> DustTag<'a>, -{ - move |i: &'a str| { - let (i, (opening_name, maybe_explicit_context, inner, _closing_name)) = verify( - tuple(( - preceded(tag(open_matcher), key), - terminated(opt(preceded(tag(":"), path)), tag("}")), - opt(body), - delimited(tag("{/"), key, tag("}")), - )), - |(open, _maybe_explicit, _inn, close)| open == close, - )(i)?; - - Ok(( - i, - constructor(NamedBlock { - name: opening_name, - explicit_context: maybe_explicit_context, - contents: inner, - }), - )) - } -} - -fn self_closing_named_block<'a, F>( - open_matcher: &'static str, - constructor: F, -) -> impl Fn(&'a str) -> IResult<&'a str, DustTag<'a>> -where - F: Fn(NamedBlock<'a>) -> DustTag<'a>, -{ - move |i: &'a str| { - let (i, (opening_name, maybe_explicit_context)) = tuple(( - preceded(tag(open_matcher), key), - terminated(opt(preceded(tag(":"), path)), tag("/}")), - ))(i)?; - - Ok(( - i, - constructor(NamedBlock { - name: opening_name, - explicit_context: maybe_explicit_context, - contents: None, - }), - )) - } -} - fn parameterized_block<'a, F>( open_matcher: &'static str, name_matcher: F, @@ -421,6 +354,19 @@ where )) } +fn parameterized_block_without_else<'a, F>( + open_matcher: &'static str, + name_matcher: F, +) -> impl FnMut(&'a str) -> IResult<&'a str, ParameterizedBlock<'a>> +where + F: Copy + Fn(&'a str) -> IResult<&'a str, Path<'a>>, +{ + alt(( + parameterized_block_with_body_without_else(open_matcher, name_matcher), + parameterized_self_closing_block(open_matcher, name_matcher), + )) +} + fn parameterized_block_with_body<'a, F>( open_matcher: &'static str, name_matcher: F, @@ -462,6 +408,46 @@ where } } +fn parameterized_block_with_body_without_else<'a, F>( + open_matcher: &'static str, + name_matcher: F, +) -> impl Fn(&'a str) -> IResult<&'a str, ParameterizedBlock<'a>> +where + F: Copy + Fn(&'a str) -> IResult<&'a str, Path<'a>>, +{ + move |i: &'a str| { + let (i, (opening_name, maybe_explicit_context, params, inner, _closing_name)) = + verify( + tuple(( + preceded(tag(open_matcher), name_matcher), + opt(preceded(tag(":"), path)), + terminated( + opt(delimited( + space1, + separated_list1(space1, key_value_pair), + space0, + )), + tag("}"), + ), + opt(body), + delimited(tag("{/"), name_matcher, tag("}")), + )), + |(open, _maybe_explicit, _params, _inn, close)| open == close, + )(i)?; + + Ok(( + i, + ParameterizedBlock { + path: opening_name, + explicit_context: maybe_explicit_context, + params: params.unwrap_or(Vec::new()), + contents: inner, + else_contents: None, + }, + )) + } +} + fn parameterized_self_closing_block<'a, F>( open_matcher: &'static str, name_matcher: F, @@ -984,10 +970,12 @@ mod tests { super::dust_tag("{+foo/}"), Ok(( "", - DustTag::DTBlock(NamedBlock { - name: "foo", + DustTag::DTBlock(ParameterizedBlock { + path: Path { keys: vec!["foo"] }, explicit_context: None, - contents: None + params: Vec::new(), + contents: None, + else_contents: None }) )) ); @@ -999,9 +987,10 @@ mod tests { super::dust_tag("{+foo}hello {name}{/foo}"), Ok(( "", - DustTag::DTBlock(NamedBlock { - name: "foo", + DustTag::DTBlock(ParameterizedBlock { + path: Path { keys: vec!["foo"] }, explicit_context: None, + params: Vec::new(), contents: Some(Body { elements: vec![ TemplateElement::TESpan(Span { contents: "hello " }), @@ -1010,7 +999,8 @@ mod tests { filters: Vec::new() })) ] - }) + }), + else_contents: None }) )) ); @@ -1022,12 +1012,14 @@ mod tests { super::dust_tag("{+foo:bar.baz/}"), Ok(( "", - DustTag::DTBlock(NamedBlock { - name: "foo", + DustTag::DTBlock(ParameterizedBlock { + path: Path { keys: vec!["foo"] }, explicit_context: Some(Path { keys: vec!["bar", "baz"] }), - contents: None + params: Vec::new(), + contents: None, + else_contents: None }) )) ); @@ -1039,11 +1031,12 @@ mod tests { super::dust_tag("{+foo:bar.baz}hello {name}{/foo}"), Ok(( "", - DustTag::DTBlock(NamedBlock { - name: "foo", + DustTag::DTBlock(ParameterizedBlock { + path: Path { keys: vec!["foo"] }, explicit_context: Some(Path { keys: vec!["bar", "baz"] }), + params: Vec::new(), contents: Some(Body { elements: vec![ TemplateElement::TESpan(Span { contents: "hello " }), @@ -1052,7 +1045,8 @@ mod tests { filters: Vec::new() })) ] - }) + }), + else_contents: None }) )) ); @@ -1064,10 +1058,12 @@ mod tests { super::dust_tag("{( } DustTag::DTPartial(..) => (), DustTag::DTInlinePartial(named_block) => { - blocks.insert(&named_block.name, &named_block.contents); + blocks.insert(&named_block.path.keys[0], &named_block.contents); } DustTag::DTBlock(..) => (), DustTag::DTHelperEquals(parameterized_block) => { diff --git a/src/renderer/renderer.rs b/src/renderer/renderer.rs index 88617db..8898405 100644 --- a/src/renderer/renderer.rs +++ b/src/renderer/renderer.rs @@ -347,7 +347,7 @@ impl<'a> DustRenderer<'a> { None, &named_block.explicit_context, ); - return match blocks.blocks.get_block(named_block.name) { + return match blocks.blocks.get_block(named_block.path.keys[0]) { None => self.render_maybe_body( &named_block.contents, new_breadcrumbs.as_ref().unwrap_or(breadcrumbs),