mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
153 lines
5 KiB
Rust
153 lines
5 KiB
Rust
use crate::*;
|
|
|
|
pub enum EdnItem<T> {
|
|
Nil,
|
|
Num(usize),
|
|
Sym(T),
|
|
Key(T),
|
|
Exp(Vec<EdnItem<T>>),
|
|
}
|
|
impl<T> Default for EdnItem<T> {
|
|
fn default () -> Self {
|
|
Self::Nil
|
|
}
|
|
}
|
|
impl<T: Debug> Debug for EdnItem<T> {
|
|
fn fmt (&self, f: &mut Formatter<'_>) -> Result<(), FormatError> {
|
|
use EdnItem::*;
|
|
match self {
|
|
Nil => write!(f, "Nil"),
|
|
Num(u) => write!(f, "Num({u})"),
|
|
Sym(u) => write!(f, "Sym({u:?})"),
|
|
Key(u) => write!(f, "Key({u:?})"),
|
|
Exp(e) => write!(f, "Exp({})",
|
|
itertools::join(e.iter().map(|i|format!("{:?}", i)), ","))
|
|
}
|
|
}
|
|
}
|
|
impl<T: PartialEq> PartialEq for EdnItem<T> {
|
|
fn eq (&self, other: &Self) -> bool {
|
|
use EdnItem::*;
|
|
match (self, other) {
|
|
(Nil, Nil) => true,
|
|
(Num(a), Num(b)) => a == b,
|
|
(Sym(a), Sym(b)) => a == b,
|
|
(Key(a), Key(b)) => a == b,
|
|
(Exp(a), Exp(b)) => a == b,
|
|
_ => false
|
|
}
|
|
}
|
|
}
|
|
impl<T: AsRef<str> + PartialEq + Default + Clone + std::fmt::Debug> EdnItem<T> {
|
|
pub fn to_ref (&self) -> EdnItem<&str> {
|
|
match self {
|
|
Self::Key(x) => EdnItem::Key(x.as_ref()),
|
|
_ => todo!()
|
|
}
|
|
}
|
|
pub fn to_str (&self) -> &str {
|
|
match self {
|
|
Self::Key(x) => x.as_ref(),
|
|
_ => todo!()
|
|
}
|
|
}
|
|
pub fn symbols <'a> (&'a self) -> EdnIterator<'a, T> {
|
|
EdnIterator::new(&self)
|
|
}
|
|
}
|
|
impl EdnItem<String> {
|
|
pub fn from (other: EdnItem<impl AsRef<str>>) -> EdnItem<String> {
|
|
use EdnItem::*;
|
|
match other {
|
|
Nil => Nil,
|
|
Key(t) => Key(t.as_ref().to_string()),
|
|
_ => todo!()
|
|
}
|
|
}
|
|
}
|
|
impl<'a> TryFrom<Token<'a>> for EdnItem<String> {
|
|
type Error = ParseError;
|
|
fn try_from (token: Token<'a>) -> Result<Self, Self::Error> {
|
|
use Token::*;
|
|
Ok(match token {
|
|
Nil => Self::Nil,
|
|
Num(chars, index, length) =>
|
|
Self::Num(Token::number(&chars[index..index+length])),
|
|
Sym(chars, index, length) =>
|
|
Self::Sym(String::from(&chars[index..index+length])),
|
|
Key(chars, index, length) =>
|
|
Self::Key(String::from(&chars[index..index+length])),
|
|
Exp(chars, index, length, 0) =>
|
|
Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?),
|
|
_ => panic!("unclosed delimiter")
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<'a> TryFrom<Token<'a>> for EdnItem<&'a str> {
|
|
type Error = ParseError;
|
|
fn try_from (token: Token<'a>) -> Result<Self, Self::Error> {
|
|
use Token::*;
|
|
Ok(match token {
|
|
Nil => EdnItem::Nil,
|
|
Num(chars, index, length) =>
|
|
Self::Num(Token::number(&chars[index..index+length])),
|
|
Sym(chars, index, length) =>
|
|
Self::Sym(&chars[index..index+length]),
|
|
Key(chars, index, length) =>
|
|
Self::Key(&chars[index..index+length]),
|
|
Exp(chars, index, length, 0) =>
|
|
Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?),
|
|
_ => panic!("unclosed delimiter")
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<'a, T: std::fmt::Debug + Clone + Default + PartialEq + From<&'a str>> EdnItem<T> {
|
|
pub fn read_all (mut source: &'a str) -> Result<Vec<Self>, ParseError> {
|
|
let mut items = vec![];
|
|
loop {
|
|
if source.len() == 0 {
|
|
break
|
|
}
|
|
let (remaining, token) = Token::chomp(source)?;
|
|
match Self::read(token)? { Self::Nil => {}, item => items.push(item) };
|
|
source = remaining
|
|
}
|
|
Ok(items)
|
|
}
|
|
pub fn read_one (source: &'a str) -> Result<(Self, &'a str), ParseError> {
|
|
Ok({
|
|
if source.len() == 0 {
|
|
return Err(ParseError::Unknown(5))
|
|
}
|
|
let (remaining, token) = Token::chomp(source)?;
|
|
(Self::read(token)?, remaining)
|
|
})
|
|
}
|
|
pub fn read (token: Token<'a>) -> Result<Self, ParseError> {
|
|
use Token::*;
|
|
Ok(match token {
|
|
Nil => EdnItem::Nil,
|
|
Num(chars, index, length) =>
|
|
Self::Num(Token::number(&chars[index..index+length])),
|
|
Sym(chars, index, length) =>
|
|
Self::Sym(T::from(&chars[index..index+length])),
|
|
Key(chars, index, length) =>
|
|
Self::Key(T::from(&chars[index..index+length])),
|
|
Exp(chars, index, length, 0) =>
|
|
Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?),
|
|
_ => panic!("unclosed delimiter")
|
|
})
|
|
}
|
|
//pub fn to_str <'a> (&'a self) -> EdnItem<&'a str> {
|
|
//use EdnItem::*;
|
|
//match self {
|
|
//Nil => Nil,
|
|
//Num(n) => Num(*n),
|
|
//Sym(t) => Sym(t.as_str()),
|
|
//Key(t) => Key(t.as_str()),
|
|
//Exp(t) => Exp(t.iter().map(|x|x.to_str()).collect())
|
|
//}
|
|
//}
|
|
}
|