Compare commits

..

No commits in common. "9c910b80764e9450c026de14455a0fc926d8c7b4" and "315238f14d914babefbd731524c26fe8d1e78b8b" have entirely different histories.

4 changed files with 71 additions and 195 deletions

View file

@ -21,7 +21,6 @@ bng_macros = { path = "bng_macros" }
const_format = "0.2.33" const_format = "0.2.33"
thiserror = "1.0.64" thiserror = "1.0.64"
derive-new = "0.7.0" derive-new = "0.7.0"
naan = "0.1.32"
[features] [features]
default = ["play", "save"] default = ["play", "save"]

View file

@ -8,6 +8,7 @@ use anyhow::Context;
use bng_macros::{ModifierParser, QuickModifierParser, SlopeModifierParser}; use bng_macros::{ModifierParser, QuickModifierParser, SlopeModifierParser};
use derive_new::new; use derive_new::new;
use derived_deref::Deref; use derived_deref::Deref;
use lex::lexer::atom;
use nom::{ use nom::{
branch::alt, branch::alt,
character::{complete::char, streaming::one_of}, character::{complete::char, streaming::one_of},

View file

@ -1,11 +1,9 @@
use std::{ use std::{
fmt::{Debug, Display}, fmt::{Debug, Display},
num::TryFromIntError, num::TryFromIntError,
ops::Deref,
}; };
use derive_new::new; use derive_new::new;
use naan::fun::{F1Once, F2Once};
use nom::{ use nom::{
character::complete::one_of, character::complete::one_of,
combinator::all_consuming, combinator::all_consuming,
@ -20,7 +18,7 @@ use serde::{
}; };
use thiserror::Error; use thiserror::Error;
use crate::bng::score::lex::lexer::root; use crate::bng::score::lex::lexer::atom;
use super::{ use super::{
utils::{inflate, InflateError}, utils::{inflate, InflateError},
@ -56,7 +54,11 @@ impl<'de> Deserialize<'de> for Atoms {
Ok(Default::default()) Ok(Default::default())
} else { } else {
root(&sheet, &notes) root(&sheet, &notes)
.map_err(|e| pretty_verbose_err.curry().call1(sheet.as_str()).call1(e)) .map_err(|e: nom::Err<VerboseError<&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(sheet.as_str(), e),
})
.map_err(AtomsSerializeError::Parsing) .map_err(AtomsSerializeError::Parsing)
.map_err(de::Error::custom) .map_err(de::Error::custom)
.and_then(|(_, v)| { .and_then(|(_, v)| {
@ -69,13 +71,22 @@ impl<'de> Deserialize<'de> for Atoms {
} }
} }
fn pretty_verbose_err<I>(input: I, e: nom::Err<VerboseError<I>>) -> String fn maybe_yml_str_space<'a, E>() -> impl Parser<&'a str, Vec<char>, E>
where where
I: Deref<Target = str>, E: nom::error::ParseError<&'a str> + ContextError<&'a str>,
{ {
match e { context("yml white space", many0(one_of(" \t\r\n")))
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), fn root<'a, E>(i: &'a str, notes: &'a str) -> IResult<&'a str, Vec<FlatAtom>, 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)
} }

View file

@ -9,13 +9,15 @@ use nom::{
branch::alt, branch::alt,
bytes::complete::{take_till, take_till1}, bytes::complete::{take_till, take_till1},
character::complete::{anychar, char, one_of, space1, u16, u8}, 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}, error::{context, ContextError, ErrorKind, FromExternalError, ParseError},
multi::{many0, many1}, multi::many0,
sequence::{delimited, pair, preceded, separated_pair, terminated}, sequence::{delimited, pair, preceded, separated_pair, terminated},
Err, IResult, Parser, Err, IResult, Parser,
}; };
use crate::bng::score::{modifier, quick_modifier, slope_modifier};
use super::{ use super::{
super::super::Expression as Instruction, Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier, super::super::Expression as Instruction, Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier,
}; };
@ -23,175 +25,7 @@ use super::{
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
fn maybe_yml_str_space<'a, E>() -> impl Parser<&'a str, Vec<char>, E> pub fn atom<'a, E>(notes: &'a str) -> impl Parser<&'a str, FlatAtom, 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<FlatAtom>, 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>
where where
E: ParseError<&'a str> E: ParseError<&'a str>
+ ContextError<&'a str> + ContextError<&'a str>
@ -201,18 +35,49 @@ where
context( context(
"atom", "atom",
alt(( alt((
note(notes), map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from).map(FlatAtom::Note),
rest, value(FlatAtom::Rest, char(Atom::REST)),
start_here, value(FlatAtom::StartHere, char(Atom::START_HERE)),
modifier, preceded(char(Atom::MODIFIER), modifier).map(FlatAtom::Modifier),
quick_modifier, quick_modifier.map(FlatAtom::QuickModifier),
loop_starts, preceded(
loop_ends, char(Atom::LOOP.0),
tuple_starts, map_opt(opt(u8), |n| {
tuple_ends, if let Some(n) = n {
slope_starts, NonZeroU8::new(n)
slope_ends, } else {
comment, 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),
),
),
)), )),
) )
} }