mirror of
https://github.com/dredozubov/polyrhythmix.git
synced 2024-12-22 14:25:29 +00:00
Fix flatten_group
This commit is contained in:
parent
58bb2ba87c
commit
9ffa47977e
1 changed files with 100 additions and 72 deletions
172
src/dsl/dsl.rs
172
src/dsl/dsl.rs
|
@ -487,18 +487,32 @@ fn times(input: &str) -> IResult<&str, Times> {
|
|||
}
|
||||
|
||||
fn group(input: &str) -> IResult<&str, Group<GroupOrNote>> {
|
||||
let repeated = map(
|
||||
tuple((times, char(','), length, many1(note))),
|
||||
let repeated_syntax = map(
|
||||
tuple((
|
||||
times,
|
||||
char(','),
|
||||
length,
|
||||
many1(alt((
|
||||
map_res(note, |x| -> Result<GroupOrNote, &str> { Ok(SingleNote(x))}),
|
||||
map_res(delimited_group, |x| -> Result<GroupOrNote, &str> { Ok(SingleGroup(x))}),
|
||||
))),
|
||||
)),
|
||||
|(t, _, l, n)| (t, l, n),
|
||||
);
|
||||
let single = map(tuple((length, many1(note))), |(l, vn)| (Times(1), l, vn));
|
||||
let (rem, (t, l, n)) = alt((repeated, single))(input)?;
|
||||
let single_syntax = map(
|
||||
tuple((
|
||||
length,
|
||||
many1(alt((
|
||||
map_res(note, |x| -> Result<GroupOrNote, &str> { Ok(SingleNote(x))}),
|
||||
map_res(delimited_group, |x| -> Result<GroupOrNote, &str> { Ok(SingleGroup(x))}),
|
||||
))),
|
||||
)), |(l, vn)| (Times(1), l, vn));
|
||||
let (rem, (t, l, n)) = alt((repeated_syntax, single_syntax))(input)?;
|
||||
Ok((
|
||||
rem,
|
||||
Group {
|
||||
notes: n
|
||||
.iter()
|
||||
.map(|x| GroupOrNote::SingleNote(x.clone()))
|
||||
.into_iter()
|
||||
.collect(),
|
||||
length: l,
|
||||
times: t,
|
||||
|
@ -515,35 +529,11 @@ pub fn group_or_delimited_group(input: &str) -> IResult<&str, Group<GroupOrNote>
|
|||
}
|
||||
|
||||
pub fn groups(input: &str) -> IResult<&str, Groups> {
|
||||
all_consuming(many1(group_or_delimited_group))(input).map(|x| (x.0, flatten_groups(x.1)))
|
||||
}
|
||||
|
||||
pub fn flatten_group(input: Group<GroupOrNote>) -> Groups {
|
||||
let mut note_group = Vec::new();
|
||||
let mut out_groups = Vec::new();
|
||||
input.notes.iter().for_each(|g| match g {
|
||||
SingleGroup(group) => {
|
||||
let isolated_group = Group {
|
||||
notes: note_group.clone(),
|
||||
length: input.length,
|
||||
times: Times(1),
|
||||
};
|
||||
out_groups.push(isolated_group);
|
||||
note_group.clear();
|
||||
out_groups.extend(flatten_group(group.clone()).0);
|
||||
}
|
||||
SingleNote(note) => {
|
||||
note_group.push(*note);
|
||||
}
|
||||
});
|
||||
Groups(
|
||||
out_groups
|
||||
.iter()
|
||||
.cloned()
|
||||
.cycle()
|
||||
.take(out_groups.len() * (input.times.0 as usize))
|
||||
.collect(),
|
||||
)
|
||||
map_res(
|
||||
all_consuming(many1(group_or_delimited_group)),
|
||||
|gs| -> Result<Groups, &str> {
|
||||
Ok(flatten_groups(gs))
|
||||
})(input)
|
||||
}
|
||||
|
||||
pub fn flatten_groups<I>(input_groups: I) -> Groups
|
||||
|
@ -559,31 +549,69 @@ where
|
|||
Groups(out)
|
||||
}
|
||||
|
||||
pub fn flatten_group(input: Group<GroupOrNote>) -> Groups {
|
||||
flatten_group_(&input, &mut Vec::new())
|
||||
}
|
||||
|
||||
fn flatten_group_(input: &Group<GroupOrNote>, out_groups: &mut Vec<Group<Note>>) -> Groups {
|
||||
let mut note_group = Vec::new();
|
||||
input.notes.iter().for_each(|g| {
|
||||
match g {
|
||||
SingleGroup(group) => {
|
||||
let isolated_group = Group {
|
||||
notes: note_group.clone(),
|
||||
length: input.length,
|
||||
times: Times(1),
|
||||
};
|
||||
out_groups.push(isolated_group);
|
||||
note_group.clear();
|
||||
flatten_group_(&group, out_groups);
|
||||
}
|
||||
SingleNote(note) => {
|
||||
note_group.push(*note);
|
||||
}
|
||||
}
|
||||
});
|
||||
if !note_group.is_empty() {
|
||||
let isolated_group = Group {
|
||||
notes: note_group.clone(),
|
||||
length: input.length,
|
||||
times: input.times,
|
||||
};
|
||||
out_groups.push(isolated_group);
|
||||
}
|
||||
Groups(
|
||||
out_groups
|
||||
.iter()
|
||||
.cloned()
|
||||
.cycle()
|
||||
.take(out_groups.len() * (input.times.0 as usize))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_group() {
|
||||
let out = Groups(vec![
|
||||
Group {
|
||||
notes: vec![Hit],
|
||||
length: *SIXTEENTH,
|
||||
times: Times(1),
|
||||
},
|
||||
Group {
|
||||
notes: vec![Rest, Hit],
|
||||
length: *EIGHTH,
|
||||
times: Times(3),
|
||||
},
|
||||
Group {
|
||||
notes: vec![Hit],
|
||||
length: *SIXTEENTH,
|
||||
times: Times(1),
|
||||
},
|
||||
Group {
|
||||
notes: vec![Rest, Hit],
|
||||
length: *EIGHTH,
|
||||
times: Times(3),
|
||||
},
|
||||
let output = Groups(vec![
|
||||
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
||||
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
||||
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
||||
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
||||
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
||||
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
||||
]);
|
||||
assert_eq!(flatten_group(group("(2,16x(3,8-x))").unwrap().1), out);
|
||||
// basically it's 3,16x(2,8-x)
|
||||
let input = Group {
|
||||
notes: vec![
|
||||
SingleNote(Hit), SingleGroup(Group {
|
||||
notes: vec![SingleNote(Rest), SingleNote(Hit)],
|
||||
length: *EIGHTH,
|
||||
times: Times(2),
|
||||
})],
|
||||
length: *SIXTEENTH,
|
||||
times: Times(3),
|
||||
};
|
||||
assert_eq!(flatten_group(input), output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -604,7 +632,7 @@ fn parse_length() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn parse_groups() {
|
||||
fn test_parse_groups() {
|
||||
assert_eq!(
|
||||
groups("8x-(7,8xx)"),
|
||||
Ok((
|
||||
|
@ -623,30 +651,30 @@ fn parse_groups() {
|
|||
])
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
groups("8x-(7,8xx"),
|
||||
Err(Err::Error(nom::error::make_error(
|
||||
"(7,8xx",
|
||||
nom::error::ErrorKind::Eof
|
||||
)))
|
||||
);
|
||||
// assert_eq!(
|
||||
// groups("8x-(7,8xx"),
|
||||
// Err(Err::Error(nom::error::make_error(
|
||||
// "(7,8xx",
|
||||
// nom::error::ErrorKind::Eof
|
||||
// )))
|
||||
// );
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_group() {
|
||||
fn test_parse_group() {
|
||||
let expectation = Group {
|
||||
times: *TWICE,
|
||||
notes: vec![
|
||||
SingleNote(Hit),
|
||||
SingleGroup(Group {
|
||||
times: *ONCE,
|
||||
notes: vec![],
|
||||
length: *EIGHTH
|
||||
})
|
||||
notes: vec![SingleNote(Rest), SingleNote(Hit)],
|
||||
length: *EIGHTH,
|
||||
}),
|
||||
],
|
||||
length: *SIXTEENTH
|
||||
length: *SIXTEENTH,
|
||||
};
|
||||
assert_eq!(group("(2,16x(8-x))"), Ok(("", expectation)));
|
||||
assert_eq!(group("2,16x(8-x)"), Ok(("", expectation)));
|
||||
assert_eq!(
|
||||
group("16x--x-"),
|
||||
Ok((
|
||||
|
@ -724,7 +752,7 @@ fn parse_delimited_group() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn parse_group_or_delimited_group() {
|
||||
fn test_parse_group_or_delimited_group() {
|
||||
assert_eq!(
|
||||
group_or_delimited_group("(3,16x--x-)"),
|
||||
Ok((
|
||||
|
|
Loading…
Reference in a new issue