atom parser

This commit is contained in:
Ponj 2024-10-12 17:28:33 -04:00
parent 9e0ead7605
commit b2b8546f20
Signed by: p6nj
GPG key ID: 6FED68D87C479A59
2 changed files with 67 additions and 6 deletions

View file

@ -2,10 +2,9 @@ use bng_macros::{ModifierParser, QuickModifierParser, SlopeModifierParser};
use fasteval::Instruction;
mod lex;
use lex::Token;
pub(super) enum Atom {
Note(u8),
Note(char),
Rest,
StartHere,
Modifier(Modifier),
@ -16,6 +15,30 @@ pub(super) enum Atom {
Comment,
}
pub(super) enum FlatAtom {
Note(char),
Rest,
StartHere,
Modifier(Modifier),
QuickModifier(QuickModifier),
LoopStarts(u8),
LoopEnds,
TupleStarts,
TupleEnds,
SlopeStarts(SlopeModifier, Instruction),
SlopeEnds,
Comment,
}
impl Clone for FlatAtom {
fn clone(&self) -> Self {
match self {
Self::Rest => Self::Rest,
_ => unimplemented!("variant can't be cloned"),
}
}
}
#[derive(ModifierParser)]
pub(super) enum Modifier {
Volume(u8),
@ -24,6 +47,12 @@ pub(super) enum Modifier {
Tempo(u16),
}
impl Default for Modifier {
fn default() -> Self {
Modifier::Volume(Default::default())
}
}
#[derive(QuickModifierParser)]
pub(super) enum QuickModifier {
Volume(bool),

View file

@ -1,13 +1,18 @@
use std::collections::BTreeMap;
use clap::builder::TypedValueParser;
use fasteval::{Compiler, Instruction};
use nom::{
branch::alt,
character::complete::{char, one_of, u8},
combinator::value,
bytes::complete::take_till1,
character::complete::{anychar, char, one_of, u8},
combinator::{map_res, value},
multi::many0,
sequence::{delimited, pair, preceded},
sequence::{delimited, pair, preceded, separated_pair},
Err, IResult, Parser,
};
use crate::bng::score::{Atom, FlatAtom, Modifier, QuickModifier};
use crate::bng::score::{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier};
pub(crate) trait Parse: Sized {
fn parse(input: &str) -> IResult<&str, Self>;
@ -21,5 +26,32 @@ fn atom_parser<'a>(notes: &'a str) -> impl Parser<&str, FlatAtom, nom::error::Er
preceded(char(Atom::MODIFIER), Modifier::parse).map(FlatAtom::Modifier),
QuickModifier::parse.map(FlatAtom::QuickModifier),
preceded(char(Atom::LOOP.0), u8).map(FlatAtom::LoopStarts),
value(FlatAtom::LoopEnds, char(Atom::LOOP.1)),
value(FlatAtom::TupleStarts, char(Atom::TUPLE.0)),
value(FlatAtom::TupleEnds, char(Atom::TUPLE.1)),
preceded(
char(Atom::SLOPE.0),
separated_pair(
SlopeModifier::parse,
char(' '),
map_res(take_till1(|c| c == ','), |s| {
let parser = fasteval::Parser::new();
let mut slab = fasteval::Slab::new();
Result::<Instruction, nom::error::Error<&str>>::Ok(
parser
.parse(s, &mut slab.ps)
.map_err(|_| nom::error::Error::new(s, nom::error::ErrorKind::Verify))?
.from(&slab.ps)
.compile(&slab.ps, &mut slab.cs),
)
}),
),
)
.map(|(sm, i)| FlatAtom::SlopeStarts(sm, i)),
value(FlatAtom::SlopeEnds, char(Atom::SLOPE.1)),
value(
FlatAtom::Comment,
delimited(char(Atom::COMMENT.0), anychar, char(Atom::COMMENT.1)),
),
))
}