Compare commits
2 commits
7460a14bc1
...
f5448e0e78
Author | SHA1 | Date | |
---|---|---|---|
|
f5448e0e78 | ||
|
b03b0ef5ee |
3 changed files with 19 additions and 12 deletions
|
@ -37,6 +37,8 @@ const DEFAULT_LENGTH: &str = "2^(2-log(2, l))*(60/T)";
|
||||||
pub(super) enum Cli {
|
pub(super) enum Cli {
|
||||||
/// Play a song
|
/// Play a song
|
||||||
Play(PlayOpts),
|
Play(PlayOpts),
|
||||||
|
/// Check for typos
|
||||||
|
Check(PlayOpts),
|
||||||
/// Export a song to an audio file or stdout
|
/// Export a song to an audio file or stdout
|
||||||
Export(ExportOpts),
|
Export(ExportOpts),
|
||||||
/// Memo menu for examples and general help about syntax and supported audio formats
|
/// Memo menu for examples and general help about syntax and supported audio formats
|
||||||
|
|
|
@ -26,6 +26,9 @@ fn main() -> anyhow::Result<()> {
|
||||||
debug!("options: {cli:#?}");
|
debug!("options: {cli:#?}");
|
||||||
use Cli::*;
|
use Cli::*;
|
||||||
match cli {
|
match cli {
|
||||||
|
Check(opts) => {
|
||||||
|
parse_and_compile(&opts)?;
|
||||||
|
}
|
||||||
Play(opts) => {
|
Play(opts) => {
|
||||||
let (_stream, stream_handle) = OutputStream::try_default()
|
let (_stream, stream_handle) = OutputStream::try_default()
|
||||||
.context("Failed to find (or use) default audio device")?;
|
.context("Failed to find (or use) default audio device")?;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use nom::{
|
||||||
complete::{char, space1, usize},
|
complete::{char, space1, usize},
|
||||||
streaming::one_of,
|
streaming::one_of,
|
||||||
},
|
},
|
||||||
combinator::{all_consuming, opt, value},
|
combinator::{all_consuming, cut, opt, value},
|
||||||
error::{Error, ParseError},
|
error::{Error, ParseError},
|
||||||
multi::many0,
|
multi::many0,
|
||||||
sequence::{delimited, preceded},
|
sequence::{delimited, preceded},
|
||||||
|
@ -53,7 +53,7 @@ where
|
||||||
input: &'a str,
|
input: &'a str,
|
||||||
) -> Result<TokenVec, Error<nom_locate::LocatedSpan<&'a str>>> {
|
) -> Result<TokenVec, Error<nom_locate::LocatedSpan<&'a str>>> {
|
||||||
debug!("parsing input \"{input}\"");
|
debug!("parsing input \"{input}\"");
|
||||||
token_parser(self)
|
all_consuming(token_parser(self))
|
||||||
.parse_complete(LocatedSpan::new(input))
|
.parse_complete(LocatedSpan::new(input))
|
||||||
.finish()
|
.finish()
|
||||||
.map(|(_, o)| o)
|
.map(|(_, o)| o)
|
||||||
|
@ -81,7 +81,7 @@ where
|
||||||
many0(value((), char('#').and(take_till(|c| c == '\n'))).or(value((), space1))),
|
many0(value((), char('#').and(take_till(|c| c == '\n'))).or(value((), space1))),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
all_consuming(many0(delimited(
|
many0(delimited(
|
||||||
space_or_comment(),
|
space_or_comment(),
|
||||||
alt((
|
alt((
|
||||||
Silence::parser().map(into_box),
|
Silence::parser().map(into_box),
|
||||||
|
@ -93,7 +93,7 @@ where
|
||||||
Slope::parser(parser).map(into_box),
|
Slope::parser(parser).map(into_box),
|
||||||
)),
|
)),
|
||||||
space_or_comment(),
|
space_or_comment(),
|
||||||
)))
|
))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,10 +171,12 @@ impl VariableChange {
|
||||||
move |i: I| {
|
move |i: I| {
|
||||||
preceded(
|
preceded(
|
||||||
char('$'),
|
char('$'),
|
||||||
one_of(variables.as_ref().iter().collect::<String>().as_str()),
|
cut(
|
||||||
|
one_of(variables.as_ref().iter().collect::<String>().as_str())
|
||||||
|
.and(expression_parser(variables.as_ref()))
|
||||||
|
.map(|(name, change)| VariableChange(name, change)),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.and(expression_parser(variables.as_ref()))
|
|
||||||
.map(|(name, change)| VariableChange(name, change))
|
|
||||||
.parse(i)
|
.parse(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +214,7 @@ impl Loop {
|
||||||
.map(LoopCount::Variable),
|
.map(LoopCount::Variable),
|
||||||
)))
|
)))
|
||||||
.and(token_parser(parser)),
|
.and(token_parser(parser)),
|
||||||
char(')'),
|
cut(char(')')),
|
||||||
)
|
)
|
||||||
.map(|(c, v)| Self(c.unwrap_or_default(), v))
|
.map(|(c, v)| Self(c.unwrap_or_default(), v))
|
||||||
.parse(input)
|
.parse(input)
|
||||||
|
@ -237,7 +239,7 @@ impl Tuplet {
|
||||||
{
|
{
|
||||||
trace!("making the {} parser", type_name::<Self>());
|
trace!("making the {} parser", type_name::<Self>());
|
||||||
|input| {
|
|input| {
|
||||||
delimited(char('['), token_parser(parser), char(']'))
|
delimited(char('['), token_parser(parser), cut(char(']')))
|
||||||
.map(Self)
|
.map(Self)
|
||||||
.parse(input)
|
.parse(input)
|
||||||
}
|
}
|
||||||
|
@ -277,15 +279,15 @@ impl Slope {
|
||||||
let iter: std::vec::IntoIter<(String, VariableChange)> = slopes.into_iter();
|
let iter: std::vec::IntoIter<(String, VariableChange)> = slopes.into_iter();
|
||||||
delimited(
|
delimited(
|
||||||
char('{'),
|
char('{'),
|
||||||
alt(iter
|
cut(alt(iter
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
Box::new(move |input: I| value(v.clone(), tag(k.as_str())).parse(input))
|
Box::new(move |input: I| value(v.clone(), tag(k.as_str())).parse(input))
|
||||||
as Box<dyn Fn(I) -> IResult<I, VariableChange>>
|
as Box<dyn Fn(I) -> IResult<I, VariableChange>>
|
||||||
})
|
})
|
||||||
.collect::<Vec<Box<dyn Fn(I) -> IResult<I, VariableChange>>>>()
|
.collect::<Vec<Box<dyn Fn(I) -> IResult<I, VariableChange>>>>()
|
||||||
.as_mut_slice())
|
.as_mut_slice()))
|
||||||
.and(token_parser(parser)),
|
.and(token_parser(parser)),
|
||||||
char('}'),
|
cut(char('}')),
|
||||||
)
|
)
|
||||||
.map(|(i, v)| Self::new(i, v))
|
.map(|(i, v)| Self::new(i, v))
|
||||||
.parse(input)
|
.parse(input)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue