diff --git a/src/dsl/dsl.rs b/src/dsl/dsl.rs index ba12d09..de7d118 100644 --- a/src/dsl/dsl.rs +++ b/src/dsl/dsl.rs @@ -487,18 +487,32 @@ fn times(input: &str) -> IResult<&str, Times> { } fn group(input: &str) -> IResult<&str, Group> { - let repeated = map( - tuple((times, char(','), length, many1(note))), + let repeated_syntax = map( + tuple(( + times, + char(','), + length, + many1(alt(( + map_res(note, |x| -> Result { Ok(SingleNote(x))}), + map_res(delimited_group, |x| -> Result { 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 { Ok(SingleNote(x))}), + map_res(delimited_group, |x| -> Result { 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 } 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) -> 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 { + Ok(flatten_groups(gs)) + })(input) } pub fn flatten_groups(input_groups: I) -> Groups @@ -559,31 +549,69 @@ where Groups(out) } +pub fn flatten_group(input: Group) -> Groups { + flatten_group_(&input, &mut Vec::new()) +} + +fn flatten_group_(input: &Group, out_groups: &mut Vec>) -> 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((