mirror of
https://github.com/dredozubov/polyrhythmix.git
synced 2024-11-22 11:57:43 +00:00
note length parser
This commit is contained in:
parent
e7a933b837
commit
2251a09bc2
1 changed files with 45 additions and 45 deletions
|
@ -2,9 +2,11 @@ use std::str;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
pub use nom::character::complete::{char, digit1};
|
pub use nom::character::complete::{char, digit1};
|
||||||
|
use nom::sequence::{separated_pair, tuple};
|
||||||
use nom::{Err, IResult};
|
use nom::{Err, IResult};
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::combinator::{map, map_res};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -21,85 +23,83 @@ pub enum BasicLength {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ModdedLength {
|
pub enum ModdedLength {
|
||||||
Plain(BasicLength),
|
Plain(BasicLength),
|
||||||
Dotted(BasicLength),
|
Dotted(BasicLength)
|
||||||
Triplet(BasicLength)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Length {
|
pub enum Length {
|
||||||
Simple(ModdedLength),
|
Simple(ModdedLength),
|
||||||
Tied(ModdedLength, ModdedLength)
|
Tied(ModdedLength, ModdedLength),
|
||||||
|
Triplet(ModdedLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Note {
|
pub enum Note {
|
||||||
Hit(Length),
|
Hit,
|
||||||
Rest(Length)
|
Rest
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Group { notes: Vec<Note> }
|
pub struct Group { notes: Vec<Note>, length: Length }
|
||||||
|
|
||||||
fn hit(len: Length, input: &str) -> IResult<&str, Note> {
|
fn hit(input: &str) -> IResult<&str, Note> {
|
||||||
// note that this is really creating a function, the parser for abc
|
// note that this is really creating a function, the parser for abc
|
||||||
// vvvvv
|
// vvvvv
|
||||||
// which is then called here, returning an IResult<&str, &str>
|
// which is then called here, returning an IResult<&str, &str>
|
||||||
// vvvvv
|
// vvvvv
|
||||||
let (rem, c) = char('x')(input)?;
|
map(char('x'), |_| { Note::Hit })(input)
|
||||||
Ok((rem, Note::Hit(len)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rest( len: Length, input: &str) -> IResult<&str, Note> {
|
fn rest(input: &str) -> IResult<&str, Note> {
|
||||||
let (rem, c) = char('-')(input)?;
|
map(char('-'), |_| { Note::Rest })(input)
|
||||||
Ok((rem, Note::Rest(len)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn note(input: &str, len: Length) -> IResult<&str, Note> {
|
fn note(input: &str) -> IResult<&str, Note> {
|
||||||
alt((hit(len), rest(len)))(input)
|
alt((hit, rest))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn length_basic(input: &str) -> IResult<&str, Length> {
|
fn length_basic(input: &str) -> IResult<&str, BasicLength> {
|
||||||
match map_res(digit1, str::parse)(input) {
|
match map_res(digit1, str::parse)(input) {
|
||||||
Ok(r,1) => Ok(r, Whole),
|
Ok((r,1)) => Ok((r, BasicLength::Whole)),
|
||||||
Ok(r,2) => Ok(r, Half),
|
Ok((r,2)) => Ok((r, BasicLength::Half)),
|
||||||
Ok(r,4) => Ok(r, Fourth),
|
Ok((r,4)) => Ok((r, BasicLength::Fourth)),
|
||||||
Ok(r,8) => Ok(r, Eighth),
|
Ok((r,8)) => Ok((r, BasicLength::Eighth)),
|
||||||
Ok(r,16) => Ok(r, Sixteenth),
|
Ok((r,16)) => Ok((r, BasicLength::Sixteenth)),
|
||||||
Ok(r,32) => Ok(r, ThirtySecond),
|
Ok((r,32)) => Ok((r, BasicLength::ThirtySecond)),
|
||||||
Ok(r, 64) => Ok(r, SixtyFourth),
|
Ok((r, 64)) => Ok((r, BasicLength::SixtyFourth)),
|
||||||
e => e
|
Ok((r, i)) => {
|
||||||
|
Err(Err::Error(nom::error::make_error(r, nom::error::ErrorKind::Fail)))
|
||||||
|
},
|
||||||
|
Err(e) => Err(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tie_length(input: &str) -> IResult<&str, Length> {
|
fn dotted_length(input: &str) -> IResult<&str, ModdedLength> {
|
||||||
let (rem, (l1,l2)) = separated_pair(length_basic, char('+'), length_basic)?;
|
map(tuple((length_basic, char('.'))), |(l, _)| { ModdedLength::Dotted(l)})(input)
|
||||||
Ok(rem, Tie(l1, l2))
|
}
|
||||||
|
|
||||||
|
fn modded_length(input: &str) -> IResult<&str, ModdedLength> {
|
||||||
|
alt((dotted_length, map(length_basic, |x| {ModdedLength::Plain(x)})))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn triplet_length(input: &str) -> IResult<&str, Length> {
|
||||||
|
map(tuple((modded_length, char('t'))), |(l, _)| { Length::Triplet(l)})(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tied_length(input: &str) -> IResult<&str, Length> {
|
||||||
|
map(separated_pair(modded_length, char('+'), modded_length), |(x, y)| { Length::Tied(x,y)})(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn length(input: &str) -> IResult<&str, Length> {
|
fn length(input: &str) -> IResult<&str, Length> {
|
||||||
let (rem, len) = alt(tie_length, length_basic)(input)?;
|
alt((triplet_length, tied_length, map(modded_length, |x| { Length::Simple(x) })))(input)
|
||||||
let (rem2, is_triplet) = char('t')(rem)?;
|
|
||||||
if is_triplet {
|
|
||||||
Triplet(len)
|
|
||||||
} else {
|
|
||||||
leṇ
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_basic_length() {
|
fn parse_basic_length() {
|
||||||
assert_eq!(
|
assert_eq!(length("16"), Ok(("", Length::Simple(ModdedLength::Plain(BasicLength::Sixteenth)))));
|
||||||
length("16"),
|
assert_eq!(length("8+16"), Ok(("", Length::Tied(ModdedLength::Plain(BasicLength::Eighth), ModdedLength::Plain(BasicLength::Sixteenth)))));
|
||||||
Ok((
|
assert_eq!(length("8t"), Ok(("", Length::Triplet(ModdedLength::Plain(BasicLength::Eighth)))));
|
||||||
"",
|
assert_eq!(length("4.t"), Ok(("", Length::Triplet(ModdedLength::Dotted(BasicLength::Fourth)))));
|
||||||
Sixteenth
|
|
||||||
))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
length("8+16"),
|
|
||||||
Ok("", Tie(Eighth, Sixteenth))
|
|
||||||
);
|
|
||||||
assert_eq!(length("8t"), Triplet(Eighth))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// “x” hit
|
// “x” hit
|
||||||
|
|
Loading…
Reference in a new issue