replace Token trait with consts

This commit is contained in:
Ponj 2024-10-12 16:27:27 -04:00
parent 040bb4ecb3
commit 9e0ead7605
Signed by: p6nj
GPG key ID: 6FED68D87C479A59
3 changed files with 60 additions and 60 deletions

View file

@ -1,7 +1,8 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
use syn::{parse_macro_input, Data, DataEnum, DeriveInput, Fields};
use syn::{parse_macro_input, Data, DataEnum, DeriveInput, Fields, Ident};
#[proc_macro_derive(ModifierParser)]
pub fn modifier_parser(input: TokenStream) -> TokenStream {
@ -31,11 +32,12 @@ fn impl_modifier_parser(ast: DeriveInput) -> TokenStream {
} else {
panic!("Expected unnamed fields in enum variants");
};
let const_name =
Ident::new(&variant.ident.to_string().to_uppercase(), Span::call_site());
quote! {
nom::combinator::map(
nom::sequence::preceded(
nom::character::complete::char(#name::#variant_name(Default::default()).token()),
nom::character::complete::char(#name::#const_name),
nom::character::complete::#variant_type
),
#name::#variant_name
@ -63,15 +65,15 @@ fn impl_slope_modifier_parser(ast: DeriveInput) -> TokenStream {
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
let match_arms = variants.iter().map(|variant| {
let variant_name = &variant.ident;
let const_name = Ident::new(&variant.ident.to_string().to_uppercase(),Span::call_site());
quote! {
tag(#name::#variant_name)
nom::combinator::value(#name::#variant_name, nom::character::complete::char(SlopeModifier::#const_name))
}
});
quote! {
impl lex::lexer::Parse for #name {
fn parse(input: &str) -> nom::IResult<&str, #name> {
let tag = |sm: SlopeModifier| nom::combinator::value(sm, nom::character::complete::char(sm.token()));
nom::branch::alt((
#(#match_arms),*
))(input)
@ -89,18 +91,19 @@ fn impl_quick_modifier_parser(ast: DeriveInput) -> TokenStream {
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
let match_arms = variants.iter().map(|variant| {
let variant_name = &variant.ident;
let const_name =
Ident::new(&variant.ident.to_string().to_uppercase(), Span::call_site());
quote! {
nom::combinator::map(
nom::branch::alt(
(
nom::combinator::value(
true,
nom::character::complete::char(#name::#variant_name(Default::default()).token().0)
lex::MORE,
nom::character::complete::char(#name::#const_name.0)
),
nom::combinator::value(
false,
nom::character::complete::char(#name::#variant_name(Default::default()).token().1)
lex::LESS,
nom::character::complete::char(#name::#const_name.1)
)
)
),

View file

@ -1,11 +1,11 @@
use super::{Atom, Modifier, QuickModifier, SlopeModifier};
use super::{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier};
pub(super) mod lexer;
const MORE: bool = true;
const LESS: bool = false;
const ON: bool = true;
const OFF: bool = false;
pub(super) const MORE: bool = true;
pub(super) const LESS: bool = false;
pub(super) const ON: bool = true;
pub(super) const OFF: bool = false;
struct WrappingTokens;
impl WrappingTokens {
@ -19,51 +19,34 @@ impl WrappingTokens {
const QUOTE_DEG: (char, char) = ('\'', '°');
}
pub(super) trait Token<T> {
fn token(self) -> T;
impl QuickModifier {
pub(super) const VOLUME: (char, char) = WrappingTokens::PLUS_MINUS;
pub(super) const OCTAVE: (char, char) = WrappingTokens::RIGHT_LEFT;
pub(super) const LENGTH: (char, char) = WrappingTokens::SLASH_BACKSLASH;
pub(super) const PIZZ: (char, char) = WrappingTokens::QUOTE_DEG;
}
impl Token<(char, char)> for QuickModifier {
fn token(self) -> (char, char) {
match self {
Self::Volume(_) => WrappingTokens::PLUS_MINUS,
Self::Octave(_) => WrappingTokens::RIGHT_LEFT,
Self::Length(_) => WrappingTokens::SLASH_BACKSLASH,
Self::Pizz(_) => WrappingTokens::QUOTE_DEG,
}
}
impl Modifier {
pub(super) const VOLUME: char = 'v';
pub(super) const OCTAVE: char = 'o';
pub(super) const LENGTH: char = 'l';
pub(super) const TEMPO: char = 't';
}
impl Token<char> for Modifier {
fn token(self) -> char {
match self {
Self::Volume(_) => 'v',
Self::Octave(_) => 'o',
Self::Length(_) => 'l',
Self::Tempo(_) => 't',
}
}
impl SlopeModifier {
pub(super) const NOTE: char = 'n';
pub(super) const VOLUME: char = 'v';
pub(super) const OCTAVE: char = 'o';
pub(super) const LENGTH: char = 'l';
pub(super) const TEMPO: char = 't';
}
impl Token<char> for SlopeModifier {
fn token(self) -> char {
match self {
Self::Note => 'n',
Self::Volume => 'v',
Self::Octave => 'o',
Self::Length => 'l',
Self::Tempo => 't',
}
}
}
impl Token<char> for Atom {
fn token(self) -> char {
match self {
Atom::Rest => '.',
Atom::StartHere => ':',
Atom::Modifier(_) => '!',
_ => unimplemented!("not a singleton"),
}
}
impl Atom {
pub(super) const REST: char = '.';
pub(super) const START_HERE: char = ':';
pub(super) const MODIFIER: char = '!';
pub(super) const LOOP: (char, char) = WrappingTokens::PARENTHESES;
pub(super) const TUPLE: (char, char) = WrappingTokens::SQUARE_BRACKETS;
pub(super) const SLOPE: (char, char) = WrappingTokens::BRACKETS;
pub(super) const COMMENT: (char, char) = WrappingTokens::SEMICOLON_COMMA;
}

View file

@ -1,11 +1,25 @@
use nom::{
branch::alt, character::complete::char, combinator::value, sequence::delimited, IResult, Parser,
branch::alt,
character::complete::{char, one_of, u8},
combinator::value,
multi::many0,
sequence::{delimited, pair, preceded},
Err, IResult, Parser,
};
use crate::bng::score::QuickModifier;
use super::Token;
use crate::bng::score::{Atom, FlatAtom, Modifier, QuickModifier};
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>> {
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),
))
}