slope parser test, fix for longest string matching first

This commit is contained in:
Breval Ferrari 2025-05-21 18:31:31 +02:00
parent fb39301b31
commit 69c2869388

View file

@ -189,8 +189,16 @@ impl<'s> Slope<'s> {
N: AsRef<str> + Clone, N: AsRef<str> + Clone,
{ {
|input| { |input| {
let iter: std::collections::hash_map::Iter<'s, String, VariableChange> = let iter: std::iter::Rev<std::vec::IntoIter<(&'s String, &'s VariableChange)>> = {
parser.slopes.iter(); let mut vec = parser
.slopes
.iter()
.collect::<Vec<(&'s String, &'s VariableChange)>>();
vec.sort_by_key(|(name, _)| name.len());
vec
}
.into_iter()
.rev();
delimited( delimited(
char('{'), char('{'),
alt(iter alt(iter
@ -259,7 +267,7 @@ mod tests {
use crate::{ use crate::{
compiler::{ compiler::{
Loop, LoopCount, Marker, Note, Silence, Slope, Token, TokenVec, Tuplet, VariableChange, Loop, LoopCount, Marker, Note, Silence, Slope, TokenVec, Tuplet, VariableChange,
}, },
parser::expression_parser, parser::expression_parser,
}; };
@ -531,4 +539,75 @@ mod tests {
); );
} }
} }
#[test]
fn slope() {
let normal = || VariableChange('n', "1".parse().unwrap());
let very_fancy = || VariableChange('n', "1+1".parse().unwrap());
let slopes = HashMap::from([
("nor".to_string(), very_fancy()),
("normal".to_string(), normal()),
]);
fn parser_builder<'s>(
slopes: &'s HashMap<String, VariableChange>,
) -> impl Fn(&str) -> IResult<&str, Slope<'s>> {
move |input: &str| {
Slope::parser(
&ParserBuilder::create_empty()
.notes(&["do", "", "mi"])
.slopes(slopes)
.variables(&['n'])
.build()
.unwrap(),
)
.parse(input)
}
}
let parser = parser_builder(&slopes);
let normal_value = normal();
let very_fancy_value = very_fancy();
let mut working_cases = vec![
(
"{normal.%}",
(
"",
Slope(
&normal_value,
TokenVec(vec![Box::new(Silence), Box::new(Marker)]),
),
),
),
("{normal}", ("", Slope(&normal_value, TokenVec(vec![])))),
("{nor}", ("", Slope(&very_fancy_value, TokenVec(vec![])))),
(
"{normal do}f",
("f", Slope(&normal_value, TokenVec(vec![Box::new(Note(0))]))),
),
];
let mut not_working_cases = vec![
"",
"{",
"}",
"{normal",
"{fancy}",
"{norma do}",
"{do}",
"{}",
];
for (test, expected) in working_cases.drain(..) {
let output = parser(test);
if let Ok(result) = output {
assert_eq!(expected, result, "case \"{test}\"");
} else {
panic!("result of \"{test}\" was not Ok: {output:?}");
}
}
for test in not_working_cases.drain(..) {
let output = parser(test);
assert!(
output.is_err(),
"result of \"{test}\" was not Err: {output:?}"
);
}
}
} }