diff options
Diffstat (limited to 'src/repo/profile/make_defaults/parsers.rs')
| -rw-r--r-- | src/repo/profile/make_defaults/parsers.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/repo/profile/make_defaults/parsers.rs b/src/repo/profile/make_defaults/parsers.rs new file mode 100644 index 0000000..4d27791 --- /dev/null +++ b/src/repo/profile/make_defaults/parsers.rs @@ -0,0 +1,88 @@ +use mon::{Parser, ParserIter, ascii_alpha, ascii_alphanumeric, r#if, one_of, tag}; + +use crate::{ + Parseable, + repo::profile::make_defaults::{Assignment, Interpolation, Key, Literal, Segment}, +}; + +impl<'a> Parseable<'a, &'a str> for Key { + type Parser = impl Parser<&'a str, Output = Self>; + + fn parser() -> Self::Parser { + let start = ascii_alpha(); + let rest = ascii_alphanumeric() + .or(one_of("_".chars())) + .repeated() + .many(); + + start + .followed_by(rest) + .recognize() + .map(|output: &str| Key(output.to_string())) + } +} + +impl<'a> Parseable<'a, &'a str> for Literal { + type Parser = impl Parser<&'a str, Output = Self>; + + fn parser() -> Self::Parser { + r#if(|c: &char| *c != '"') + .and_not(Interpolation::parser()) + .repeated() + .at_least(1) + .recognize() + .map(|output: &str| Literal(output.to_string())) + } +} + +impl<'a> Parseable<'a, &'a str> for Interpolation { + type Parser = impl Parser<&'a str, Output = Self>; + + fn parser() -> Self::Parser { + Key::parser() + .recognize() + .delimited_by(tag("{"), tag("}")) + .preceded_by(tag("$")) + .map(|output: &str| Interpolation(output.to_string())) + } +} + +impl<'a> Parseable<'a, &'a str> for Segment { + type Parser = impl Parser<&'a str, Output = Self>; + + fn parser() -> Self::Parser { + Literal::parser() + .map(Segment::Literal) + .or(Interpolation::parser().map(Segment::Interpolation)) + } +} + +impl<'a> Parseable<'a, &'a str> for Assignment { + type Parser = impl Parser<&'a str, Output = Self>; + + fn parser() -> Self::Parser { + Key::parser() + .followed_by(tag("=")) + .and( + Segment::parser() + .repeated() + .many() + .delimited_by(tag("\""), tag("\"")), + ) + .map(|(key, value)| Assignment(key, value)) + } +} + +#[cfg(test)] +mod test { + use mon::input::InputIter; + + use super::*; + + #[test] + fn test_parse_value() { + let it = InputIter::new(r#"KEY="foo ${bar}""#); + + Assignment::parser().check_finished(it).unwrap(); + } +} |
