mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 19:56:44 +01:00
46 lines
1.4 KiB
Rust
46 lines
1.4 KiB
Rust
use crate::*;
|
|
|
|
pub trait DslNs<'a, T: 'a>: DslNsWords<'a, T> + DslNsExprs<'a, T> {
|
|
/// Resolve an expression or symbol.
|
|
fn from (&'a self, dsl: impl Dsl + 'a) -> Perhaps<T> {
|
|
if let Ok(Some(literal)) = self.from_literal(&dsl) {
|
|
Ok(Some(literal))
|
|
} else if let Ok(Some(meaning)) = self.from_word(&dsl) {
|
|
Ok(Some(meaning))
|
|
} else {
|
|
self.from_expr(dsl)
|
|
}
|
|
}
|
|
/// Resolve as literal if valid.
|
|
fn from_literal (&self, _: impl Dsl) -> Perhaps<T> {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
#[macro_export] macro_rules! dsl_ns {
|
|
($State:ty: $Type:ty {
|
|
$(literal = |$dsl:ident| $literal:expr;)?
|
|
$(word = |$state_w:ident| {
|
|
$($word:literal => $body_w:expr),* $(,)?
|
|
};)?
|
|
$(expr = |$state_e:ident| {
|
|
$($head:literal $args:tt => $body_e:expr),* $(,)?
|
|
};)?
|
|
}) => {
|
|
impl<'a> DslNs<'a, $Type> for $State {
|
|
$(fn from_literal (&self, $dsl: impl Dsl) -> Perhaps<$Type> {
|
|
$literal
|
|
})?
|
|
}
|
|
impl<'a> DslNsWords<'a, $Type> for $State {
|
|
$(dsl_words! { 'a |$state_w| -> $Type {
|
|
$($word => $body_w),*
|
|
} })?
|
|
}
|
|
impl<'a> DslNsExprs<'a, $Type> for $State {
|
|
$(dsl_exprs! { 'a |$state_e| -> $Type {
|
|
$($head $args => $body_e),*
|
|
} })?
|
|
}
|
|
}
|
|
}
|