quick modifier parser macro
This commit is contained in:
parent
f9841267ec
commit
2d5291c07b
4 changed files with 67 additions and 3 deletions
|
@ -15,6 +15,12 @@ pub fn slope_modifier_parser(input: TokenStream) -> TokenStream {
|
||||||
impl_slope_modifier_parser(ast)
|
impl_slope_modifier_parser(ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(QuickModifierParser)]
|
||||||
|
pub fn quick_modifier_parser(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
|
impl_quick_modifier_parser(ast)
|
||||||
|
}
|
||||||
|
|
||||||
fn impl_modifier_parser(ast: DeriveInput) -> TokenStream {
|
fn impl_modifier_parser(ast: DeriveInput) -> TokenStream {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
|
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
|
||||||
|
@ -77,3 +83,43 @@ fn impl_slope_modifier_parser(ast: DeriveInput) -> TokenStream {
|
||||||
panic!("this macro only works on enums")
|
panic!("this macro only works on enums")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn impl_quick_modifier_parser(ast: DeriveInput) -> TokenStream {
|
||||||
|
let name = &ast.ident;
|
||||||
|
if let Data::Enum(DataEnum { variants, .. }) = ast.data {
|
||||||
|
let match_arms = variants.iter().map(|variant| {
|
||||||
|
let variant_name = &variant.ident;
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
nom::combinator::map(
|
||||||
|
nom::branch::alt(
|
||||||
|
(
|
||||||
|
nom::combinator::value(
|
||||||
|
true,
|
||||||
|
nom::character::complete::char(#name::#variant_name(Default::default()).token()[0])
|
||||||
|
),
|
||||||
|
nom::combinator::value(
|
||||||
|
false,
|
||||||
|
nom::character::complete::char(#name::#variant_name(Default::default()).token()[1])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
#name::#variant_name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl lex::lexer::Parse for #name {
|
||||||
|
fn parse(input: &str) -> nom::IResult<&str, #name> {
|
||||||
|
nom::branch::alt((
|
||||||
|
#(#match_arms),*
|
||||||
|
))(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
panic!("this macro only works on enums")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use bng_macros::{ModifierParser, SlopeModifierParser};
|
use bng_macros::{ModifierParser, QuickModifierParser, SlopeModifierParser};
|
||||||
use fasteval::Instruction;
|
use fasteval::Instruction;
|
||||||
|
|
||||||
mod lex;
|
mod lex;
|
||||||
|
@ -22,6 +22,7 @@ pub(super) enum Modifier {
|
||||||
Tempo(u16),
|
Tempo(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(QuickModifierParser)]
|
||||||
pub(super) enum QuickModifier {
|
pub(super) enum QuickModifier {
|
||||||
Volume(bool),
|
Volume(bool),
|
||||||
Octave(bool),
|
Octave(bool),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{Atom, Modifier, SlopeModifier, WrapperKind};
|
use super::{Atom, Modifier, QuickModifier, SlopeModifier, WrapperKind};
|
||||||
|
|
||||||
pub(super) mod lexer;
|
pub(super) mod lexer;
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@ impl WrappingTokens {
|
||||||
const SQUARE_BRACKETS: (char, char) = ('[', ']');
|
const SQUARE_BRACKETS: (char, char) = ('[', ']');
|
||||||
const BRACKETS: (char, char) = ('{', '}');
|
const BRACKETS: (char, char) = ('{', '}');
|
||||||
const SEMICOLON_COMMA: (char, char) = (';', ',');
|
const SEMICOLON_COMMA: (char, char) = (';', ',');
|
||||||
|
const PLUS_MINUS: (char, char) = ('+', '-');
|
||||||
|
const RIGHT_LEFT: (char, char) = ('>', '<');
|
||||||
|
const SLASH_BACKSLASH: (char, char) = ('/', '\\');
|
||||||
|
const QUOTE_DEG: (char, char) = ('\'', '°');
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) trait Token<T> {
|
pub(super) trait Token<T> {
|
||||||
|
@ -30,6 +34,17 @@ impl Token<(char, char)> for WrapperKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 Token<char> for Modifier {
|
impl Token<char> for Modifier {
|
||||||
fn token(self) -> char {
|
fn token(self) -> char {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use nom::IResult;
|
use nom::{branch::alt, character::complete::char, combinator::value, IResult, Parser};
|
||||||
|
|
||||||
|
use crate::bng::score::QuickModifier;
|
||||||
|
|
||||||
pub(crate) trait Parse: Sized {
|
pub(crate) trait Parse: Sized {
|
||||||
fn parse(input: &str) -> IResult<&str, Self>;
|
fn parse(input: &str) -> IResult<&str, Self>;
|
||||||
|
|
Loading…
Reference in a new issue