mirror of
https://github.com/dredozubov/polyrhythmix.git
synced 2024-11-22 03:47:43 +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>> {
|
fn group(input: &str) -> IResult<&str, Group<GroupOrNote>> {
|
||||||
let repeated = map(
|
let repeated_syntax = map(
|
||||||
tuple((times, char(','), length, many1(note))),
|
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),
|
|(t, _, l, n)| (t, l, n),
|
||||||
);
|
);
|
||||||
let single = map(tuple((length, many1(note))), |(l, vn)| (Times(1), l, vn));
|
let single_syntax = map(
|
||||||
let (rem, (t, l, n)) = alt((repeated, single))(input)?;
|
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((
|
Ok((
|
||||||
rem,
|
rem,
|
||||||
Group {
|
Group {
|
||||||
notes: n
|
notes: n
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|x| GroupOrNote::SingleNote(x.clone()))
|
|
||||||
.collect(),
|
.collect(),
|
||||||
length: l,
|
length: l,
|
||||||
times: t,
|
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> {
|
pub fn groups(input: &str) -> IResult<&str, Groups> {
|
||||||
all_consuming(many1(group_or_delimited_group))(input).map(|x| (x.0, flatten_groups(x.1)))
|
map_res(
|
||||||
}
|
all_consuming(many1(group_or_delimited_group)),
|
||||||
|
|gs| -> Result<Groups, &str> {
|
||||||
pub fn flatten_group(input: Group<GroupOrNote>) -> Groups {
|
Ok(flatten_groups(gs))
|
||||||
let mut note_group = Vec::new();
|
})(input)
|
||||||
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(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flatten_groups<I>(input_groups: I) -> Groups
|
pub fn flatten_groups<I>(input_groups: I) -> Groups
|
||||||
|
@ -559,31 +549,69 @@ where
|
||||||
Groups(out)
|
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]
|
#[test]
|
||||||
fn test_flatten_group() {
|
fn test_flatten_group() {
|
||||||
let out = Groups(vec![
|
let output = Groups(vec![
|
||||||
Group {
|
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
||||||
notes: vec![Hit],
|
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
||||||
length: *SIXTEENTH,
|
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
||||||
times: Times(1),
|
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
||||||
},
|
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
||||||
Group {
|
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
||||||
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),
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
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]
|
#[test]
|
||||||
|
@ -604,7 +632,7 @@ fn parse_length() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_groups() {
|
fn test_parse_groups() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
groups("8x-(7,8xx)"),
|
groups("8x-(7,8xx)"),
|
||||||
Ok((
|
Ok((
|
||||||
|
@ -623,30 +651,30 @@ fn parse_groups() {
|
||||||
])
|
])
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
groups("8x-(7,8xx"),
|
// groups("8x-(7,8xx"),
|
||||||
Err(Err::Error(nom::error::make_error(
|
// Err(Err::Error(nom::error::make_error(
|
||||||
"(7,8xx",
|
// "(7,8xx",
|
||||||
nom::error::ErrorKind::Eof
|
// nom::error::ErrorKind::Eof
|
||||||
)))
|
// )))
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_group() {
|
fn test_parse_group() {
|
||||||
let expectation = Group {
|
let expectation = Group {
|
||||||
times: *TWICE,
|
times: *TWICE,
|
||||||
notes: vec![
|
notes: vec![
|
||||||
SingleNote(Hit),
|
SingleNote(Hit),
|
||||||
SingleGroup(Group {
|
SingleGroup(Group {
|
||||||
times: *ONCE,
|
times: *ONCE,
|
||||||
notes: vec![],
|
notes: vec![SingleNote(Rest), SingleNote(Hit)],
|
||||||
length: *EIGHTH
|
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!(
|
assert_eq!(
|
||||||
group("16x--x-"),
|
group("16x--x-"),
|
||||||
Ok((
|
Ok((
|
||||||
|
@ -724,7 +752,7 @@ fn parse_delimited_group() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_group_or_delimited_group() {
|
fn test_parse_group_or_delimited_group() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
group_or_delimited_group("(3,16x--x-)"),
|
group_or_delimited_group("(3,16x--x-)"),
|
||||||
Ok((
|
Ok((
|
||||||
|
|
Loading…
Reference in a new issue