use crate::span::Span;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Datum<'a> {
pub kind: DatumKind<'a>,
pub span: Span,
pub line: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DatumKind<'a> {
List {
delim: Delim,
items: Vec<Datum<'a>>,
tail: Option<Box<Datum<'a>>>,
},
Symbol(&'a str),
Keyword(&'a str),
Number(&'a str),
Str(&'a str),
Char(&'a str),
Bool(bool),
Prefixed {
prefix: Prefix,
notation: Notation,
inner: Box<Datum<'a>>,
arg: Option<Box<Datum<'a>>>,
},
HashLiteral {
tag: &'a str,
inner: Option<Box<Datum<'a>>>,
},
Label {
id: &'a str,
inner: Box<Datum<'a>>,
},
LabelRef {
id: &'a str,
},
}
impl<'a> Datum<'a> {
pub fn as_symbol(&self) -> Option<&'a str> {
match self.kind {
DatumKind::Symbol(s) => Some(s),
_ => None,
}
}
pub fn as_keyword(&self) -> Option<&'a str> {
match self.kind {
DatumKind::Keyword(s) => Some(s),
_ => None,
}
}
pub fn as_number(&self) -> Option<&'a str> {
match self.kind {
DatumKind::Number(s) => Some(s),
_ => None,
}
}
pub fn as_str(&self) -> Option<&'a str> {
match self.kind {
DatumKind::Str(s) => Some(s),
_ => None,
}
}
pub fn as_char(&self) -> Option<&'a str> {
match self.kind {
DatumKind::Char(s) => Some(s),
_ => None,
}
}
pub fn items(&self) -> Option<&[Datum<'a>]> {
match &self.kind {
DatumKind::List { items, .. } => Some(items),
_ => None,
}
}
pub fn head_symbol(&self) -> Option<&'a str> {
self.items()?.first()?.as_symbol()
}
pub fn text<'s>(&self, source: &'s str) -> &'s str {
self.span.text(source)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Delim {
Round,
Square,
Curly,
Set,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Prefix {
Quote,
Quasiquote,
Unquote,
UnquoteSplicing,
Discard,
VarQuote,
FunctionQuote,
Deref,
Meta,
ReadEval,
FeatureConditional {
include: bool,
},
ReaderConditional {
splicing: bool,
},
HashFn,
Splice,
Mutable,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Notation {
Shorthand,
Longhand,
}