tests for secondary parsers

This commit is contained in:
Breval Ferrari 2024-10-13 01:46:33 -04:00
parent b2b8546f20
commit 0465fb2e4c
No known key found for this signature in database
GPG key ID: 6FED68D87C479A59
6 changed files with 244 additions and 60 deletions

View file

@ -1,27 +1,31 @@
use bng_macros::{ModifierParser, QuickModifierParser, SlopeModifierParser};
use std::num::{NonZeroU16, NonZeroU8};
use bng_macros::{QuickModifierParser, SlopeModifierParser};
use fasteval::Instruction;
mod lex;
#[cfg_attr(test, derive(Debug, PartialEq))]
pub(super) enum Atom {
Note(char),
Rest,
StartHere,
Modifier(Modifier),
QuickModifier(QuickModifier),
Loop(u8, Vec<Atom>),
Loop(NonZeroU8, Vec<Atom>),
Tuple(Vec<Atom>),
Slope(SlopeModifier, Instruction, Vec<Atom>),
Comment,
}
#[cfg_attr(test, derive(Debug, PartialEq))]
pub(super) enum FlatAtom {
Note(char),
Rest,
StartHere,
Modifier(Modifier),
QuickModifier(QuickModifier),
LoopStarts(u8),
LoopStarts(NonZeroU8),
LoopEnds,
TupleStarts,
TupleEnds,
@ -39,12 +43,12 @@ impl Clone for FlatAtom {
}
}
#[derive(ModifierParser)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub(super) enum Modifier {
Volume(u8),
Octave(u8),
Length(u8),
Tempo(u16),
Length(NonZeroU8),
Tempo(NonZeroU16),
}
impl Default for Modifier {
@ -54,6 +58,7 @@ impl Default for Modifier {
}
#[derive(QuickModifierParser)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub(super) enum QuickModifier {
Volume(bool),
Octave(bool),
@ -62,6 +67,7 @@ pub(super) enum QuickModifier {
}
#[derive(Clone, Copy, SlopeModifierParser)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub(super) enum SlopeModifier {
Note,
Volume,

View file

@ -2,10 +2,10 @@ use super::{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier};
pub(super) mod lexer;
pub(super) const MORE: bool = true;
pub(super) const LESS: bool = false;
pub(super) const ON: bool = true;
pub(super) const OFF: bool = false;
pub(super) const UP: bool = true;
pub(super) const DOWN: bool = false;
struct WrappingTokens;
impl WrappingTokens {

View file

@ -1,12 +1,15 @@
use std::collections::BTreeMap;
use std::{
collections::BTreeMap,
num::{NonZeroU16, NonZeroU8},
};
use clap::builder::TypedValueParser;
use fasteval::{Compiler, Instruction};
use nom::{
branch::alt,
bytes::complete::take_till1,
character::complete::{anychar, char, one_of, u8},
combinator::{map_res, value},
character::complete::{anychar, char, one_of, u16, u8},
combinator::{map_opt, map_res, value},
multi::many0,
sequence::{delimited, pair, preceded, separated_pair},
Err, IResult, Parser,
@ -14,18 +17,32 @@ use nom::{
use crate::bng::score::{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier};
#[cfg(test)]
mod tests;
pub(crate) trait Parse: Sized {
fn parse(input: &str) -> IResult<&str, Self>;
}
fn atom_parser<'a>(notes: &'a str) -> impl Parser<&str, FlatAtom, nom::error::Error<&str>> {
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)
}
}
fn atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Error<&str>> {
alt((
one_of(notes).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), u8).map(FlatAtom::LoopStarts),
preceded(char(Atom::LOOP.0), map_opt(u8, NonZeroU8::new)).map(FlatAtom::LoopStarts),
value(FlatAtom::LoopEnds, char(Atom::LOOP.1)),
value(FlatAtom::TupleStarts, char(Atom::TUPLE.0)),
value(FlatAtom::TupleEnds, char(Atom::TUPLE.1)),

View file

@ -0,0 +1,204 @@
mod modifier {
use std::num::{NonZeroU16, NonZeroU8};
use const_format::concatcp;
use nom::{
error::{Error, ErrorKind},
Err,
};
use crate::bng::score::{lex::lexer::Parse, Atom, Modifier};
pub(super) const SAMPLE_STR: &str = concatcp!(
Atom::TUPLE.0,
"acc",
Atom::TUPLE.1,
"ed",
Atom::COMMENT.0,
"hello"
);
#[test]
fn volume() {
assert_eq!(
Ok((SAMPLE_STR, Modifier::Volume(2))),
Modifier::parse(concatcp!(Modifier::VOLUME, 2u8, SAMPLE_STR))
);
assert_eq!(
Err(nom::Err::Error(Error::new(
concatcp!(Modifier::VOLUME, 2556u16, SAMPLE_STR),
ErrorKind::Char
))),
Modifier::parse(concatcp!(Modifier::VOLUME, 2556u16, SAMPLE_STR))
);
}
#[test]
fn octave() {
assert_eq!(
Ok((SAMPLE_STR, Modifier::Octave(2))),
Modifier::parse(concatcp!(Modifier::OCTAVE, 2u8, SAMPLE_STR))
);
assert_eq!(
Err(nom::Err::Error(Error::new(
concatcp!(Modifier::OCTAVE, 2556u16, SAMPLE_STR),
ErrorKind::Char
))),
Modifier::parse(concatcp!(Modifier::OCTAVE, 2556u16, SAMPLE_STR))
);
}
#[test]
fn length() {
assert_eq!(
Ok((
SAMPLE_STR,
Modifier::Length(unsafe { NonZeroU8::new_unchecked(2) })
)),
Modifier::parse(concatcp!(Modifier::LENGTH, 2u8, SAMPLE_STR))
);
assert_eq!(
Err(nom::Err::Error(Error::new(
concatcp!(Modifier::LENGTH, 2556u16, SAMPLE_STR),
ErrorKind::Char
))),
Modifier::parse(concatcp!(Modifier::LENGTH, 2556u16, SAMPLE_STR))
);
assert_eq!(
Err(nom::Err::Error(Error::new(
concatcp!(Modifier::LENGTH, 0u8, SAMPLE_STR),
ErrorKind::Char
))),
Modifier::parse(concatcp!(Modifier::LENGTH, 0u8, SAMPLE_STR))
);
}
#[test]
fn tempo() {
assert_eq!(
Ok((
SAMPLE_STR,
Modifier::Tempo(unsafe { NonZeroU16::new_unchecked(2) })
)),
Modifier::parse(concatcp!(Modifier::TEMPO, 2u8, SAMPLE_STR))
);
assert_eq!(
Err(nom::Err::Error(Error::new(
concatcp!(655353u32, SAMPLE_STR),
ErrorKind::Digit
))),
Modifier::parse(concatcp!(Modifier::TEMPO, 655353u32, SAMPLE_STR))
);
}
}
use modifier::SAMPLE_STR as MODIFIER_SAMPLE_STRING;
mod quick_modifier {
use const_format::concatcp;
use nom::{error::Error, Err};
use super::MODIFIER_SAMPLE_STRING as SAMPLE_STR;
use crate::bng::score::{
lex::{lexer::Parse, DOWN, OFF, ON, UP},
Atom, QuickModifier,
};
#[test]
fn volume() {
assert_eq!(
Ok((SAMPLE_STR, QuickModifier::Volume(UP))),
QuickModifier::parse(concatcp!(QuickModifier::VOLUME.0, SAMPLE_STR))
);
assert_eq!(
Ok((SAMPLE_STR, QuickModifier::Volume(DOWN))),
QuickModifier::parse(concatcp!(QuickModifier::VOLUME.1, SAMPLE_STR))
);
}
#[test]
fn octave() {
assert_eq!(
Ok((SAMPLE_STR, QuickModifier::Octave(UP))),
QuickModifier::parse(concatcp!(QuickModifier::OCTAVE.0, SAMPLE_STR))
);
assert_eq!(
Ok((SAMPLE_STR, QuickModifier::Octave(DOWN))),
QuickModifier::parse(concatcp!(QuickModifier::OCTAVE.1, SAMPLE_STR))
);
}
#[test]
fn length() {
assert_eq!(
Ok((SAMPLE_STR, QuickModifier::Length(UP))),
QuickModifier::parse(concatcp!(QuickModifier::LENGTH.0, SAMPLE_STR))
);
assert_eq!(
Ok((SAMPLE_STR, QuickModifier::Length(DOWN))),
QuickModifier::parse(concatcp!(QuickModifier::LENGTH.1, SAMPLE_STR))
);
}
#[test]
fn pizz() {
assert_eq!(
Ok((SAMPLE_STR, QuickModifier::Pizz(ON))),
QuickModifier::parse(concatcp!(QuickModifier::PIZZ.0, SAMPLE_STR))
);
assert_eq!(
Ok((SAMPLE_STR, QuickModifier::Pizz(OFF))),
QuickModifier::parse(concatcp!(QuickModifier::PIZZ.1, SAMPLE_STR))
);
}
}
#[cfg(test)]
mod slope_modifier {
use const_format::concatcp;
use nom::{error::Error, Err};
use crate::bng::score::{lex::lexer::Parse, Atom, SlopeModifier};
const SAMPLE_STR: &str = concatcp!(" 1-cos((PI*x)/2),acced", Atom::SLOPE.1);
#[test]
fn note() {
assert_eq!(
Ok((SAMPLE_STR, SlopeModifier::Note)),
SlopeModifier::parse(concatcp!(SlopeModifier::NOTE, SAMPLE_STR))
)
}
#[test]
fn volume() {
assert_eq!(
Ok((SAMPLE_STR, SlopeModifier::Volume)),
SlopeModifier::parse(concatcp!(SlopeModifier::VOLUME, SAMPLE_STR))
)
}
#[test]
fn octave() {
assert_eq!(
Ok((SAMPLE_STR, SlopeModifier::Octave)),
SlopeModifier::parse(concatcp!(SlopeModifier::OCTAVE, SAMPLE_STR))
)
}
#[test]
fn length() {
assert_eq!(
Ok((SAMPLE_STR, SlopeModifier::Length)),
SlopeModifier::parse(concatcp!(SlopeModifier::LENGTH, SAMPLE_STR))
)
}
#[test]
fn tempo() {
assert_eq!(
Ok((SAMPLE_STR, SlopeModifier::Tempo)),
SlopeModifier::parse(concatcp!(SlopeModifier::TEMPO, SAMPLE_STR))
)
}
}