tengri/dsl/src/dsl_ns.rs

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),*
} })?
}
}
}