mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 11:46:42 +01:00
parent
c8827b43c3
commit
91dc77cfea
16 changed files with 931 additions and 823 deletions
110
dsl/src/dsl.rs
Normal file
110
dsl/src/dsl.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
use crate::*;
|
||||
|
||||
#[derive(Error, Debug, Copy, Clone, PartialEq)] 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),
|
||||
}
|
||||
|
||||
/// Thing that may construct itself from `State` and [DslValue].
|
||||
pub trait FromDsl<State>: Sized {
|
||||
fn try_provide (
|
||||
state: &State,
|
||||
value: DslValue<impl DslStr, impl DslExp>
|
||||
) -> Perhaps<Self>;
|
||||
fn provide (
|
||||
state: &State,
|
||||
value: DslValue<impl DslStr, impl DslExp>,
|
||||
error: impl Fn()->Box<dyn std::error::Error>
|
||||
) -> Usually<Self> {
|
||||
match Self::try_provide(state, value)? {
|
||||
Some(value) => Ok(value),
|
||||
_ => Err(error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type DslResult<T> = Result<T, DslError>;
|
||||
|
||||
/// Marker trait for supported string types.
|
||||
pub trait DslStr: PartialEq + Clone + Default + Debug + AsRef<str> {}
|
||||
impl<T: PartialEq + Clone + Default + Debug + AsRef<str>> DslStr for T {}
|
||||
|
||||
/// Marker trait for supported expression types.
|
||||
pub trait DslExp: PartialEq + Clone + Default + Debug {}
|
||||
impl<T: PartialEq + Clone + Default + Debug> DslExp for T {}
|
||||
|
||||
/// A DSL value generic over string and expression types.
|
||||
/// See [CstValue] and [AstValue].
|
||||
#[derive(Clone, Debug, PartialEq, Default)]
|
||||
pub enum DslValue<Str: DslStr, Exp: DslExp> {
|
||||
#[default]
|
||||
Nil,
|
||||
Err(DslError),
|
||||
Num(usize),
|
||||
Sym(Str),
|
||||
Key(Str),
|
||||
Str(Str),
|
||||
Exp(usize, Exp),
|
||||
}
|
||||
|
||||
impl<Str: DslStr, Exp: DslExp> DslValue<Str, Exp> {
|
||||
pub fn is_nil (&self) -> bool {
|
||||
matches!(self, Self::Nil)
|
||||
}
|
||||
pub fn as_err (&self) -> Option<&DslError> {
|
||||
if let Self::Err(e) = self { Some(e) } else { None }
|
||||
}
|
||||
pub fn as_num (&self) -> Option<usize> {
|
||||
if let Self::Num(n) = self { Some(*n) } else { None }
|
||||
}
|
||||
pub fn as_sym (&self) -> Option<&str> {
|
||||
if let Self::Sym(s) = self { Some(s.as_ref()) } else { None }
|
||||
}
|
||||
pub fn as_key (&self) -> Option<&str> {
|
||||
if let Self::Key(k) = self { Some(k.as_ref()) } else { None }
|
||||
}
|
||||
pub fn as_str (&self) -> Option<&str> {
|
||||
if let Self::Str(s) = self { Some(s.as_ref()) } else { None }
|
||||
}
|
||||
pub fn as_exp (&self) -> Option<&Exp> {
|
||||
if let Self::Exp(_, x) = self { Some(x) } else { None }
|
||||
}
|
||||
pub fn exp_match <T, F> (&self, namespace: &str, cb: F) -> Perhaps<T>
|
||||
where F: Fn(&str, &Exp)-> Perhaps<T> {
|
||||
if let Some(Self::Key(key)) = self.exp_head()
|
||||
&& key.as_ref().starts_with(namespace)
|
||||
&& let Some(tail) = self.exp_tail() {
|
||||
cb(key.as_ref().split_at(namespace.len()).1, tail)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
pub fn exp_depth (&self) -> Option<usize> {
|
||||
todo!()
|
||||
}
|
||||
pub fn exp_head (&self) -> Option<&Self> {
|
||||
todo!()
|
||||
} // TODO
|
||||
pub fn exp_tail (&self) -> Option<&Exp> {
|
||||
todo!()
|
||||
} // TODO
|
||||
pub fn peek (&self) -> Option<Self> {
|
||||
todo!()
|
||||
}
|
||||
pub fn next (&mut self) -> Option<Self> {
|
||||
todo!()
|
||||
}
|
||||
pub fn rest (self) -> Vec<Self> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Str: DslStr + Copy, Exp: DslExp + Copy> Copy for DslValue<Str, Exp> {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue