this one at least compiles

This commit is contained in:
🪞👃🪞 2025-07-19 07:55:56 +03:00
parent a145e332de
commit 291b917970
7 changed files with 416 additions and 198 deletions

View file

@ -44,13 +44,16 @@ impl<Str: DslStr, Exp: DslExp> Val<Str, Exp> {
T::Str: for<'a> From<&'a Str>,
T::Exp: for<'a> From<&'a Exp>
{
match self { Val::Nil => Val::Nil,
Val::Num(u) => Val::Num(*u),
Val::Sym(s) => Val::Sym(s.into()),
Val::Key(s) => Val::Key(s.into()),
Val::Str(s) => Val::Str(s.into()),
Val::Exp(d, x) => Val::Exp(*d, x.into()),
Val::Error(e) => Val::Error(*e) } }
match self {
Val::Nil => Val::Nil,
Val::Num(u) => Val::Num(*u),
Val::Sym(s) => Val::Sym(s.into()),
Val::Key(s) => Val::Key(s.into()),
Val::Str(s) => Val::Str(s.into()),
Val::Exp(d, x) => Val::Exp(*d, x.into()),
Val::Error(e) => Val::Error(*e)
}
}
}
/// The expression representation for a [Dsl] implementation.
/// [Cst] uses [CstIter]. [Ast] uses [VecDeque].
@ -96,22 +99,6 @@ impl<Str, Exp> Token<Str, Exp> {
Self { value: self.value, ..*self }
}
}
impl<'s> CstToken<'s> {
pub const fn slice (&self) -> &str {
str_range(self.source, self.start, self.end()) }
pub const fn slice_exp (&self) -> &str {
str_range(self.source, self.start.saturating_add(1), self.end()) }
pub const fn grow (&mut self) -> &mut Self {
let max_length = self.source.len().saturating_sub(self.start);
self.length = self.length + 1;
if self.length > max_length { self.length = max_length }
self
}
pub const fn grow_exp (&'s mut self, depth: isize, source: &'s str) -> &mut Self {
self.value = Val::Exp(depth, Cst(CstConstIter(source)));
self
}
}
/// To the [Dsl], a token is equivalent to its `value` field.
impl<Str: DslStr, Exp: DslExp> Dsl for Token<Str, Exp> {
type Str = Str; type Exp = Exp;
@ -126,16 +113,17 @@ pub trait Dsl: Clone + Debug {
/// Request the top-level DSL [Val]ue.
/// May perform cloning or parsing.
fn dsl (&self) -> Val<Self::Str, Self::Exp>;
fn err (&self) -> Option<DslError> {self.dsl().err()}
fn nil (&self) -> bool {self.dsl().nil()}
fn num (&self) -> Option<usize> {self.dsl().num()}
fn sym (&self) -> Option<Self::Str> {self.dsl().sym()}
fn key (&self) -> Option<Self::Str> {self.dsl().key()}
fn str (&self) -> Option<Self::Str> {self.dsl().str()}
fn exp (&self) -> Option<Self::Exp> {self.dsl().exp()}
fn err (&self) -> Option<DslError> {self.dsl().err()}
fn nil (&self) -> bool {self.dsl().nil()}
fn num (&self) -> Option<usize> {self.dsl().num()}
fn sym (&self) -> Option<Self::Str> {self.dsl().sym()}
fn key (&self) -> Option<Self::Str> {self.dsl().key()}
fn str (&self) -> Option<Self::Str> {self.dsl().str()}
fn exp (&self) -> Option<Self::Exp> {self.dsl().exp()}
fn exp_depth (&self) -> Option<isize> {self.dsl().exp_depth()}
fn exp_head (&self) -> Val<Self::Str, Self::Exp> {self.dsl().exp_head()}
fn exp_tail (&self) -> Val<Self::Str, Self::Exp> {self.dsl().exp_tail()}
fn exp_tail (&self) -> Self::Exp {self.dsl().exp_tail()}
fn exp_each (&self, f: impl Fn(&Self) -> Usually<()>) -> Usually<()> { todo!() }
}
/// The most basic implementor of the [Dsl] trait.
impl<Str: DslStr, Exp: DslExp> Dsl for Val<Str, Exp> {
@ -146,25 +134,71 @@ impl<Str: DslStr, Exp: DslExp> Dsl for Val<Str, Exp> {
/// by cloning source slices into owned ([Arc]) string slices.
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Ast(Arc<VecDeque<Arc<Token<Arc<str>, Ast>>>>);
pub type AstVal = Val<Arc<str>, Ast>;
pub type AstToken = Token<Arc<str>, Ast>;
impl Dsl for Ast {
type Str = Arc<str>; type Exp = Ast;
fn dsl (&self) -> Val<Arc<str>, Ast> { Val::Exp(0, Ast(self.0.clone())) }
}
impl<'s> From<&'s str> for Ast {
fn from (source: &'s str) -> Self {
let source: Arc<str> = source.into();
Self(CstIter(CstConstIter(source.as_ref()))
.map(|token|Arc::new(Token {
source: source.clone(),
start: token.start,
length: token.length,
value: match token.value {
Val::Nil => Val::Nil,
Val::Num(u) => Val::Num(u),
Val::Sym(s) => Val::Sym(s.into()),
Val::Key(s) => Val::Key(s.into()),
Val::Str(s) => Val::Str(s.into()),
Val::Exp(d, x) => Val::Exp(d, x.into()),
Val::Error(e) => Val::Error(e.into())
},
}))
.collect::<VecDeque<_>>()
.into())
}
}
impl<'s> From<Cst<'s>> for Ast {
fn from (cst: Cst<'s>) -> Self {
let mut tokens: VecDeque<_> = Default::default();
Self(tokens.into())
}
}
/// The concrete syntax tree (CST) implements zero-copy
/// parsing of the DSL from a string reference. CST items
/// preserve info about their location in the source.
/// CST stores strings as source references and expressions as [CstIter] instances.
#[derive(Debug, Copy, Clone, Default, PartialEq)]
pub struct Cst<'s>(pub CstConstIter<'s>);
pub struct Cst<'s>(pub CstIter<'s>);
pub type CstVal<'s> = Val<&'s str, Cst<'s>>;
pub type CstToken<'s> = Token<&'s str, Cst<'s>>;
impl<'s> CstToken<'s> {
pub const fn slice (&self) -> &str {
str_range(self.source, self.start, self.end()) }
pub const fn slice_exp (&self) -> &str {
str_range(self.source, self.start.saturating_add(1), self.end()) }
pub const fn grow (&mut self) -> &mut Self {
let max_length = self.source.len().saturating_sub(self.start);
self.length = self.length + 1;
if self.length > max_length { self.length = max_length }
self
}
pub const fn grow_exp (&'s mut self, depth: isize, source: &'s str) -> &mut Self {
self.value = Val::Exp(depth, Cst(CstIter(CstConstIter(source))));
self
}
}
impl<'s> Dsl for Cst<'s> {
type Str = &'s str; type Exp = Cst<'s>;
fn dsl (&self) -> Val<Self::Str, Self::Exp> { Val::Exp(0, Cst(self.0)) }
}
impl<'s> From<&'s str> for Cst<'s> {
fn from (source: &'s str) -> Self {
Self(CstConstIter(source))
Self(CstIter(CstConstIter(source)))
}
}
/// DSL-specific error codes.
@ -250,7 +284,7 @@ pub const fn peek <'s> (mut value: CstVal<'s>, source: &'s str) -> CstToken<'s>
start = i;
length = 1;
if is_exp_start(c) {
value = Exp(1, Cst(CstConstIter(str_range(source, i, i+1))));
value = Exp(1, Cst(CstIter(CstConstIter(str_range(source, i, i+1)))));
} else if is_str_start(c) {
value = Str(str_range(source, i, i+1));
} else if is_sym_start(c) {
@ -289,17 +323,14 @@ pub const fn peek <'s> (mut value: CstVal<'s>, source: &'s str) -> CstToken<'s>
}
} else if let Exp(depth, exp) = value {
if depth == 0 {
value = Exp(0, Cst(CstConstIter(str_range(source, start, start + length))));
value = Exp(0, Cst(CstIter(CstConstIter(str_range(source, start, start + length)))));
break
}
length += 1;
if c == ')' {
value = Exp(depth-1, Cst(CstConstIter(str_range(source, start, start + length))));
} else if c == '(' {
value = Exp(depth+1, Cst(CstConstIter(str_range(source, start, start + length))));
} else {
value = Exp(depth, Cst(CstConstIter(str_range(source, start, start + length))));
}
value = Exp(
if c == ')' { depth-1 } else if c == '(' { depth+1 } else { depth },
Cst(CstIter(CstConstIter(str_range(source, start, start + length))))
);
} else if let Num(m) = value {
if is_num_end(c) {
break