//#![feature(adt_const_params)] //#![feature(type_alias_impl_trait)] #![feature(if_let_guard)] #![feature(impl_trait_in_fn_trait_return)] #![feature(const_precise_live_drops)] extern crate const_panic; use const_panic::PanicFmt; use std::fmt::Debug; pub(crate) use std::error::Error; pub(crate) use std::sync::Arc; pub(crate) use konst::iter::for_each; pub(crate) use konst::string::{str_from, str_range, char_indices}; pub(crate) use thiserror::Error; pub(crate) use ::tengri_core::*; pub(crate) use self::DslError::*; mod dsl_conv; pub use self::dsl_conv::*; mod dsl_parse; pub(crate) use self::dsl_parse::*; pub mod parse { pub use crate::dsl_parse::*; } #[cfg(test)] mod dsl_test; flex_trait!(Dsl: Debug + Send + Sync + Sized { fn src (&self) -> DslPerhaps<&str> { unreachable!("Dsl::src default impl") } }); impl Dsl for Arc { fn src (&self) -> DslPerhaps<&str> { Ok(Some(self.as_ref())) } } impl<'s> Dsl for &'s str { fn src (&self) -> DslPerhaps<&str> { Ok(Some(self.as_ref())) } } impl Dsl for Option { fn src (&self) -> DslPerhaps<&str> { Ok(if let Some(dsl) = self { dsl.src()? } else { None }) } } impl Dsl for Result { fn src (&self) -> DslPerhaps<&str> { match self { Ok(dsl) => Ok(dsl.src()?), Err(e) => Err(*e) } } } impl DslExp for D {} pub trait DslExp: Dsl { fn exp (&self) -> DslPerhaps<&str> { ok_flat(self.src()?.map(exp_peek_inner)) } fn head (&self) -> DslPerhaps<&str> { ok_flat(self.src()?.map(peek)) } fn tail (&self) -> DslPerhaps<&str> { ok_flat(self.src()?.map(peek_tail(self.head()))) } } impl DslSym for D {} pub trait DslSym: Dsl { fn sym (&self) -> DslPerhaps<&str> { ok_flat(self.src()?.map(sym_peek_only)) } } impl DslKey for D {} pub trait DslKey: Dsl { fn key (&self) -> DslPerhaps<&str> { ok_flat(self.src()?.map(key_peek_only)) } } impl DslText for D {} pub trait DslText: Dsl { fn text (&self) -> DslPerhaps<&str> { ok_flat(self.src()?.map(text_peek_only)) } } impl DslNum for D {} pub trait DslNum: Dsl { fn num (&self) -> DslPerhaps<&str> { ok_flat(self.src()?.map(num_peek_only)) } } /// DSL-specific result type. pub type DslResult = Result; /// DSL-specific optional result type. pub type DslPerhaps = Result, DslError>; /// DSL-specific error codes. #[derive(Error, Debug, Copy, Clone, PartialEq, PanicFmt)] pub enum DslError { #[error("parse failed: not implemented")] Unimplemented, #[error("parse failed: empty")] Empty, #[error("parse failed: incomplete")] Incomplete, #[error("parse failed: unexpected character '{0}'")] Unexpected(char), #[error("parse failed: error #{0}")] Code(u8), #[error("end reached")] End } #[macro_export] macro_rules! dsl_for_each (($dsl:expr => |$next:ident|$body:expr)=>{ let mut dsl: Arc = $dsl.src().into(); let mut $next: Option> = dsl.next()?.map(Into::into); let mut rest: Option> = dsl.rest()?.map(Into::into); loop { if let Some($next) = $next { $body; } else { break } if let Some(next) = rest { $next = next.next()?.map(Into::into); rest = next.rest()?.map(Into::into); } else { break } } }); fn ok_flat (x: Option>) -> DslPerhaps { Ok(x.transpose()?.flatten()) } fn peek_tail <'a> (head: DslPerhaps<&'a str>) -> impl Fn(&'a str)->DslPerhaps<&'a str> { move|src|match head { Ok(Some(next)) => { let src = &src[src.len().min(1 + next.len())..]; for c in src.chars() { if !is_whitespace(c) { return Ok(Some(src)) } } Ok(None) }, e => e } }