extact dsl_token; flip Dsl; try to obviate ViewContext

This commit is contained in:
🪞👃🪞 2025-05-20 16:27:05 +03:00
parent f08593f0f8
commit f797a7143d
12 changed files with 264 additions and 209 deletions

View file

@ -171,112 +171,3 @@ pub const fn to_digit (c: char) -> DslResult<usize> {
_ => return Result::Err(Unexpected(c))
})
}
#[derive(Debug, Copy, Clone, Default, PartialEq)] pub struct Token<'source> {
pub source: &'source str,
pub start: usize,
pub length: usize,
pub value: Value<'source>,
}
#[derive(Debug, Copy, Clone, Default, PartialEq)] pub enum Value<'source> {
#[default] Nil,
Err(DslError),
Num(usize),
Sym(&'source str),
Key(&'source str),
Str(&'source str),
Exp(usize, TokenIter<'source>),
}
impl<'source> std::fmt::Display for Value<'source> {
fn fmt (&self, out: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(out, "{}", match self {
Nil => String::new(),
Err(e) => format!("[error: {e}]"),
Num(n) => format!("{n}"),
Sym(s) => format!("{s}"),
Key(s) => format!("{s}"),
Str(s) => format!("{s}"),
Exp(_, e) => format!("{e:?}"),
})
}
}
impl<'source> Token<'source> {
pub const fn new (
source: &'source str, start: usize, length: usize, value: Value<'source>
) -> Self {
Self { source, start, length, value }
}
pub const fn end (&self) -> usize {
self.start.saturating_add(self.length)
}
pub const fn slice (&'source self) -> &'source str {
self.slice_source(self.source)
}
pub const fn slice_source <'range> (&'source self, source: &'range str) -> &'range str {
str_range(source, self.start, self.end())
}
pub const fn slice_source_exp <'range> (&'source self, source: &'range str) -> &'range str {
str_range(source, self.start.saturating_add(1), self.end())
}
pub const fn with_value (self, value: Value<'source>) -> Self {
Self { value, ..self }
}
pub const fn value (&self) -> Value {
self.value
}
pub const fn error (self, error: DslError) -> Self {
Self { value: Value::Err(error), ..self }
}
pub const fn grow (self) -> Self {
Self { length: self.length.saturating_add(1), ..self }
}
pub const fn grow_num (self, m: usize, c: char) -> Self {
match to_digit(c) {
Ok(n) => Self { value: Num(10*m+n), ..self.grow() },
Result::Err(e) => Self { value: Err(e), ..self.grow() },
}
}
pub const fn grow_key (self) -> Self {
let token = self.grow();
token.with_value(Key(token.slice_source(self.source)))
}
pub const fn grow_sym (self) -> Self {
let token = self.grow();
token.with_value(Sym(token.slice_source(self.source)))
}
pub const fn grow_str (self) -> Self {
let token = self.grow();
token.with_value(Str(token.slice_source(self.source)))
}
pub const fn grow_exp (self) -> Self {
let token = self.grow();
if let Exp(depth, _) = token.value {
token.with_value(Exp(depth, TokenIter::new(token.slice_source_exp(self.source))))
} else {
unreachable!()
}
}
pub const fn grow_in (self) -> Self {
let token = self.grow_exp();
if let Value::Exp(depth, source) = token.value {
token.with_value(Value::Exp(depth.saturating_add(1), source))
} else {
unreachable!()
}
}
pub const fn grow_out (self) -> Self {
let token = self.grow_exp();
if let Value::Exp(depth, source) = token.value {
if depth > 0 {
token.with_value(Value::Exp(depth - 1, source))
} else {
return self.error(Unexpected(')'))
}
} else {
unreachable!()
}
}
}

View file

@ -1,12 +1,49 @@
use crate::*;
pub trait Dsl<State>: Sized {
fn take_from <'state, 'source: 'state> (state: &'state State, _: &mut TokenIter<'source>)
-> Perhaps<Self>
{
unimplemented!()
}
fn take_from_or_fail <'state, 'source: 'state> (
state: &'state State,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<Self> {
if let Some(value) = Dsl::<State>::take_from(state, token)? {
Ok(value)
} else {
Result::Err(error.into())
}
}
}
impl<T, U: Dsl<T>> DslFrom<U> for T {}
pub trait DslFrom<T: Dsl<Self>>: Sized {
fn take <'state, 'source: 'state> (&'state self, token: &mut TokenIter<'source>)
-> Perhaps<T>
{
T::take_from(self, token)
}
fn take_or_fail <'state, 'source: 'state> (
&'state self,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<T> {
T::take_from_or_fail(self, token, error)
}
}
/// Implement the [Dsl] trait, which boils down to
/// specifying two types and providing an expression.
#[macro_export] macro_rules! dsl {
($T:ty: |$self:ident:$S:ty, $iter:ident|$expr:expr) => {
impl ::tengri::dsl::Dsl<$T> for $S {
fn take <'state, 'source> (
&'state $self, $iter: &mut ::tengri::dsl::TokenIter<'source>,
impl ::tengri::dsl::Dsl<$S> for $T {
fn take_from <'state, 'source: 'state> (
state: &'state $S,
$iter: &mut ::tengri::dsl::TokenIter<'source>,
) -> ::tengri::Perhaps<$T> {
$expr
}
@ -14,43 +51,24 @@ use crate::*;
}
}
/// Maps a sequencer of EDN tokens to parameters of supported types
/// for a given context.
pub trait Dsl<Value>: Sized {
fn take <'state, 'source> (&'state self, _: &mut TokenIter<'source>) -> Perhaps<Value> {
unimplemented!()
}
fn take_or_fail <'state, 'source> (
&'state self,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<Value> {
if let Some(value) = Dsl::<Value>::take(self, token)? {
Ok(value)
} else {
Result::Err(error.into())
}
}
}
pub trait FromDsl<'state, State>: Sized {
fn take_from <'source: 'state> (state: &'state State, _token: &mut TokenIter<'source>)
-> Perhaps<Self>
{
unimplemented!()
}
fn take_from_or_fail <'source: 'state> (
state: &'state State,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<Self> {
if let Some(value) = FromDsl::<State>::take_from(state, token)? {
Ok(value)
} else {
Result::Err(error.into())
}
}
}
///// Maps a sequencer of EDN tokens to parameters of supported types
///// for a given context.
//pub trait Dsl<Value>: Sized {
//fn take <'state, 'source> (&'state self, _: &mut TokenIter<'source>) -> Perhaps<Value> {
//unimplemented!()
//}
//fn take_or_fail <'state, 'source> (
//&'state self,
//token: &mut TokenIter<'source>,
//error: impl Into<Box<dyn std::error::Error>>
//) -> Usually<Value> {
//if let Some(value) = Dsl::<Value>::take(self, token)? {
//Ok(value)
//} else {
//Result::Err(error.into())
//}
//}
//}
//impl<T: Dsl<U>, U> Dsl<U> for &T {
//fn take <'state, 'source> (&'state self, iter: &mut TokenIter<'source>) -> Perhaps<U> {
@ -64,8 +82,8 @@ pub trait FromDsl<'state, State>: Sized {
//}
//}
impl<'state, X, Y> Dsl<X> for Y where Y: FromDsl<'state, X> {
}
//impl<T, U: FromDsl<T>> Dsl<U> for T {
//impl<'state, X, Y> Dsl<X> for Y where Y: Dsl<'state, X> {
//}
//impl<T, U: Dsl<T>> Dsl<U> for T {
//}

110
dsl/src/dsl_token.rs Normal file
View file

@ -0,0 +1,110 @@
use crate::*;
#[derive(Debug, Copy, Clone, Default, PartialEq)] pub struct Token<'source> {
pub source: &'source str,
pub start: usize,
pub length: usize,
pub value: Value<'source>,
}
#[derive(Debug, Copy, Clone, Default, PartialEq)] pub enum Value<'source> {
#[default] Nil,
Err(DslError),
Num(usize),
Sym(&'source str),
Key(&'source str),
Str(&'source str),
Exp(usize, TokenIter<'source>),
}
impl<'source> std::fmt::Display for Value<'source> {
fn fmt (&self, out: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(out, "{}", match self {
Nil => String::new(),
Err(e) => format!("[error: {e}]"),
Num(n) => format!("{n}"),
Sym(s) => format!("{s}"),
Key(s) => format!("{s}"),
Str(s) => format!("{s}"),
Exp(_, e) => format!("{e:?}"),
})
}
}
impl<'source> Token<'source> {
pub const fn new (
source: &'source str, start: usize, length: usize, value: Value<'source>
) -> Self {
Self { source, start, length, value }
}
pub const fn end (&self) -> usize {
self.start.saturating_add(self.length)
}
pub const fn slice (&'source self) -> &'source str {
self.slice_source(self.source)
}
pub const fn slice_source <'range> (&'source self, source: &'range str) -> &'range str {
str_range(source, self.start, self.end())
}
pub const fn slice_source_exp <'range> (&'source self, source: &'range str) -> &'range str {
str_range(source, self.start.saturating_add(1), self.end())
}
pub const fn with_value (self, value: Value<'source>) -> Self {
Self { value, ..self }
}
pub const fn value (&self) -> Value {
self.value
}
pub const fn error (self, error: DslError) -> Self {
Self { value: Value::Err(error), ..self }
}
pub const fn grow (self) -> Self {
Self { length: self.length.saturating_add(1), ..self }
}
pub const fn grow_num (self, m: usize, c: char) -> Self {
match to_digit(c) {
Ok(n) => Self { value: Num(10*m+n), ..self.grow() },
Result::Err(e) => Self { value: Err(e), ..self.grow() },
}
}
pub const fn grow_key (self) -> Self {
let token = self.grow();
token.with_value(Key(token.slice_source(self.source)))
}
pub const fn grow_sym (self) -> Self {
let token = self.grow();
token.with_value(Sym(token.slice_source(self.source)))
}
pub const fn grow_str (self) -> Self {
let token = self.grow();
token.with_value(Str(token.slice_source(self.source)))
}
pub const fn grow_exp (self) -> Self {
let token = self.grow();
if let Exp(depth, _) = token.value {
token.with_value(Exp(depth, TokenIter::new(token.slice_source_exp(self.source))))
} else {
unreachable!()
}
}
pub const fn grow_in (self) -> Self {
let token = self.grow_exp();
if let Value::Exp(depth, source) = token.value {
token.with_value(Value::Exp(depth.saturating_add(1), source))
} else {
unreachable!()
}
}
pub const fn grow_out (self) -> Self {
let token = self.grow_exp();
if let Value::Exp(depth, source) = token.value {
if depth > 0 {
token.with_value(Value::Exp(depth - 1, source))
} else {
return self.error(Unexpected(')'))
}
} else {
unreachable!()
}
}
}

View file

@ -46,6 +46,7 @@ pub(crate) use self::Value::*;
pub(crate) use self::DslError::*;
mod dsl_error; pub use self::dsl_error::*;
mod dsl_token; pub use self::dsl_token::*;
mod dsl_parse; pub use self::dsl_parse::*;
mod dsl_provide; pub use self::dsl_provide::*;