diff --git a/src/compiler.rs b/src/compiler.rs index d27c864..fc227a5 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -11,30 +11,25 @@ pub trait Token { } } -#[cfg_attr(debug_assertions, derive(Default))] #[derive(Clone, Copy)] pub struct Silence; impl Token for Silence {} -#[cfg_attr(debug_assertions, derive(Default))] #[derive(Clone, Copy)] pub struct Marker; impl Token for Marker {} -#[cfg_attr(debug_assertions, derive(Default))] #[derive(Clone, Copy)] pub struct Note(pub u8); impl Token for Note {} -#[cfg_attr(debug_assertions, derive(Default))] pub struct VariableChange(pub char, pub Expression); impl Token for VariableChange {} -#[cfg_attr(debug_assertions, derive(Default))] pub struct Loop(pub LoopCount, pub TokenVec); pub enum LoopCount { @@ -50,18 +45,16 @@ impl Default for LoopCount { impl Token for Loop {} -#[cfg_attr(debug_assertions, derive(Default))] pub struct Tuplet(pub TokenVec); impl Token for Tuplet {} -#[cfg_attr(debug_assertions, derive(Default))] -pub struct Slope(pub VariableChange, pub TokenVec); +pub struct Slope<'a>(pub &'a VariableChange, pub TokenVec); -impl Token for Slope {} +impl Token for Slope<'_> {} #[derive(new)] -#[cfg_attr(debug_assertions, derive(Debug, Default))] +#[cfg_attr(debug_assertions, derive(Debug))] pub struct Expression { pub(crate) instruction: Instruction, pub(crate) slab: Slab, diff --git a/src/parser.rs b/src/parser.rs index ad2e53b..cd99dd4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -20,7 +20,9 @@ use nom::{ }; use nom_locate::LocatedSpan; -use crate::compiler::{Expression, Loop, LoopCount, Marker, Note, Silence, Token, VariableChange}; +use crate::compiler::{ + Expression, Loop, LoopCount, Marker, Note, Silence, Slope, Token, Tuplet, VariableChange, +}; #[derive(Builder)] pub struct Parser<'i, 'n, 's, 'v> { @@ -30,7 +32,7 @@ pub struct Parser<'i, 'n, 's, 'v> { variables: &'v [char], } -impl<'i, 'n, 's, 'v> Parser<'i, 'n, 's, 'v> { +impl<'i> Parser<'i, '_, '_, '_> { pub fn parse_all( &self, ) -> Result>, Error>> { @@ -41,7 +43,7 @@ impl<'i, 'n, 's, 'v> Parser<'i, 'n, 's, 'v> { } } -fn token_parser<'a, 'i, 'n, 's, 'v>( +fn token_parser<'a>( parser: &Parser, ) -> impl NomParser< LocatedSpan<&'a str>, @@ -62,6 +64,8 @@ fn token_parser<'a, 'i, 'n, 's, 'v>( Note::parser(parser.notes).map(into_box), VariableChange::parser(parser.variables).map(into_box), Loop::parser(parser).map(into_box), + Tuplet::parser(parser).map(into_box), + Slope::parser(parser).map(into_box), )), space_or_comment(), )) @@ -132,9 +136,9 @@ impl VariableChange { } impl Loop { - fn parser<'a, 'i, 'n, 's, 'v>( + fn parser<'i, 'n, 's, 'v>( parser: &Parser<'i, 'n, 's, 'v>, - ) -> impl Fn(LocatedSpan<&str>) -> TokenResult { + ) -> impl Fn(LocatedSpan<&str>) -> TokenResult { |input| { delimited( char('('), @@ -151,6 +155,56 @@ impl Loop { } } +impl Tuplet { + fn parser<'i, 'n, 's, 'v>( + parser: &Parser<'i, 'n, 's, 'v>, + ) -> impl Fn(LocatedSpan<&str>) -> TokenResult { + |input| { + delimited(char('['), token_parser(parser), char(']')) + .map(Self) + .parse(input) + } + } +} + +impl<'s> Slope<'s> { + fn parser<'a, 'i, 'n, 'v>( + parser: &Parser<'i, 'n, 's, 'v>, + ) -> impl Fn(LocatedSpan<&'a str>) -> TokenResult<'a, Self> { + |input| { + delimited( + char('{'), + alt( + parser + .slopes + .iter() + .map(|(k, v)| { + Box::new(move |input: LocatedSpan<&'a str>| { + value(v, tag(k.as_str())).parse(input) + }) + as Box< + dyn Fn( + LocatedSpan<&'a str>, + ) + -> TokenResult<'a, &'s VariableChange>, + > + }) + .collect::) -> TokenResult<'a, &'s VariableChange>, + >, + >>() + .as_mut_slice(), + ) + .and(token_parser(parser)), + char('}'), + ) + .map(|(i, v)| Self(i, v)) + .parse(input) + } + } +} + /// Will return the longest valid fasteval expression fn expression_parser + Ord + Display>( variables: &[C],