mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 11:46:42 +01:00
dsl gets the gordian treatment
This commit is contained in:
parent
93b1cf1a5c
commit
d6e8be6ce5
9 changed files with 540 additions and 456 deletions
|
|
@ -1,70 +1,36 @@
|
|||
use crate::*;
|
||||
use std::sync::Arc;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub enum Ast {
|
||||
#[default] Nil,
|
||||
Err(DslError),
|
||||
Num(usize),
|
||||
Sym(Arc<str>),
|
||||
Key(Arc<str>),
|
||||
Str(Arc<str>),
|
||||
Exp(Arc<Box<dyn AstIter>>),
|
||||
}
|
||||
/// Owns its values, and has no metadata.
|
||||
pub type AstToken = Token<AstValue, AstMeta>;
|
||||
|
||||
/// Emits tokens.
|
||||
pub trait AstIter: Debug {
|
||||
fn peek (&self) -> Option<Ast>;
|
||||
fn next (&mut self) -> Option<Ast>;
|
||||
fn rest (self) -> Option<Box<dyn AstIter>>;
|
||||
}
|
||||
#[derive(Debug, Copy, Clone, Default, PartialEq)]
|
||||
pub struct AstMeta;
|
||||
|
||||
/// A [Cst] can be used as an [Ast].
|
||||
impl<'source: 'static> AstIter for Cst<'source> {
|
||||
fn peek (&self) -> Option<Ast> {
|
||||
Cst::peek(self).map(|token|token.value.into())
|
||||
}
|
||||
fn next (&mut self) -> Option<Ast> {
|
||||
Iterator::next(self).map(|token|token.value.into())
|
||||
}
|
||||
fn rest (self) -> Option<Box<dyn AstIter>> {
|
||||
self.peek().is_some().then(||Box::new(self) as Box<dyn AstIter>)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Ast {
|
||||
fn fmt (&self, out: &mut Formatter) -> Result<(), std::fmt::Error> {
|
||||
use Ast::*;
|
||||
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: 'static> From<CstValue<'source>> for Ast {
|
||||
fn from (other: CstValue<'source>) -> Self {
|
||||
use CstValue::*;
|
||||
match other {
|
||||
Nil => Self::Nil,
|
||||
Err(e) => Self::Err(e),
|
||||
Num(u) => Self::Num(u),
|
||||
Sym(s) => Self::Sym(s.into()),
|
||||
Key(s) => Self::Key(s.into()),
|
||||
Str(s) => Self::Str(s.into()),
|
||||
Exp(_, s) => Self::Exp(Arc::new(s.into())),
|
||||
pub type AstValue = Value<Arc<str>, AstExp>;
|
||||
impl<'source> From<CstValue<'source>> for AstValue {
|
||||
fn from (value: CstValue<'source>) -> Self {
|
||||
use Value::*;
|
||||
match value {
|
||||
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(x) => Exp(x.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'source: 'static> Into<Box<dyn AstIter>> for Cst<'source> {
|
||||
fn into (self) -> Box<dyn AstIter> {
|
||||
Box::new(self)
|
||||
#[derive(Clone, Default, PartialEq)]
|
||||
pub struct AstExp(pub Vec<AstToken>);
|
||||
impl<'source> From<CstExp<'source>> for AstExp {
|
||||
fn from (exp: CstExp<'source>) -> AstExp {
|
||||
AstExp(exp.words.map(|token|Token(
|
||||
AstValue::from(token.value()),
|
||||
AstMeta,
|
||||
)).collect())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue