Compare commits

...

3 commits

Author SHA1 Message Date
brevalferrari
df342893ee fix rustfmt 2025-06-07 17:38:00 +02:00
brevalferrari
5e38b15f93 more detail for language design 2025-06-07 17:37:33 +02:00
brevalferrari
e45053eebe blip as example for docs.rs example scraping 2025-06-07 17:37:15 +02:00
4 changed files with 48 additions and 17 deletions

View file

@ -47,3 +47,11 @@ raw = ["raw_audio"]
name = "blip"
path = "src/cli/main.rs"
required-features = ["bin"]
[[example]]
name = "blip"
path = "src/cli/main.rs"
required-features = ["bin"]
[lints.rust]
missing_docs = "warn"

View file

@ -1,8 +1,8 @@
notes: dorémi abc... as they appear in the note list
variables: $v8
variables: $v8 assign '8' to the variable named 'v'
$v1+2
$vv+1
$v-4.1 as soon as the variable mutation string stops being valid, usual sheet music parsing continues
$v-4.1 as soon as the variable mutation string stops being valid, usual sheet music parsing continues (https://en.wikipedia.org/wiki/Maximal_munch)
loops: (...)
(2...) to loop 2 times
(n...) to loop n times (taking the integer part with the floor function)

View file

@ -166,7 +166,7 @@ fn parse_and_compile(opts: &PlayOpts) -> anyhow::Result<Vec<f64>> {
compiler
.compile_all(tokens)
.inspect(|v| {
let is_nan = |sample| sample.abs().is_nan();
let is_nan = |sample: &f64| sample.abs().is_nan();
if v.iter().all(is_nan) {
error!("🎉 All your samples are NaN, you got yourself a \"Not a Song\" (NaS)!")
} else if v.iter().any(is_nan) {

View file

@ -10,10 +10,17 @@ use derive_new::new;
use fasteval::Evaler;
use log::{debug, trace, warn};
use nom::{
branch::alt, bytes::complete::{tag, take, take_till}, character::{
AsChar, Compare, Input, Parser as _,
branch::alt,
bytes::complete::{tag, take, take_till},
character::{
complete::{char, space1, usize},
streaming::one_of,
}, combinator::{all_consuming, cut, opt, value}, error::{ErrorKind, FromExternalError, ParseError}, multi::many0, sequence::{delimited, preceded}, AsChar, Compare, Input, Parser as _
},
combinator::{all_consuming, cut, opt, value},
error::{ErrorKind, FromExternalError, ParseError},
multi::many0,
sequence::{delimited, preceded},
};
use nom_locate::LocatedSpan;
@ -94,7 +101,10 @@ where
impl<I> FromExternalError<I, anyhow::Error> for LocatedVerboseError<I> {
fn from_external_error(input: I, _kind: ErrorKind, e: anyhow::Error) -> Self {
Self { location: input, error: Some(e) }
Self {
location: input,
error: Some(e),
}
}
}
@ -230,6 +240,7 @@ impl Note {
sorted
};
move |input: I| {
#[allow(clippy::type_complexity)]
let mut parsers: Vec<Box<dyn Fn(I) -> IResult<I, Self>>> = notes
.clone()
.drain(..)
@ -310,10 +321,10 @@ impl Loop {
.and(cut(take_till(|c| c == ')').and_then(cut(expect(all_consuming(token_parser(parser)), "input did not match any known grammar for inner tokens (typo?)"))))),
cut(
expect(
char(')'),
char(')'),
format!(
"the loop started at line {line} column {column} was not closed at this point",
line = input.location_line(),
line = input.location_line(),
column = input.get_utf8_column()
)
)
@ -340,12 +351,16 @@ impl Tuplet {
{
trace!("making the {} parser", type_name::<Self>());
|input| {
delimited(char('['), cut(take_till(|c| c == ']').and_then(cut(expect(all_consuming(token_parser(parser)), "input did not match any known grammar for inner tokens (typo?)")))), cut(
delimited(char('['),
cut(take_till(|c| c == ']')
.and_then(cut(expect(
all_consuming(token_parser(parser)),
"input did not match any known grammar for inner tokens (typo?)")))), cut(
expect(
char(']'),
char(']'),
format!(
"the tuplet started at line {line} column {column} was not closed at this point",
line = input.location_line(),
line = input.location_line(),
column = input.get_utf8_column()
)
)
@ -405,14 +420,20 @@ impl Slope {
-> IResult<LocatedSpan<&'a str>, VariableChange>,
>,
>>()
.as_mut_slice()), format!("expected a slope name from available slope names ({:?})", parser.slopes.clone().into_iter().map(|(s1, _)| s1.as_ref().to_string()).collect::<Vec<_>>())))
.and(cut(take_till(|c| c == '}').and_then(cut(expect(all_consuming(token_parser(parser)), "input did not match any known grammar for inner tokens (typo?)"))))),
.as_mut_slice()),
format!(
"expected a slope name from available slope names ({:?})",
parser.slopes.clone().into_iter().map(|(s1, _)| s1.as_ref().to_string()).collect::<Vec<_>>()
)))
.and(cut(take_till(|c| c == '}').and_then(cut(
expect(all_consuming(token_parser(parser)),
"input did not match any known grammar for inner tokens (typo?)"))))),
cut(
expect(
char('}'),
char('}'),
format!(
"the slope started at line {line} column {column} was not closed at this point",
line = input.location_line(),
line = input.location_line(),
column = input.get_utf8_column()
)
)
@ -520,14 +541,16 @@ mod tests {
VariableChange('n', "1".parse().unwrap())
}
fn parser_generator() -> Parser<
type DefaultParser = Parser<
[&'static str; 3],
&'static str,
HashMap<String, VariableChange>,
String,
VariableChange,
[char; 1],
> {
>;
fn parser_generator() -> DefaultParser {
Parser::new(
["do", "", "mi"],
HashMap::from([