mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 11:46:42 +01:00
parent
ca4c558eab
commit
e72225f83c
11 changed files with 421 additions and 574 deletions
178
dsl/src/dsl.rs
178
dsl/src/dsl.rs
|
|
@ -1,178 +0,0 @@
|
|||
use crate::*;
|
||||
use std::error::Error;
|
||||
|
||||
/// Standard result type for DSL-specific operations.
|
||||
pub type DslResult<T> = Result<T, DslErr>;
|
||||
|
||||
/// DSL-specific error codes.
|
||||
#[derive(Error, Debug, Copy, Clone, PartialEq)] pub enum DslErr {
|
||||
#[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),
|
||||
}
|
||||
|
||||
/// Enumeration of possible DSL tokens.
|
||||
/// Generic over string and expression storage.
|
||||
///
|
||||
/// * [ ] FIXME: Value may be [Err] which may shadow [Result::Err]
|
||||
/// * [DslVal::Exp] wraps an expression depth and a [CstIter]
|
||||
/// with the remaining part of the expression.
|
||||
/// * expression depth other that 0 mean unclosed parenthesis.
|
||||
/// * closing and unopened parenthesis panics during reading.
|
||||
/// * [ ] TODO: signed depth might be interesting
|
||||
/// * [DslVal::Sym] and [DslVal::Key] are stringish literals
|
||||
/// with slightly different parsing rules.
|
||||
/// * [DslVal::Num] is an unsigned integer literal.
|
||||
#[derive(Clone, Debug, PartialEq, Default)]
|
||||
pub enum DslVal<Str, Exp> {
|
||||
#[default]
|
||||
Nil,
|
||||
Err(DslErr),
|
||||
Num(usize),
|
||||
Sym(Str),
|
||||
Key(Str),
|
||||
Str(Str),
|
||||
Exp(usize, Exp),
|
||||
}
|
||||
|
||||
pub fn dsl_val <A: Into<X>, B: Into<Y>, X, Y> (val: DslVal<A, B>) -> DslVal<X, Y> {
|
||||
use DslVal::*;
|
||||
match val {
|
||||
Nil => Nil,
|
||||
Err(e) => Err(e),
|
||||
Num(u) => Num(u),
|
||||
Sym(s) => Sym(s.into()),
|
||||
Key(s) => Key(s.into()),
|
||||
Str(s) => Str(s.into()),
|
||||
Exp(d, x) => Exp(d, x.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Dsl: Debug {
|
||||
type Str: PartialEq + Clone + Default + Debug + AsRef<str>;
|
||||
type Exp: PartialEq + Clone + Default + Debug + Dsl;
|
||||
fn nth (&self, index: usize) -> Option<DslVal<Self::Str, Self::Exp>>;
|
||||
fn val (&self) -> DslVal<Self::Str, Self::Exp> {
|
||||
self.nth(0).unwrap_or(DslVal::Nil)
|
||||
}
|
||||
// exp-only nth here?
|
||||
}
|
||||
|
||||
impl<
|
||||
Str: PartialEq + Clone + Default + Debug + AsRef<str>,
|
||||
Exp: PartialEq + Clone + Default + Debug + Dsl,
|
||||
> Dsl for DslVal<Str, Exp> {
|
||||
type Str = Str;
|
||||
type Exp = Exp;
|
||||
fn val (&self) -> DslVal<Str, Exp> {
|
||||
self.clone()
|
||||
}
|
||||
fn nth (&self, _index: usize) -> Option<DslVal<Str, Exp>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// May construct self from state and DSL.
|
||||
pub trait DslFrom<State>: Sized {
|
||||
fn try_dsl_from (state: &State, value: &impl Dsl) -> Perhaps<Self>;
|
||||
fn dsl_from (
|
||||
state: &State, value: &impl Dsl, error: impl Fn()->Box<dyn Error>
|
||||
) -> Usually<Self> {
|
||||
match Self::try_dsl_from(state, value)? {
|
||||
Some(value) => Ok(value),
|
||||
_ => Err(error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// May construct another from self and DSL.
|
||||
pub trait DslInto<Item> {
|
||||
fn try_dsl_into (&self, dsl: &impl Dsl) -> Perhaps<Item>;
|
||||
fn dsl_into (
|
||||
&self, value: &impl Dsl, error: impl Fn()->Box<dyn Error>
|
||||
) -> Usually<Item> {
|
||||
match Self::try_dsl_into(self, value)? {
|
||||
Some(value) => Ok(value),
|
||||
_ => Err(error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Str, Exp> DslVal<Str, Exp> {
|
||||
pub fn is_nil (&self) -> bool {
|
||||
matches!(self, Self::Nil)
|
||||
}
|
||||
pub fn as_err (&self) -> Option<&DslErr> {
|
||||
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_exp (&self) -> Option<&Exp> {
|
||||
if let Self::Exp(_, x) = self { Some(x) } else { 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: Copy, Exp: Copy> Copy for DslVal<Str, Exp> {}
|
||||
|
||||
impl<Str: AsRef<str>, Exp> DslVal<Str, Exp> {
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! from_str {
|
||||
($Struct:ty |$source:ident| $expr:expr) => {
|
||||
impl<'s> From<&'s str> for $Struct {
|
||||
fn from ($source: &'s str) -> Self {
|
||||
$expr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
from_str!(Ast|source|Self::from(CstIter::from(source)));
|
||||
from_str!(Cst<'s>|source|Self(CstIter(CstConstIter(source))));
|
||||
from_str!(CstIter<'s>|source|Self(CstConstIter(source)));
|
||||
from_str!(CstConstIter<'s>|source|Self::new(source));
|
||||
Loading…
Add table
Add a link
Reference in a new issue