diff --git a/Cargo.toml b/Cargo.toml index 7aceef6..5c9009e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ bng_macros = { path = "bng_macros" } const_format = "0.2.33" thiserror = "1.0.64" derive-new = "0.7.0" -naan = "0.1.32" [features] default = ["play", "save"] diff --git a/src/bng/score.rs b/src/bng/score.rs index 6a4a68e..df2b65b 100644 --- a/src/bng/score.rs +++ b/src/bng/score.rs @@ -8,6 +8,7 @@ use anyhow::Context; use bng_macros::{ModifierParser, QuickModifierParser, SlopeModifierParser}; use derive_new::new; use derived_deref::Deref; +use lex::lexer::atom; use nom::{ branch::alt, character::{complete::char, streaming::one_of}, diff --git a/src/bng/score/de.rs b/src/bng/score/de.rs index 9756e9b..11526fd 100644 --- a/src/bng/score/de.rs +++ b/src/bng/score/de.rs @@ -1,11 +1,9 @@ use std::{ fmt::{Debug, Display}, num::TryFromIntError, - ops::Deref, }; use derive_new::new; -use naan::fun::{F1Once, F2Once}; use nom::{ character::complete::one_of, combinator::all_consuming, @@ -20,7 +18,7 @@ use serde::{ }; use thiserror::Error; -use crate::bng::score::lex::lexer::root; +use crate::bng::score::lex::lexer::atom; use super::{ utils::{inflate, InflateError}, @@ -56,7 +54,11 @@ impl<'de> Deserialize<'de> for Atoms { Ok(Default::default()) } else { root(&sheet, ¬es) - .map_err(|e| pretty_verbose_err.curry().call1(sheet.as_str()).call1(e)) + .map_err(|e: nom::Err>| match e { + nom::Err::Incomplete(Needed::Unknown) => "needed some more bytes".to_string(), + nom::Err::Incomplete(Needed::Size(n)) => format!("needed {} more bytes", n), + nom::Err::Error(e) | nom::Err::Failure(e) => convert_error(sheet.as_str(), e), + }) .map_err(AtomsSerializeError::Parsing) .map_err(de::Error::custom) .and_then(|(_, v)| { @@ -69,13 +71,22 @@ impl<'de> Deserialize<'de> for Atoms { } } -fn pretty_verbose_err(input: I, e: nom::Err>) -> String +fn maybe_yml_str_space<'a, E>() -> impl Parser<&'a str, Vec, E> where - I: Deref, + E: nom::error::ParseError<&'a str> + ContextError<&'a str>, { - match e { - nom::Err::Incomplete(Needed::Unknown) => "needed some more bytes".to_string(), - nom::Err::Incomplete(Needed::Size(n)) => format!("needed {} more bytes", n), - nom::Err::Error(e) | nom::Err::Failure(e) => convert_error(input, e), - } + context("yml white space", many0(one_of(" \t\r\n"))) +} + +fn root<'a, E>(i: &'a str, notes: &'a str) -> IResult<&'a str, Vec, E> +where + E: ParseError<&'a str> + + ContextError<&'a str> + + FromExternalError<&'a str, TryFromIntError> + + FromExternalError<&'a str, E>, +{ + all_consuming(terminated( + many1(preceded(maybe_yml_str_space(), atom(notes))), + maybe_yml_str_space(), + ))(i) } diff --git a/src/bng/score/lex/lexer.rs b/src/bng/score/lex/lexer.rs index 45bf7ad..aa98244 100644 --- a/src/bng/score/lex/lexer.rs +++ b/src/bng/score/lex/lexer.rs @@ -9,13 +9,15 @@ use nom::{ branch::alt, bytes::complete::{take_till, take_till1}, character::complete::{anychar, char, one_of, space1, u16, u8}, - combinator::{all_consuming, map_opt, map_res, opt, value, verify}, + combinator::{map_opt, map_res, opt, value, verify}, error::{context, ContextError, ErrorKind, FromExternalError, ParseError}, - multi::{many0, many1}, + multi::many0, sequence::{delimited, pair, preceded, separated_pair, terminated}, Err, IResult, Parser, }; +use crate::bng::score::{modifier, quick_modifier, slope_modifier}; + use super::{ super::super::Expression as Instruction, Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier, }; @@ -23,175 +25,7 @@ use super::{ #[cfg(test)] mod tests; -fn maybe_yml_str_space<'a, E>() -> impl Parser<&'a str, Vec, E> -where - E: nom::error::ParseError<&'a str> + ContextError<&'a str>, -{ - context("yml white space", many0(one_of(" \t\r\n"))) -} - -pub fn root<'a, E>(i: &'a str, notes: &'a str) -> IResult<&'a str, Vec, E> -where - E: ParseError<&'a str> - + ContextError<&'a str> - + FromExternalError<&'a str, TryFromIntError> - + FromExternalError<&'a str, E>, -{ - all_consuming(terminated( - many1(preceded(maybe_yml_str_space(), atom(notes))), - maybe_yml_str_space(), - ))(i) -} - -fn note<'a, E>(notes: &'a str) -> impl Parser<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str> + FromExternalError<&'a str, TryFromIntError>, -{ - context( - "note", - map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from).map(FlatAtom::Note), - ) -} - -fn rest<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - context("rest", value(FlatAtom::Rest, char(Atom::REST)))(i) -} - -fn start_here<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - context( - "start_here", - value(FlatAtom::StartHere, char(Atom::START_HERE)), - )(i) -} - -fn modifier<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - use super::super::modifier; - context( - "modifier", - preceded(char(Atom::MODIFIER), modifier).map(FlatAtom::Modifier), - )(i) -} - -fn quick_modifier<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - use super::super::quick_modifier; - context( - "quick_modifier", - quick_modifier.map(FlatAtom::QuickModifier), - )(i) -} - -fn loop_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - context( - "loop_starts", - 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), - )(i) -} - -fn loop_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - context("loop_ends", value(FlatAtom::LoopEnds, char(Atom::LOOP.1)))(i) -} - -fn tuple_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - context( - "tuple_starts", - value(FlatAtom::TupleStarts, char(Atom::TUPLE.0)), - )(i) -} - -fn tuple_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - context( - "tuple_ends", - value(FlatAtom::TupleEnds, char(Atom::TUPLE.1)), - )(i) -} - -fn slope_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str> + FromExternalError<&'a str, E>, -{ - use super::super::slope_modifier; - context( - "slope_starts", - terminated( - preceded( - char(Atom::SLOPE.0), - separated_pair( - slope_modifier, - char(' '), - map_res(take_till1(|c| c == ','), |s: &str| { - s.parse() - .map_err(|_| E::from_error_kind(s, ErrorKind::Verify)) - }), - ), - ), - char(','), - ) - .map(|(sm, i)| FlatAtom::SlopeStarts(sm, i)), - )(i) -} - -fn slope_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - context( - "slope_ends", - value(FlatAtom::SlopeEnds, char(Atom::SLOPE.1)), - )(i) -} - -fn comment<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> -where - E: ParseError<&'a str> + ContextError<&'a str>, -{ - context( - "comment", - value( - FlatAtom::Comment, - delimited( - char(Atom::COMMENT.0), - take_till(|c| c == Atom::COMMENT.1), - char(Atom::COMMENT.1), - ), - ), - )(i) -} - -fn atom<'a, E>(notes: &'a str) -> impl Parser<&'a str, FlatAtom, E> +pub fn atom<'a, E>(notes: &'a str) -> impl Parser<&'a str, FlatAtom, E> where E: ParseError<&'a str> + ContextError<&'a str> @@ -201,18 +35,49 @@ where context( "atom", alt(( - note(notes), - rest, - start_here, - modifier, - quick_modifier, - loop_starts, - loop_ends, - tuple_starts, - tuple_ends, - slope_starts, - slope_ends, - comment, + 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).map(FlatAtom::Modifier), + quick_modifier.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::SLOPE.0), + separated_pair( + slope_modifier, + char(' '), + map_res(take_till1(|c| c == ','), |s: &str| { + s.parse() + .map_err(|_| E::from_error_kind(s, 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), + ), + ), )), ) }