context & function names without another Parse trait
This commit is contained in:
parent
78d7c493bb
commit
a2566f1be3
6 changed files with 192 additions and 104 deletions
|
@ -7,6 +7,7 @@ edition = "2021"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
Inflector = "0.11.4"
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
syn = { version = "2.0", features = ["full"] }
|
syn = { version = "2.0", features = ["full"] }
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
use inflector::Inflector;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::quote;
|
use quote::{quote, ToTokens};
|
||||||
use syn::{parse_macro_input, Data, DataEnum, DeriveInput, Ident};
|
use syn::{parse_macro_input, Data, DataEnum, DeriveInput, Fields, FieldsUnnamed, Ident};
|
||||||
|
|
||||||
#[proc_macro_derive(SlopeModifierParser)]
|
#[proc_macro_derive(SlopeModifierParser)]
|
||||||
pub fn slope_modifier_parser(input: TokenStream) -> TokenStream {
|
pub fn slope_modifier_parser(input: TokenStream) -> TokenStream {
|
||||||
|
@ -16,24 +17,49 @@ pub fn quick_modifier_parser(input: TokenStream) -> TokenStream {
|
||||||
impl_quick_modifier_parser(ast)
|
impl_quick_modifier_parser(ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(ModifierParser)]
|
||||||
|
pub fn modifier_parser(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
|
impl_modifier_parser(ast)
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ToIdent: ToString {
|
||||||
|
fn to_ident(&self) -> Ident {
|
||||||
|
Ident::new(&self.to_string(), Span::call_site())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: ToString> ToIdent for S {}
|
||||||
|
|
||||||
fn impl_slope_modifier_parser(ast: DeriveInput) -> TokenStream {
|
fn impl_slope_modifier_parser(ast: DeriveInput) -> TokenStream {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
|
let fn_name = name.to_string().to_snake_case().to_ident();
|
||||||
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
|
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
|
||||||
let match_arms = variants.iter().map(|variant| {
|
let match_arms = variants.iter().map(|variant| {
|
||||||
let variant_name = &variant.ident;
|
let variant_name = &variant.ident;
|
||||||
let const_name = Ident::new(&variant.ident.to_string().to_uppercase(),Span::call_site());
|
let variant_name_lower = variant_name.to_string().to_lowercase().to_ident();
|
||||||
|
let const_name = &variant.ident.to_string().to_uppercase().to_ident();
|
||||||
quote! {
|
quote! {
|
||||||
nom::combinator::value(#name::#variant_name, nom::character::complete::char(SlopeModifier::#const_name))
|
nom::error::context(
|
||||||
|
stringify!(#variant_name_lower),
|
||||||
|
nom::combinator::value(
|
||||||
|
#name::#variant_name,
|
||||||
|
nom::character::complete::char(SlopeModifier::#const_name)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl lex::lexer::Parse for #name {
|
pub fn #fn_name<'a, E: nom::error::ParseError<&'a str> + nom::error::ContextError<&'a str>>(
|
||||||
fn parse(input: &str) -> nom::IResult<&str, #name> {
|
i: &'a str,
|
||||||
|
) -> nom::IResult<&'a str, #name, E> {
|
||||||
|
nom::error::context(
|
||||||
|
"slope modifier",
|
||||||
nom::branch::alt((
|
nom::branch::alt((
|
||||||
#(#match_arms),*
|
#(#match_arms),*
|
||||||
))(input)
|
))
|
||||||
}
|
)(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
|
@ -44,12 +70,15 @@ fn impl_slope_modifier_parser(ast: DeriveInput) -> TokenStream {
|
||||||
|
|
||||||
fn impl_quick_modifier_parser(ast: DeriveInput) -> TokenStream {
|
fn impl_quick_modifier_parser(ast: DeriveInput) -> TokenStream {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
|
let fn_name = name.to_string().to_snake_case().to_ident();
|
||||||
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
|
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
|
||||||
let match_arms = variants.iter().map(|variant| {
|
let match_arms = variants.iter().map(|variant| {
|
||||||
let variant_name = &variant.ident;
|
let variant_name = &variant.ident;
|
||||||
let const_name =
|
let variant_name_lower = variant_name.to_string().to_lowercase().to_ident();
|
||||||
Ident::new(&variant.ident.to_string().to_uppercase(), Span::call_site());
|
let const_name = &variant.ident.to_string().to_uppercase().to_ident();
|
||||||
quote! {
|
quote! {
|
||||||
|
nom::error::context(
|
||||||
|
stringify!(#variant_name_lower),
|
||||||
nom::combinator::map(
|
nom::combinator::map(
|
||||||
nom::branch::alt(
|
nom::branch::alt(
|
||||||
(
|
(
|
||||||
|
@ -65,16 +94,86 @@ fn impl_quick_modifier_parser(ast: DeriveInput) -> TokenStream {
|
||||||
),
|
),
|
||||||
#name::#variant_name
|
#name::#variant_name
|
||||||
)
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl lex::lexer::Parse for #name {
|
pub fn #fn_name<'a, E: nom::error::ParseError<&'a str> + nom::error::ContextError<&'a str>>(
|
||||||
fn parse(input: &str) -> nom::IResult<&str, #name> {
|
i: &'a str,
|
||||||
|
) -> nom::IResult<&'a str, #name, E> {
|
||||||
|
nom::error::context(
|
||||||
|
"quick modifier",
|
||||||
nom::branch::alt((
|
nom::branch::alt((
|
||||||
#(#match_arms),*
|
#(#match_arms),*
|
||||||
))(input)
|
))
|
||||||
}
|
)(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
panic!("this macro only works on enums")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn impl_modifier_parser(ast: DeriveInput) -> TokenStream {
|
||||||
|
let name = &ast.ident;
|
||||||
|
let fn_name = name.to_string().to_snake_case().to_ident();
|
||||||
|
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
|
||||||
|
let match_arms = variants.iter().map(|variant| {
|
||||||
|
let variant_name = &variant.ident;
|
||||||
|
let variant_name_lower = variant_name.to_string().to_lowercase().to_ident();
|
||||||
|
let const_name = &variant.ident.to_string().to_uppercase().to_ident();
|
||||||
|
if let Fields::Unnamed(FieldsUnnamed {
|
||||||
|
paren_token: _,
|
||||||
|
unnamed,
|
||||||
|
}) = &variant.fields
|
||||||
|
{
|
||||||
|
let type_name = {
|
||||||
|
let type_name = &unnamed[0].ty.to_token_stream().to_string();
|
||||||
|
match type_name.strip_prefix("NonZero") {
|
||||||
|
Some(s) => {
|
||||||
|
let lower = s.to_lowercase().to_ident();
|
||||||
|
let type_name = &unnamed[0].ty;
|
||||||
|
quote! {
|
||||||
|
nom::combinator::map_opt(
|
||||||
|
nom::character::complete::#lower,
|
||||||
|
std::num::#type_name::new
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let type_name = &unnamed[0].ty;
|
||||||
|
quote! {
|
||||||
|
nom::character::complete::#type_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
nom::error::context(
|
||||||
|
stringify!(#variant_name_lower),
|
||||||
|
nom::combinator::map(
|
||||||
|
nom::sequence::preceded(nom::character::complete::char(#name::#const_name), #type_name),
|
||||||
|
#name::#variant_name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("this macro only works on unnamed fields")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
pub fn #fn_name<'a, E: nom::error::ParseError<&'a str> + nom::error::ContextError<&'a str>>(
|
||||||
|
i: &'a str,
|
||||||
|
) -> nom::IResult<&'a str, #name, E> {
|
||||||
|
nom::error::context(
|
||||||
|
"modifier",
|
||||||
|
nom::branch::alt((
|
||||||
|
#(#match_arms),*
|
||||||
|
))
|
||||||
|
)(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
|
|
|
@ -5,10 +5,10 @@ use std::{
|
||||||
|
|
||||||
use amplify::From;
|
use amplify::From;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use bng_macros::{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::flat_atom_parser;
|
use lex::lexer::atom;
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
character::{complete::char, streaming::one_of},
|
character::{complete::char, streaming::one_of},
|
||||||
|
@ -91,7 +91,7 @@ impl Clone for FlatAtom {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, ModifierParser)]
|
||||||
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
|
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
|
||||||
pub enum Modifier {
|
pub enum Modifier {
|
||||||
Volume(u8),
|
Volume(u8),
|
||||||
|
|
|
@ -12,7 +12,7 @@ use serde::{
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::bng::score::lex::lexer::flat_atom_parser;
|
use crate::bng::score::lex::lexer::atom;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
utils::{inflate, InflateError},
|
utils::{inflate, InflateError},
|
||||||
|
@ -64,7 +64,7 @@ impl<'de> Deserialize<'de> for Atoms {
|
||||||
if sheet.is_empty() {
|
if sheet.is_empty() {
|
||||||
Ok(Default::default())
|
Ok(Default::default())
|
||||||
} else {
|
} else {
|
||||||
flat_atom_parser_mapper::<D, _>(&sheet, flat_atom_parser(¬es))
|
atom_mapper::<D, _>(&sheet, atom(¬es))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ where
|
||||||
many0(one_of(" \t\r"))
|
many0(one_of(" \t\r"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flat_atom_parser_mapper<'a, 'de, D, P>(
|
fn atom_mapper<'a, 'de, D, P>(
|
||||||
input: &'a str,
|
input: &'a str,
|
||||||
parser: P,
|
parser: P,
|
||||||
) -> Result<Atoms, <D as Deserializer<'de>>::Error>
|
) -> Result<Atoms, <D as Deserializer<'de>>::Error>
|
||||||
|
|
|
@ -10,41 +10,28 @@ use nom::{
|
||||||
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::{map_opt, map_res, opt, value, verify},
|
combinator::{map_opt, map_res, opt, value, verify},
|
||||||
|
error::{context, ContextError, ParseError},
|
||||||
multi::many0,
|
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,
|
super::super::Expression as Instruction, Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier,
|
||||||
{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub(crate) trait Parse: Sized {
|
pub fn atom(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Error<&str>> {
|
||||||
fn parse(input: &str) -> IResult<&str, Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for Modifier {
|
|
||||||
fn parse(input: &str) -> IResult<&str, Self> {
|
|
||||||
alt((
|
|
||||||
preceded(char(Modifier::VOLUME), u8).map(Modifier::Volume),
|
|
||||||
preceded(char(Modifier::OCTAVE), u8).map(Modifier::Octave),
|
|
||||||
preceded(char(Modifier::LENGTH), map_opt(u8, NonZeroU8::new)).map(Modifier::Length),
|
|
||||||
preceded(char(Modifier::TEMPO), map_opt(u16, NonZeroU16::new)).map(Modifier::Tempo),
|
|
||||||
))(input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flat_atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Error<&str>> {
|
|
||||||
alt((
|
alt((
|
||||||
map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from).map(FlatAtom::Note),
|
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::Rest, char(Atom::REST)),
|
||||||
value(FlatAtom::StartHere, char(Atom::START_HERE)),
|
value(FlatAtom::StartHere, char(Atom::START_HERE)),
|
||||||
preceded(char(Atom::MODIFIER), Modifier::parse).map(FlatAtom::Modifier),
|
preceded(char(Atom::MODIFIER), modifier).map(FlatAtom::Modifier),
|
||||||
QuickModifier::parse.map(FlatAtom::QuickModifier),
|
quick_modifier.map(FlatAtom::QuickModifier),
|
||||||
preceded(
|
preceded(
|
||||||
char(Atom::LOOP.0),
|
char(Atom::LOOP.0),
|
||||||
map_opt(opt(u8), |n| {
|
map_opt(opt(u8), |n| {
|
||||||
|
@ -63,7 +50,7 @@ pub fn flat_atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::
|
||||||
preceded(
|
preceded(
|
||||||
char(Atom::SLOPE.0),
|
char(Atom::SLOPE.0),
|
||||||
separated_pair(
|
separated_pair(
|
||||||
SlopeModifier::parse,
|
slope_modifier,
|
||||||
char(' '),
|
char(' '),
|
||||||
map_res(take_till1(|c| c == ','), |s: &str| {
|
map_res(take_till1(|c| c == ','), |s: &str| {
|
||||||
s.parse()
|
s.parse()
|
||||||
|
|
|
@ -15,8 +15,8 @@ mod flat_atom {
|
||||||
use nom::Parser;
|
use nom::Parser;
|
||||||
|
|
||||||
use super::super::{
|
use super::super::{
|
||||||
super::super::super::Expression as Instruction, super::UP, flat_atom_parser, Atom,
|
super::super::super::Expression as Instruction, super::UP, atom, Atom, FlatAtom, Modifier,
|
||||||
FlatAtom, Modifier, QuickModifier, SlopeModifier,
|
QuickModifier, SlopeModifier,
|
||||||
};
|
};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ mod flat_atom {
|
||||||
fn note() {
|
fn note() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, FlatAtom::Note(2))),
|
Ok((SAMPLE_STR, FlatAtom::Note(2))),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!('c', SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!('c', SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ mod flat_atom {
|
||||||
fn rest() {
|
fn rest() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, FlatAtom::Rest)),
|
Ok((SAMPLE_STR, FlatAtom::Rest)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::REST, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::REST, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ mod flat_atom {
|
||||||
fn start_here() {
|
fn start_here() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, FlatAtom::StartHere)),
|
Ok((SAMPLE_STR, FlatAtom::StartHere)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::START_HERE, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::START_HERE, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,12 +62,7 @@ mod flat_atom {
|
||||||
SAMPLE_STR,
|
SAMPLE_STR,
|
||||||
FlatAtom::Modifier(Modifier::Length(unsafe { NonZeroU8::new_unchecked(2) }))
|
FlatAtom::Modifier(Modifier::Length(unsafe { NonZeroU8::new_unchecked(2) }))
|
||||||
)),
|
)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(
|
atom("abcdefg").parse(concatcp!(Atom::MODIFIER, Modifier::LENGTH, 2u8, SAMPLE_STR))
|
||||||
Atom::MODIFIER,
|
|
||||||
Modifier::LENGTH,
|
|
||||||
2u8,
|
|
||||||
SAMPLE_STR
|
|
||||||
))
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +73,7 @@ mod flat_atom {
|
||||||
SAMPLE_STR,
|
SAMPLE_STR,
|
||||||
FlatAtom::QuickModifier(QuickModifier::Length(UP))
|
FlatAtom::QuickModifier(QuickModifier::Length(UP))
|
||||||
)),
|
)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(QuickModifier::LENGTH.0, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(QuickModifier::LENGTH.0, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,21 +84,21 @@ mod flat_atom {
|
||||||
SAMPLE_STR,
|
SAMPLE_STR,
|
||||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) })
|
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) })
|
||||||
)),
|
)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::LOOP.0, 3u8, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::LOOP.0, 3u8, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((
|
Ok((
|
||||||
SAMPLE_STR,
|
SAMPLE_STR,
|
||||||
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(2) })
|
FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(2) })
|
||||||
)),
|
)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::LOOP.0, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::LOOP.0, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(nom::Err::Error(Error::new(
|
Err(nom::Err::Error(Error::new(
|
||||||
concatcp!(Atom::LOOP.0, 0u8, SAMPLE_STR),
|
concatcp!(Atom::LOOP.0, 0u8, SAMPLE_STR),
|
||||||
ErrorKind::Char
|
ErrorKind::Char
|
||||||
))),
|
))),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::LOOP.0, 0u8, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::LOOP.0, 0u8, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +106,7 @@ mod flat_atom {
|
||||||
fn loop_ends() {
|
fn loop_ends() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, FlatAtom::LoopEnds)),
|
Ok((SAMPLE_STR, FlatAtom::LoopEnds)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::LOOP.1, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::LOOP.1, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +114,7 @@ mod flat_atom {
|
||||||
fn tuple_starts() {
|
fn tuple_starts() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, FlatAtom::TupleStarts)),
|
Ok((SAMPLE_STR, FlatAtom::TupleStarts)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::TUPLE.0, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::TUPLE.0, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +122,7 @@ mod flat_atom {
|
||||||
fn tuple_ends() {
|
fn tuple_ends() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, FlatAtom::TupleEnds)),
|
Ok((SAMPLE_STR, FlatAtom::TupleEnds)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::TUPLE.1, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::TUPLE.1, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +133,7 @@ mod flat_atom {
|
||||||
SAMPLE_STR,
|
SAMPLE_STR,
|
||||||
FlatAtom::SlopeStarts(SlopeModifier::Note, FASTEVAL_INSTRUCTION.parse().unwrap())
|
FlatAtom::SlopeStarts(SlopeModifier::Note, FASTEVAL_INSTRUCTION.parse().unwrap())
|
||||||
)),
|
)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(
|
atom("abcdefg").parse(concatcp!(
|
||||||
Atom::SLOPE.0,
|
Atom::SLOPE.0,
|
||||||
SlopeModifier::NOTE,
|
SlopeModifier::NOTE,
|
||||||
' ',
|
' ',
|
||||||
|
@ -153,7 +148,7 @@ mod flat_atom {
|
||||||
fn slope_ends() {
|
fn slope_ends() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, FlatAtom::SlopeEnds)),
|
Ok((SAMPLE_STR, FlatAtom::SlopeEnds)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(Atom::SLOPE.1, SAMPLE_STR))
|
atom("abcdefg").parse(concatcp!(Atom::SLOPE.1, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +156,7 @@ mod flat_atom {
|
||||||
fn comment() {
|
fn comment() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, FlatAtom::Comment)),
|
Ok((SAMPLE_STR, FlatAtom::Comment)),
|
||||||
flat_atom_parser("abcdefg").parse(concatcp!(
|
atom("abcdefg").parse(concatcp!(
|
||||||
Atom::COMMENT.0,
|
Atom::COMMENT.0,
|
||||||
"hi I'm a little pony",
|
"hi I'm a little pony",
|
||||||
SAMPLE_STR,
|
SAMPLE_STR,
|
||||||
|
@ -175,22 +170,24 @@ mod flat_atom {
|
||||||
mod modifier {
|
mod modifier {
|
||||||
use std::num::{NonZeroU16, NonZeroU8};
|
use std::num::{NonZeroU16, NonZeroU8};
|
||||||
|
|
||||||
|
use const_format::concatcp;
|
||||||
|
use nom::error::{Error, ErrorKind, VerboseError};
|
||||||
|
|
||||||
use super::FLATATOM_SAMPLE_STRING as SAMPLE_STR;
|
use super::FLATATOM_SAMPLE_STRING as SAMPLE_STR;
|
||||||
use super::*;
|
use crate::bng::score::{modifier, Modifier};
|
||||||
use crate::bng::score::{lex::lexer::Parse, Modifier};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn volume() {
|
fn volume() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, Modifier::Volume(2))),
|
Ok((SAMPLE_STR, Modifier::Volume(2))),
|
||||||
Modifier::parse(concatcp!(Modifier::VOLUME, 2u8, SAMPLE_STR))
|
modifier::<VerboseError<&str>>(concatcp!(Modifier::VOLUME, 2u8, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(nom::Err::Error(Error::new(
|
Err(nom::Err::Error(Error::new(
|
||||||
concatcp!(Modifier::VOLUME, 2556u16, SAMPLE_STR),
|
concatcp!(Modifier::VOLUME, 2556u16, SAMPLE_STR),
|
||||||
ErrorKind::Char
|
ErrorKind::Char
|
||||||
))),
|
))),
|
||||||
Modifier::parse(concatcp!(Modifier::VOLUME, 2556u16, SAMPLE_STR))
|
modifier(concatcp!(Modifier::VOLUME, 2556u16, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,14 +195,14 @@ mod modifier {
|
||||||
fn octave() {
|
fn octave() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, Modifier::Octave(2))),
|
Ok((SAMPLE_STR, Modifier::Octave(2))),
|
||||||
Modifier::parse(concatcp!(Modifier::OCTAVE, 2u8, SAMPLE_STR))
|
modifier::<VerboseError<&str>>(concatcp!(Modifier::OCTAVE, 2u8, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(nom::Err::Error(Error::new(
|
Err(nom::Err::Error(Error::new(
|
||||||
concatcp!(Modifier::OCTAVE, 2556u16, SAMPLE_STR),
|
concatcp!(Modifier::OCTAVE, 2556u16, SAMPLE_STR),
|
||||||
ErrorKind::Char
|
ErrorKind::Char
|
||||||
))),
|
))),
|
||||||
Modifier::parse(concatcp!(Modifier::OCTAVE, 2556u16, SAMPLE_STR))
|
modifier(concatcp!(Modifier::OCTAVE, 2556u16, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,21 +213,21 @@ mod modifier {
|
||||||
SAMPLE_STR,
|
SAMPLE_STR,
|
||||||
Modifier::Length(unsafe { NonZeroU8::new_unchecked(2) })
|
Modifier::Length(unsafe { NonZeroU8::new_unchecked(2) })
|
||||||
)),
|
)),
|
||||||
Modifier::parse(concatcp!(Modifier::LENGTH, 2u8, SAMPLE_STR))
|
modifier::<VerboseError<&str>>(concatcp!(Modifier::LENGTH, 2u8, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(nom::Err::Error(Error::new(
|
Err(nom::Err::Error(Error::new(
|
||||||
concatcp!(Modifier::LENGTH, 2556u16, SAMPLE_STR),
|
concatcp!(Modifier::LENGTH, 2556u16, SAMPLE_STR),
|
||||||
ErrorKind::Char
|
ErrorKind::Char
|
||||||
))),
|
))),
|
||||||
Modifier::parse(concatcp!(Modifier::LENGTH, 2556u16, SAMPLE_STR))
|
modifier(concatcp!(Modifier::LENGTH, 2556u16, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(nom::Err::Error(Error::new(
|
Err(nom::Err::Error(Error::new(
|
||||||
concatcp!(Modifier::LENGTH, 0u8, SAMPLE_STR),
|
concatcp!(Modifier::LENGTH, 0u8, SAMPLE_STR),
|
||||||
ErrorKind::Char
|
ErrorKind::Char
|
||||||
))),
|
))),
|
||||||
Modifier::parse(concatcp!(Modifier::LENGTH, 0u8, SAMPLE_STR))
|
modifier(concatcp!(Modifier::LENGTH, 0u8, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,35 +238,37 @@ mod modifier {
|
||||||
SAMPLE_STR,
|
SAMPLE_STR,
|
||||||
Modifier::Tempo(unsafe { NonZeroU16::new_unchecked(2) })
|
Modifier::Tempo(unsafe { NonZeroU16::new_unchecked(2) })
|
||||||
)),
|
)),
|
||||||
Modifier::parse(concatcp!(Modifier::TEMPO, 2u8, SAMPLE_STR))
|
modifier::<VerboseError<&str>>(concatcp!(Modifier::TEMPO, 2u8, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(nom::Err::Error(Error::new(
|
Err(nom::Err::Error(Error::new(
|
||||||
concatcp!(655353u32, SAMPLE_STR),
|
concatcp!(655353u32, SAMPLE_STR),
|
||||||
ErrorKind::Digit
|
ErrorKind::Digit
|
||||||
))),
|
))),
|
||||||
Modifier::parse(concatcp!(Modifier::TEMPO, 655353u32, SAMPLE_STR))
|
modifier(concatcp!(Modifier::TEMPO, 655353u32, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod quick_modifier {
|
mod quick_modifier {
|
||||||
|
use const_format::concatcp;
|
||||||
|
use nom::error::VerboseError;
|
||||||
|
|
||||||
use super::FLATATOM_SAMPLE_STRING as SAMPLE_STR;
|
use super::FLATATOM_SAMPLE_STRING as SAMPLE_STR;
|
||||||
use super::*;
|
|
||||||
use crate::bng::score::{
|
use crate::bng::score::{
|
||||||
lex::{lexer::Parse, DOWN, OFF, ON, UP},
|
lex::{DOWN, OFF, ON, UP},
|
||||||
QuickModifier,
|
quick_modifier, QuickModifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn volume() {
|
fn volume() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, QuickModifier::Volume(UP))),
|
Ok((SAMPLE_STR, QuickModifier::Volume(UP))),
|
||||||
QuickModifier::parse(concatcp!(QuickModifier::VOLUME.0, SAMPLE_STR))
|
quick_modifier::<VerboseError<&str>>(concatcp!(QuickModifier::VOLUME.0, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, QuickModifier::Volume(DOWN))),
|
Ok((SAMPLE_STR, QuickModifier::Volume(DOWN))),
|
||||||
QuickModifier::parse(concatcp!(QuickModifier::VOLUME.1, SAMPLE_STR))
|
quick_modifier::<VerboseError<&str>>(concatcp!(QuickModifier::VOLUME.1, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,11 +276,11 @@ mod quick_modifier {
|
||||||
fn octave() {
|
fn octave() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, QuickModifier::Octave(UP))),
|
Ok((SAMPLE_STR, QuickModifier::Octave(UP))),
|
||||||
QuickModifier::parse(concatcp!(QuickModifier::OCTAVE.0, SAMPLE_STR))
|
quick_modifier::<VerboseError<&str>>(concatcp!(QuickModifier::OCTAVE.0, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, QuickModifier::Octave(DOWN))),
|
Ok((SAMPLE_STR, QuickModifier::Octave(DOWN))),
|
||||||
QuickModifier::parse(concatcp!(QuickModifier::OCTAVE.1, SAMPLE_STR))
|
quick_modifier::<VerboseError<&str>>(concatcp!(QuickModifier::OCTAVE.1, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,11 +288,11 @@ mod quick_modifier {
|
||||||
fn length() {
|
fn length() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, QuickModifier::Length(UP))),
|
Ok((SAMPLE_STR, QuickModifier::Length(UP))),
|
||||||
QuickModifier::parse(concatcp!(QuickModifier::LENGTH.0, SAMPLE_STR))
|
quick_modifier::<VerboseError<&str>>(concatcp!(QuickModifier::LENGTH.0, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, QuickModifier::Length(DOWN))),
|
Ok((SAMPLE_STR, QuickModifier::Length(DOWN))),
|
||||||
QuickModifier::parse(concatcp!(QuickModifier::LENGTH.1, SAMPLE_STR))
|
quick_modifier::<VerboseError<&str>>(concatcp!(QuickModifier::LENGTH.1, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,20 +300,22 @@ mod quick_modifier {
|
||||||
fn pizz() {
|
fn pizz() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, QuickModifier::Pizz(ON))),
|
Ok((SAMPLE_STR, QuickModifier::Pizz(ON))),
|
||||||
QuickModifier::parse(concatcp!(QuickModifier::PIZZ.0, SAMPLE_STR))
|
quick_modifier::<VerboseError<&str>>(concatcp!(QuickModifier::PIZZ.0, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, QuickModifier::Pizz(OFF))),
|
Ok((SAMPLE_STR, QuickModifier::Pizz(OFF))),
|
||||||
QuickModifier::parse(concatcp!(QuickModifier::PIZZ.1, SAMPLE_STR))
|
quick_modifier::<VerboseError<&str>>(concatcp!(QuickModifier::PIZZ.1, SAMPLE_STR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod slope_modifier {
|
mod slope_modifier {
|
||||||
|
use const_format::concatcp;
|
||||||
|
use nom::error::VerboseError;
|
||||||
|
|
||||||
use super::FLATATOM_FASTEVAL_INSTRUCTION as INSTRUCTION;
|
use super::FLATATOM_FASTEVAL_INSTRUCTION as INSTRUCTION;
|
||||||
use super::*;
|
use crate::bng::score::{slope_modifier, Atom, SlopeModifier};
|
||||||
use crate::bng::score::{lex::lexer::Parse, Atom, SlopeModifier};
|
|
||||||
|
|
||||||
const SAMPLE_STR: &str = concatcp!(' ', INSTRUCTION, Atom::SLOPE.1);
|
const SAMPLE_STR: &str = concatcp!(' ', INSTRUCTION, Atom::SLOPE.1);
|
||||||
|
|
||||||
|
@ -322,7 +323,7 @@ mod slope_modifier {
|
||||||
fn note() {
|
fn note() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, SlopeModifier::Note)),
|
Ok((SAMPLE_STR, SlopeModifier::Note)),
|
||||||
SlopeModifier::parse(concatcp!(SlopeModifier::NOTE, SAMPLE_STR))
|
slope_modifier::<VerboseError<&str>>(concatcp!(SlopeModifier::NOTE, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +331,7 @@ mod slope_modifier {
|
||||||
fn volume() {
|
fn volume() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, SlopeModifier::Volume)),
|
Ok((SAMPLE_STR, SlopeModifier::Volume)),
|
||||||
SlopeModifier::parse(concatcp!(SlopeModifier::VOLUME, SAMPLE_STR))
|
slope_modifier::<VerboseError<&str>>(concatcp!(SlopeModifier::VOLUME, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +339,7 @@ mod slope_modifier {
|
||||||
fn octave() {
|
fn octave() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, SlopeModifier::Octave)),
|
Ok((SAMPLE_STR, SlopeModifier::Octave)),
|
||||||
SlopeModifier::parse(concatcp!(SlopeModifier::OCTAVE, SAMPLE_STR))
|
slope_modifier::<VerboseError<&str>>(concatcp!(SlopeModifier::OCTAVE, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +347,7 @@ mod slope_modifier {
|
||||||
fn length() {
|
fn length() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, SlopeModifier::Length)),
|
Ok((SAMPLE_STR, SlopeModifier::Length)),
|
||||||
SlopeModifier::parse(concatcp!(SlopeModifier::LENGTH, SAMPLE_STR))
|
slope_modifier::<VerboseError<&str>>(concatcp!(SlopeModifier::LENGTH, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +355,7 @@ mod slope_modifier {
|
||||||
fn tempo() {
|
fn tempo() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((SAMPLE_STR, SlopeModifier::Tempo)),
|
Ok((SAMPLE_STR, SlopeModifier::Tempo)),
|
||||||
SlopeModifier::parse(concatcp!(SlopeModifier::TEMPO, SAMPLE_STR))
|
slope_modifier::<VerboseError<&str>>(concatcp!(SlopeModifier::TEMPO, SAMPLE_STR))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue