1use log::error;
2use miette::SourceSpan;
3use std::fmt::{Debug, Display};
4use std::panic::Location;
5
6#[derive(Debug, PartialEq, Clone)]
8pub struct MonDocument {
9 pub root: MonValue,
10 pub imports: Vec<ImportStatement>,
11}
12
13#[derive(Debug, PartialEq, Clone)]
16pub struct MonValue {
17 pub kind: MonValueKind,
18 pub anchor: Option<String>,
19 pub pos_start: usize,
20 pub pos_end: usize,
21}
22
23impl MonValue {
24 #[must_use]
26 pub fn get_source_span(&self) -> SourceSpan {
27 SourceSpan::new(self.pos_start.into(), self.pos_end - self.pos_start)
28 }
29}
30
31#[derive(Debug, PartialEq, Clone)]
33pub enum MonValueKind {
34 String(String),
36 Number(f64),
38 Boolean(bool),
40 Null,
42 Object(Vec<Member>),
44 Array(Vec<MonValue>),
46 Alias(String),
48 EnumValue {
50 enum_name: String,
51 variant_name: String,
52 },
53 ArraySpread(String),
55}
56
57#[derive(Debug, PartialEq, Clone)]
59pub enum Member {
60 Pair(Pair),
62 Spread(String),
64 Import(ImportStatement),
66 TypeDefinition(TypeDefinition),
68}
69
70#[derive(Debug, PartialEq, Clone)]
72pub struct Pair {
73 pub key: String,
75 pub value: MonValue,
77 pub validation: Option<TypeSpec>,
81}
82
83#[derive(Debug, PartialEq, Clone)]
85pub struct ImportStatement {
86 pub path: String,
88 pub spec: ImportSpec,
90 pub pos_start: usize,
92 pub pos_end: usize,
94}
95
96#[derive(Debug, PartialEq, Clone)]
98pub enum ImportSpec {
99 Namespace(String),
101 Named(Vec<ImportSpecifier>),
103}
104
105#[derive(Debug, PartialEq, Clone)]
107pub struct ImportSpecifier {
108 pub name: String,
110 pub is_anchor: bool,
112}
113
114#[derive(Debug, PartialEq, Clone)]
116pub struct TypeDefinition {
117 pub name: String,
119 pub name_span: SourceSpan,
121 pub def_type: TypeDef,
123 pub pos_start: usize,
125 pub pos_end: usize,
127}
128
129#[derive(Debug, PartialEq, Clone)]
131pub enum TypeDef {
132 Struct(StructDef),
134 Enum(EnumDef),
136}
137
138impl TypeDef {
139 #[must_use]
141 pub fn get_span(&self) -> SourceSpan {
142 match self {
143 TypeDef::Struct(s) => (s.pos_start, s.pos_end - s.pos_start).into(),
144 TypeDef::Enum(e) => (e.pos_start, e.pos_end - e.pos_start).into(),
145 }
146 }
147}
148
149#[derive(Debug, PartialEq, Clone)]
151pub struct StructDef {
152 pub fields: Vec<FieldDef>,
154 pub pos_start: usize,
156 pub pos_end: usize,
158}
159
160#[derive(Debug, PartialEq, Clone)]
162pub struct FieldDef {
163 pub name: String,
165 pub type_spec: TypeSpec,
167 pub default_value: Option<MonValue>,
169}
170
171#[derive(Debug, PartialEq, Clone)]
173pub struct EnumDef {
174 pub variants: Vec<String>,
176 pub pos_start: usize,
178 pub pos_end: usize,
180}
181
182#[derive(Debug, PartialEq, Clone)]
184pub enum TypeSpec {
185 Simple(String, SourceSpan),
187 Collection(Vec<TypeSpec>, SourceSpan),
189 Spread(Box<TypeSpec>, SourceSpan),
191}
192
193impl TypeSpec {
194 #[must_use]
195 pub fn get_span(&self) -> SourceSpan {
196 match self {
197 TypeSpec::Simple(_, span)
198 | TypeSpec::Collection(_, span)
199 | TypeSpec::Spread(_, span) => *span,
200 }
201 }
202}
203
204impl Display for Member {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 match self {
207 Member::Pair(p) => write!(f, "Pair({}: {})", p.key, p.value),
208 Member::Spread(s) => write!(f, "Spread(...*{s})"),
209 Member::Import(i) => write!(f, "Import({i:?})"),
210 Member::TypeDefinition(t) => write!(f, "TypeDef({t:?})"),
211 }
212 }
213}
214
215#[derive(Debug, Default)]
217pub struct SymbolTable {
218 pub types: std::collections::HashMap<String, TypeDefinition>,
220}
221
222impl SymbolTable {
223 #[must_use]
225 pub fn new() -> Self {
226 Self::default()
227 }
228}
229
230impl Display for MonDocument {
231 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
232 write!(f, "{}", self.root)
233 }
234}
235
236impl Display for MonValueKind {
237 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
238 match self {
239 MonValueKind::String(s) => write!(f, "\"{s}\""),
240 MonValueKind::Number(n) => write!(f, "{n}"),
241 MonValueKind::Boolean(b) => write!(f, "{b}"),
242 MonValueKind::Null => write!(f, "null"),
243 MonValueKind::Object(o) => {
244 write!(f, "{{")?;
245 for (i, member) in o.iter().enumerate() {
246 write!(f, "{member}")?;
247 if i < o.len() - 1 {
248 write!(f, ", ")?;
249 }
250 }
251 write!(f, "}}")
252 }
253 MonValueKind::Array(a) => {
254 write!(f, "[")?;
255 for (i, value) in a.iter().enumerate() {
256 write!(f, "{value}")?;
257 if i < a.len() - 1 {
258 write!(f, ", ")?;
259 }
260 }
261 write!(f, "]")
262 }
263 MonValueKind::Alias(a) => write!(f, "*{a}"),
264 MonValueKind::EnumValue {
265 enum_name,
266 variant_name,
267 } => {
268 write!(f, "${enum_name}.{variant_name}")
269 }
270 MonValueKind::ArraySpread(s) => write!(f, "...*{s}"),
271 }
272 }
273}
274
275impl Display for MonValue {
276 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
277 if let Some(anchor) = &self.anchor {
278 write!(f, "&{anchor} ")?;
279 }
280 write!(f, "{}", self.kind)
281 }
282}
283
284impl Pair {
285 #[track_caller]
286 #[must_use]
287 pub fn get_span(&self) -> SourceSpan {
288 match &self.validation {
289 None => {
290 error!(
291 "No validation for `Pair`found for source span called by {}",
292 Location::caller()
293 );
294 SourceSpan::new(0.into(), 0)
295 }
296 Some(valid) => match valid {
297 TypeSpec::Simple(_, source_span)
298 | TypeSpec::Collection(_, source_span)
299 | TypeSpec::Spread(_, source_span) => *source_span,
300 },
301 }
302 }
303}