diff --git a/src/parser/parser.rs b/src/parser/parser.rs index aaf384d..d724ead 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1,5 +1,4 @@ use nom::branch::alt; -use nom::bytes::complete::escaped; use nom::bytes::complete::escaped_transform; use nom::bytes::complete::is_a; use nom::bytes::complete::is_not; @@ -8,7 +7,6 @@ use nom::bytes::complete::take_until; use nom::character::complete::one_of; use nom::character::complete::space1; use nom::combinator::map; -use nom::combinator::not; use nom::combinator::opt; use nom::combinator::recognize; use nom::combinator::rest; @@ -17,6 +15,7 @@ use nom::combinator::verify; use nom::multi::many0; use nom::multi::many1; use nom::multi::separated_list; +use nom::multi::separated_nonempty_list; use nom::sequence::delimited; use nom::sequence::preceded; use nom::sequence::separated_pair; @@ -97,6 +96,18 @@ struct ParameterizedBlock<'a> { params: Vec<&'a str>, } +#[derive(Clone, Debug, PartialEq)] +enum RValue<'a> { + RVPath(Path<'a>), + RVString(String), +} + +#[derive(Clone, Debug, PartialEq)] +struct KVPair<'a> { + key: &'a str, + value: RValue<'a>, +} + #[derive(Clone, Debug, PartialEq)] struct Body<'a> { elements: Vec>, @@ -113,18 +124,6 @@ enum TemplateElement<'a> { TETag(DustTag<'a>), } -#[derive(Clone, Debug, PartialEq)] -enum RValue<'a> { - RVPath(Path<'a>), - RVLiteral(&'a str), -} - -#[derive(Clone, Debug, PartialEq)] -struct KVPair<'a> { - key: &'a str, - value: RValue<'a>, -} - /// Any element significant to dust that isn't plain text /// /// These elements are always wrapped in curly braces @@ -176,12 +175,17 @@ fn key(i: &str) -> IResult<&str, &str> { /// A series of keys separated by '.' to reference a variable in the context fn path(i: &str) -> IResult<&str, Path> { - map(separated_list(tag("."), key), |body| Path { keys: body })(i) + map(separated_nonempty_list(tag("."), key), |body| Path { + keys: body, + })(i) } /// Either a literal or a path to a value fn rvalue(i: &str) -> IResult<&str, RValue> { - map(path, RValue::RVPath)(i) + alt(( + map(path, RValue::RVPath), + map(quoted_string, RValue::RVString), + ))(i) } /// Parameters for a partial @@ -708,5 +712,26 @@ mod tests { ) )) ); + + assert_eq!( + delimited( + tag("{>"), + tuple(( + key, + opt(preceded(space1, separated_list(space1, key_value_pair))), + )), + tag("/}"), + )(r#"{>foo bar="ba\"z"/}"#), + Ok(( + "", + ( + "foo", + Some(vec![KVPair { + key: "bar", + value: RValue::RVString("ba\"z".to_owned()) + }]) + ) + )) + ); } }