impl profile evaluation

This commit is contained in:
John Turner
2025-11-29 20:43:28 +00:00
parent 94f3397d19
commit d1127df296
16 changed files with 1365 additions and 2 deletions

View File

@@ -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();
}
}