Merge branch 'bug_partial_parse' into partial

This commit is contained in:
Tom Alexander 2020-05-09 15:16:01 -04:00
commit df9ebaf0e0
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 120 additions and 4 deletions

View File

@ -6,7 +6,7 @@ use nom::bytes::complete::{tag, take_until, take_until_parser_matches};
use nom::character::complete::line_ending;
use nom::character::complete::multispace0;
use nom::character::complete::one_of;
use nom::character::complete::space1;
use nom::character::complete::{space0, space1};
use nom::combinator::all_consuming;
use nom::combinator::map;
use nom::combinator::opt;
@ -387,7 +387,11 @@ where
let (i, (name, params, inner, maybe_else, _closing_name)) = tuple((
preceded(tag(open_matcher), tag(tag_name)),
terminated(
opt(preceded(space1, separated_list1(space1, key_value_pair))),
opt(delimited(
space1,
separated_list1(space1, key_value_pair),
space0,
)),
tag("}"),
),
opt(body),
@ -420,7 +424,11 @@ where
tag(open_matcher),
tuple((
tag(tag_name),
opt(preceded(space1, separated_list1(space1, key_value_pair))),
opt(delimited(
space1,
separated_list1(space1, key_value_pair),
space0,
)),
)),
tag("/}"),
)(i)?;
@ -449,7 +457,11 @@ where
tag(open_matcher),
tuple((
alt((map(key, String::from), quoted_string)),
opt(preceded(space1, separated_list1(space1, key_value_pair))),
opt(delimited(
space1,
separated_list1(space1, key_value_pair),
space0,
)),
)),
tag("/}"),
)(i)?;
@ -1052,4 +1064,55 @@ mod tests {
))
);
}
#[test]
fn test_full_document_parameterized_partial() {
assert_eq!(
super::template(
r#"{#level3.level4}{>partialtwo v1="b" v2="b" v3="b" v4="b" v5="b" /}{/level3.level4}"#
),
Ok::<_, nom::Err<(&str, ErrorKind)>>((
"",
Template {
contents: Body {
elements: vec![TemplateElement::TETag(DustTag::DTSection(Container {
path: Path {
keys: vec!["level3", "level4"]
},
contents: Some(Body {
elements: vec![TemplateElement::TETag(DustTag::DTPartial(
Partial {
name: "partialtwo".to_owned(),
params: vec![
KVPair {
key: "v1",
value: RValue::RVString("b".to_owned())
},
KVPair {
key: "v2",
value: RValue::RVString("b".to_owned())
},
KVPair {
key: "v3",
value: RValue::RVString("b".to_owned())
},
KVPair {
key: "v4",
value: RValue::RVString("b".to_owned())
},
KVPair {
key: "v5",
value: RValue::RVString("b".to_owned())
}
]
}
))]
}),
else_contents: None
}))]
}
}
))
);
}
}

53
src/renderer/walking.rs Normal file
View File

@ -0,0 +1,53 @@
use crate::renderer::context_element::ContextElement;
use crate::renderer::WalkError;
enum WalkResult<'a> {
NoWalk,
PartialWalk,
FullyWalked(&'a dyn ContextElement),
}
fn walk_path_from_single_level<'a>(
context: &'a dyn ContextElement,
path: &Vec<&str>,
) -> WalkResult<'a> {
if path.is_empty() {
return WalkResult::FullyWalked(context);
}
let mut walk_failure = WalkResult::NoWalk;
let mut output = context;
for elem in path.iter() {
let new_val = output.walk(elem);
match output.walk(elem) {
Err(WalkError::CantWalk { .. }) => {
return walk_failure;
}
Ok(new_val) => {
walk_failure = WalkResult::PartialWalk;
output = new_val;
}
}
}
WalkResult::FullyWalked(output)
}
pub fn walk_path<'a>(
breadcrumbs: &Vec<&'a dyn ContextElement>,
path: &'a Vec<&str>,
) -> Result<&'a dyn ContextElement, WalkError> {
for context in breadcrumbs.iter().rev() {
match walk_path_from_single_level(*context, path) {
// If no walking was done at all, keep looping
WalkResult::NoWalk => {}
// If we partially walked then stop trying to find
// anything
WalkResult::PartialWalk => {
return Err(WalkError::CantWalk);
}
WalkResult::FullyWalked(new_context) => return Ok(new_context),
}
}
Err(WalkError::CantWalk)
}