1use std::fmt::Display;
2
3use chrono::{DateTime, Local};
4use uuid::Uuid;
5
6use crate::lexer::lexeme::Lexeme;
7
8#[derive(Debug, Clone)]
9pub struct Form<'source> {
10 pub kind: FormKind<'source>,
11 pub lexeme: Lexeme,
12}
13
14#[derive(Debug, Clone, PartialEq)]
15pub enum FormKind<'source> {
16 List(Vec<Form<'source>>),
17 Vector(Vec<Form<'source>>),
18 Map(Vec<(Form<'source>, Form<'source>)>),
19 Set(Vec<Form<'source>>),
20 Keyword(&'source str),
21 Symbol(&'source str),
22 Tagged(&'source str, Box<Form<'source>>),
23 Discard(&'source str),
24 Integer(i64),
25 Float(f64),
26 Boolean(bool),
27 Character(char),
28 String(String),
29 Inst(DateTime<Local>),
30 UUID(Uuid),
31 Nil,
32}
33
34impl PartialEq for Form<'_> {
35 fn eq(&self, other: &Self) -> bool {
36 self.kind == other.kind
37 }
38}
39
40impl<'source> Display for Form<'source> {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 match &self.kind {
43 FormKind::List(forms) => {
44 write!(f, "( ")?;
45 for form in forms {
46 write!(f, "{} ", form)?;
47 }
48 write!(f, ")")
49 }
50 FormKind::Vector(forms) => {
51 write!(f, "[ ")?;
52 for form in forms {
53 write!(f, "{} ", form)?;
54 }
55 write!(f, "]")
56 }
57 FormKind::Map(forms) => {
58 write!(f, "{{ ")?;
59 for (key, value) in forms {
60 write!(f, "{} {}, ", key, value)?;
61 }
62 write!(f, "}}")
63 }
64 FormKind::Set(forms) => {
65 write!(f, "#{{ ")?;
66 for form in forms {
67 write!(f, "{} ", form)?;
68 }
69 write!(f, "}}")
70 }
71 FormKind::Keyword(span) => write!(f, ":{}", span),
72 FormKind::Symbol(span) => write!(f, "{}", span),
73 FormKind::Tagged(span, form) => write!(f, "#{} {}", span, form),
74 FormKind::Inst(dt) => write!(f, "#inst \"{}\"", dt.to_rfc3339()),
75 FormKind::UUID(uuid) => write!(f, "#uuid \"{}\"", uuid.as_hyphenated()),
76 FormKind::Discard(span) => write!(f, "#_{}", span),
77 FormKind::Integer(span) => write!(f, "{}", span),
78 FormKind::Float(span) => write!(f, "{}", span),
79 FormKind::Boolean(span) => write!(f, "{}", span),
80 FormKind::Character(span) => write!(
81 f,
82 "\\{}",
83 match span {
84 '\n' => "newline",
85 '\r' => "return",
86 '\t' => "tab",
87 ' ' => "space",
88 c => return write!(f, "\\{}", c),
89 }
90 ),
91 FormKind::String(span) => write!(f, "\"{}\"", span),
92 FormKind::Nil => write!(f, "nil"),
93 }
94 }
95}