From 9c910b80764e9450c026de14455a0fc926d8c7b4 Mon Sep 17 00:00:00 2001 From: p6nj Date: Sat, 9 Nov 2024 18:58:28 -0500 Subject: [PATCH] divide atom parser into sub-parsers with context --- src/bng/score/lex/lexer.rs | 205 +++++++++++++++++++++++++++++-------- 1 file changed, 160 insertions(+), 45 deletions(-) diff --git a/src/bng/score/lex/lexer.rs b/src/bng/score/lex/lexer.rs index ab0a316..45bf7ad 100644 --- a/src/bng/score/lex/lexer.rs +++ b/src/bng/score/lex/lexer.rs @@ -16,8 +16,6 @@ use nom::{ Err, IResult, Parser, }; -use crate::bng::score::{modifier, quick_modifier, slope_modifier}; - use super::{ super::super::Expression as Instruction, Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier, }; @@ -45,6 +43,154 @@ where ))(i) } +fn note<'a, E>(notes: &'a str) -> impl Parser<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str> + FromExternalError<&'a str, TryFromIntError>, +{ + context( + "note", + map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from).map(FlatAtom::Note), + ) +} + +fn rest<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + context("rest", value(FlatAtom::Rest, char(Atom::REST)))(i) +} + +fn start_here<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + context( + "start_here", + value(FlatAtom::StartHere, char(Atom::START_HERE)), + )(i) +} + +fn modifier<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + use super::super::modifier; + context( + "modifier", + preceded(char(Atom::MODIFIER), modifier).map(FlatAtom::Modifier), + )(i) +} + +fn quick_modifier<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + use super::super::quick_modifier; + context( + "quick_modifier", + quick_modifier.map(FlatAtom::QuickModifier), + )(i) +} + +fn loop_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + context( + "loop_starts", + preceded( + char(Atom::LOOP.0), + map_opt(opt(u8), |n| { + if let Some(n) = n { + NonZeroU8::new(n) + } else { + unsafe { Some(NonZeroU8::new_unchecked(2)) } + } + }), + ) + .map(FlatAtom::LoopStarts), + )(i) +} + +fn loop_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + context("loop_ends", value(FlatAtom::LoopEnds, char(Atom::LOOP.1)))(i) +} + +fn tuple_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + context( + "tuple_starts", + value(FlatAtom::TupleStarts, char(Atom::TUPLE.0)), + )(i) +} + +fn tuple_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + context( + "tuple_ends", + value(FlatAtom::TupleEnds, char(Atom::TUPLE.1)), + )(i) +} + +fn slope_starts<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str> + FromExternalError<&'a str, E>, +{ + use super::super::slope_modifier; + context( + "slope_starts", + terminated( + preceded( + char(Atom::SLOPE.0), + separated_pair( + slope_modifier, + char(' '), + map_res(take_till1(|c| c == ','), |s: &str| { + s.parse() + .map_err(|_| E::from_error_kind(s, ErrorKind::Verify)) + }), + ), + ), + char(','), + ) + .map(|(sm, i)| FlatAtom::SlopeStarts(sm, i)), + )(i) +} + +fn slope_ends<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + context( + "slope_ends", + value(FlatAtom::SlopeEnds, char(Atom::SLOPE.1)), + )(i) +} + +fn comment<'a, E>(i: &'a str) -> IResult<&'a str, FlatAtom, E> +where + E: ParseError<&'a str> + ContextError<&'a str>, +{ + context( + "comment", + value( + FlatAtom::Comment, + delimited( + char(Atom::COMMENT.0), + take_till(|c| c == Atom::COMMENT.1), + char(Atom::COMMENT.1), + ), + ), + )(i) +} + fn atom<'a, E>(notes: &'a str) -> impl Parser<&'a str, FlatAtom, E> where E: ParseError<&'a str> @@ -55,49 +201,18 @@ where context( "atom", alt(( - map_res(map_opt(one_of(notes), |c| notes.find(c)), u8::try_from).map(FlatAtom::Note), - value(FlatAtom::Rest, char(Atom::REST)), - value(FlatAtom::StartHere, char(Atom::START_HERE)), - preceded(char(Atom::MODIFIER), modifier).map(FlatAtom::Modifier), - quick_modifier.map(FlatAtom::QuickModifier), - preceded( - char(Atom::LOOP.0), - map_opt(opt(u8), |n| { - if let Some(n) = n { - NonZeroU8::new(n) - } else { - unsafe { Some(NonZeroU8::new_unchecked(2)) } - } - }), - ) - .map(FlatAtom::LoopStarts), - value(FlatAtom::LoopEnds, char(Atom::LOOP.1)), - value(FlatAtom::TupleStarts, char(Atom::TUPLE.0)), - value(FlatAtom::TupleEnds, char(Atom::TUPLE.1)), - terminated( - preceded( - char(Atom::SLOPE.0), - separated_pair( - slope_modifier, - char(' '), - map_res(take_till1(|c| c == ','), |s: &str| { - s.parse() - .map_err(|_| E::from_error_kind(s, ErrorKind::Verify)) - }), - ), - ), - char(','), - ) - .map(|(sm, i)| FlatAtom::SlopeStarts(sm, i)), - value(FlatAtom::SlopeEnds, char(Atom::SLOPE.1)), - value( - FlatAtom::Comment, - delimited( - char(Atom::COMMENT.0), - take_till(|c| c == Atom::COMMENT.1), - char(Atom::COMMENT.1), - ), - ), + note(notes), + rest, + start_here, + modifier, + quick_modifier, + loop_starts, + loop_ends, + tuple_starts, + tuple_ends, + slope_starts, + slope_ends, + comment, )), ) }