dsl: simplify trait further

This commit is contained in:
🪞👃🪞 2025-09-03 00:40:50 +03:00
parent ad2d7c38b1
commit c57117df9c
9 changed files with 395 additions and 312 deletions

70
dsl/src/dsl_expr.rs Normal file
View file

@ -0,0 +1,70 @@
use crate::*;
pub type GetDslExpr<'a, S, T> = for<'b> fn(&'a S, &'b str)->Perhaps<T>;
pub type DslExprs<'a, S, T> = &'a [(&'a str, GetDslExpr<'a, S, T>)];
dsl_type!(DslExpr {
fn expr (&self) -> DslPerhaps<&str> {ok_flat(self.src()?.map(expr_peek_inner_only))}
fn head (&self) -> DslPerhaps<&str> {ok_flat(self.src()?.map(peek))}
fn tail (&self) -> DslPerhaps<&str> {ok_flat(self.src()?.map(peek_tail))}
/// my other car is a cdr :<
fn each (&self, mut cb: impl FnMut(&str)->Usually<()>) -> Usually<()> {
Ok(if let Some(head) = self.head()? {
cb(head)?;
if let Some(tail) = self.tail()? {
tail.each(cb)?;
}
})
}
} {
pub const fn expr_peek [generated];
pub const fn expr_peek_only [generated];
pub const fn expr_seek [generated];
pub const fn expr_seek_start (src) {
for_each!((i, c) in char_indices(src) =>
if is_expr_start(c) { return Ok(Some(i)) } else
if !is_space(c) { return Err(Unexpected(c, Some(i), Some("expected expression start"))) });
Ok(None)
}
pub const fn expr_seek_length (src) {
let mut depth = 0;
for_each!((i, c) in char_indices(src) =>
if is_expr_start(c) { depth += 1; } else
if is_expr_end(c) {
if depth == 0 {
return Err(Unexpected(c, Some(i), Some("expected expression end")))
} else if depth == 1 {
return Ok(Some(i + 1))
} else {
depth -= 1;
}
});
Err(Incomplete)
}
});
#[macro_export] macro_rules!dsl_exprs(($l:lifetime |$state:ident|->$Type:ty$({
$($name:literal ($($arg:ident:$ty:ty),* $(,)?) => $body:expr),* $(,)?
})?)=>{
const EXPRS: DslExprs<$l, Self, $Type> = &[$( $({
let get: GetDslExpr<$l, Self, $Type> = |$state: &$l Self, tail_base|{
let tail = tail_base;
$(
let head = tail.head()?.unwrap_or_default();
let tail = tail.tail()?.unwrap_or_default();
let $arg: $ty = if let Some(arg) = $state.from(&head)? {
arg
} else {
return Err(format!("{}: arg \"{}\" ({}) got: {head} {tail}",
$name,
stringify!($arg),
stringify!($ty),
).into())
};
)*
Ok(Some($body as $Type))
};
($name, get)
}),* )? ];
});