mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 03:36:42 +01:00
this one at least compiles
This commit is contained in:
parent
a145e332de
commit
291b917970
7 changed files with 416 additions and 198 deletions
115
dsl/src/lib.rs
115
dsl/src/lib.rs
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue