diff --git a/src/bng/score.rs b/src/bng/score.rs index fa58350..5e5e601 100644 --- a/src/bng/score.rs +++ b/src/bng/score.rs @@ -6,7 +6,13 @@ use bng_macros::{QuickModifierParser, SlopeModifierParser}; use derive_new::new; use derived_deref::Deref; use lex::lexer::flat_atom_parser; -use nom::multi::many0; +use nom::{ + branch::alt, + character::complete::char, + combinator::eof, + multi::many0, + sequence::{preceded, terminated}, +}; #[cfg(debug_assertions)] use serde::Serialize; use serde::{ @@ -98,16 +104,22 @@ impl<'de> Deserialize<'de> for Atoms { const FIELDS: &[&str] = &["notes", "sheet"]; let NotesSheet { notes, sheet } = deserializer.deserialize_struct("NotesSheet", FIELDS, NotesSheetVisitor)?; - let x = many0(flat_atom_parser(¬es))(&sheet) - .map_err(|e| e.to_string()) - .map_err(AtomsSerializeError::Parsing) - .map_err(de::Error::custom) - .and_then(|(_, v)| { - inflate(v) - .map_err(AtomsSerializeError::from) - .map_err(de::Error::custom) - }) - .map(Atoms); + let x = terminated( + many0(preceded( + many0(alt((char('\t'), char(' '), char('\n'), char('\r')))), + flat_atom_parser(¬es), + )), + eof, + )(&sheet) + .map_err(|e| e.to_string()) + .map_err(AtomsSerializeError::Parsing) + .map_err(de::Error::custom) + .and_then(|(_, v)| { + inflate(v) + .map_err(AtomsSerializeError::from) + .map_err(de::Error::custom) + }) + .map(Atoms); x } } diff --git a/src/bng/score/lex/lexer.rs b/src/bng/score/lex/lexer.rs index 7631144..762100e 100644 --- a/src/bng/score/lex/lexer.rs +++ b/src/bng/score/lex/lexer.rs @@ -39,53 +39,49 @@ impl Parse for Modifier { } pub fn flat_atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Error<&str>> { - preceded( - many0(alt((char('\t'), char(' '), char('\n'), char('\r')))), - alt(( - map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from).map(FlatAtom::Note), - value(FlatAtom::Rest, char(Atom::REST)), - value(FlatAtom::StartHere, char(Atom::START_HERE)), - preceded(char(Atom::MODIFIER), Modifier::parse).map(FlatAtom::Modifier), - QuickModifier::parse.map(FlatAtom::QuickModifier), + alt(( + map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from).map(FlatAtom::Note), + value(FlatAtom::Rest, char(Atom::REST)), + value(FlatAtom::StartHere, char(Atom::START_HERE)), + preceded(char(Atom::MODIFIER), Modifier::parse).map(FlatAtom::Modifier), + QuickModifier::parse.map(FlatAtom::QuickModifier), + preceded( + char(Atom::LOOP.0), + map_opt(opt(u8), |n| { + if let Some(n) = n { + NonZeroU8::new(n) + } else { + unsafe { Some(NonZeroU8::new_unchecked(2)) } + } + }), + ) + .map(FlatAtom::LoopStarts), + value(FlatAtom::LoopEnds, char(Atom::LOOP.1)), + value(FlatAtom::TupleStarts, char(Atom::TUPLE.0)), + value(FlatAtom::TupleEnds, char(Atom::TUPLE.1)), + terminated( preceded( - char(Atom::LOOP.0), - map_opt(opt(u8), |n| { - if let Some(n) = n { - NonZeroU8::new(n) - } else { - unsafe { Some(NonZeroU8::new_unchecked(2)) } - } - }), - ) - .map(FlatAtom::LoopStarts), - value(FlatAtom::LoopEnds, char(Atom::LOOP.1)), - value(FlatAtom::TupleStarts, char(Atom::TUPLE.0)), - value(FlatAtom::TupleEnds, char(Atom::TUPLE.1)), - terminated( - preceded( - char(Atom::SLOPE.0), - separated_pair( - SlopeModifier::parse, - char(' '), - map_res(take_till1(|c| c == ','), |s: &str| { - s.parse().map_err(|_| { - nom::error::Error::new(s, nom::error::ErrorKind::Verify) - }) - }), - ), - ), - char(','), - ) - .map(|(sm, i)| FlatAtom::SlopeStarts(sm, i)), - value(FlatAtom::SlopeEnds, char(Atom::SLOPE.1)), - value( - FlatAtom::Comment, - delimited( - char(Atom::COMMENT.0), - take_till(|c| c == Atom::COMMENT.1), - char(Atom::COMMENT.1), + char(Atom::SLOPE.0), + separated_pair( + SlopeModifier::parse, + char(' '), + map_res(take_till1(|c| c == ','), |s: &str| { + s.parse() + .map_err(|_| nom::error::Error::new(s, nom::error::ErrorKind::Verify)) + }), ), ), - )), - ) + char(','), + ) + .map(|(sm, i)| FlatAtom::SlopeStarts(sm, i)), + value(FlatAtom::SlopeEnds, char(Atom::SLOPE.1)), + value( + FlatAtom::Comment, + delimited( + char(Atom::COMMENT.0), + take_till(|c| c == Atom::COMMENT.1), + char(Atom::COMMENT.1), + ), + ), + )) }