1use super::lex::Lexeme;
24
25#[derive(Debug)]
26pub enum Value<'a> {
27 Nil,
28 Number {
29 literal: &'a str,
30 },
31 String {
32 literal: &'a str,
33 },
34 Boolean {
35 value: bool,
36 },
37 SymbolicValue {
38 literal: &'a str,
39 },
40 Symbol {
41 namespace: Option<&'a str>,
42 name: &'a str,
43 },
44 Keyword {
45 namespace: Option<&'a str>,
46 name: &'a str,
47 alias: bool,
48 },
49 TaggedLiteral {
50 namespace: Option<&'a str>,
51 name: &'a str,
52 value: Box<Value<'a>>,
53 },
54 VarQuoted {
55 namespace: Option<&'a str>,
56 name: &'a str,
57 },
58 List {
59 values: Box<[Value<'a>]>,
60 },
61
62 Vector {
63 values: Box<[Value<'a>]>,
64 },
65
66 Set {
67 values: Box<[Value<'a>]>,
68 },
69 Map {
70 entries: Box<[MapEntry<'a>]>,
71 },
72}
73
74#[derive(Debug)]
75pub struct MapEntry<'a> {
76 pub key: Value<'a>,
77 pub value: Value<'a>,
78}
79
80#[derive(Debug)]
81pub enum BuildError {
82 TooFewTopLevelValues,
83 TooManyTopLevelValues,
84 RunawayCollection,
85 InconsistentCollections,
86 IncompleteMapEntry,
87 ExpectedTagForTaggedLiteral,
88 ExpectedValueForTaggedLiteral,
89 IncompleteTaggedLiteral,
90 UnexpectedLiteralTag,
91 ExpectedSymbolForLiteralTag,
92 ExpectedSymbolForVarQuote,
93}
94
95pub fn build<'a>(lexemes: &[Lexeme<'a>]) -> Result<Value<'a>, BuildError> {
96 use Lexeme::*;
97 let mut b = Builder::new();
98
99 for lexeme in lexemes {
100 let mut composite_ready = match lexeme {
101 Whitespace { .. } | SymbolicValuePrefix { .. } => false, Nil { .. } => b.add_to_composite(Value::Nil)?,
103 Boolean { value, .. } => {
104 b.add_to_composite(Value::Boolean { value: *value })?
105 }
106 Numeric { source, .. } => {
107 b.add_to_composite(Value::Number { literal: source })?
108 }
109 String { source, .. } => {
110 b.add_to_composite(Value::String { literal: source })?
111 }
112 SymbolicValue { source, .. } => {
113 b.add_to_composite(Value::SymbolicValue { literal: source })?
114 }
115 Symbol {
119 namespace, name, ..
120 }
121 | Tag {
122 namespace, name, ..
123 } => b.add_to_composite(Value::Symbol {
124 name,
125 namespace: *namespace,
126 })?,
127 Keyword {
128 alias,
129 namespace,
130 name,
131 ..
132 } => b.add_to_composite(Value::Keyword {
133 name,
134 namespace: *namespace,
135 alias: *alias,
136 })?,
137 StartList { .. } => b.start(CompositeType::List)?,
138 EndList { .. } => b.end(CompositeType::List)?,
139 StartSet { .. } => b.start(CompositeType::Set)?,
140 EndSet { .. } => b.end(CompositeType::Set)?,
141 StartVector { .. } => b.start(CompositeType::Vector)?,
142 EndVector { .. } => b.end(CompositeType::Vector)?,
143 StartMap { .. } => b.start(CompositeType::Map)?,
144 EndMap { .. } => b.end(CompositeType::Map)?,
145 TaggedLiteral { .. } => b.start(CompositeType::TaggedLiteral)?,
146 VarQuote { .. } => b.start(CompositeType::VarQuoted)?,
147 unhandled => todo!("Missing rule for:\n{:#?}", unhandled),
148 };
149
150 while composite_ready {
151 composite_ready = b.build_composite()?;
152 }
153 }
154
155 b.build_top_level()
156}
157
158struct Builder<'a> {
159 stack: Vec<CompositeBuilder<'a>>,
160}
161
162impl<'a> Builder<'a> {
163 fn new() -> Self {
164 Self {
165 stack: vec![CompositeBuilder::new(CompositeType::TopLevel)],
166 }
167 }
168
169 fn start(
170 &mut self,
171 composite_type: CompositeType,
172 ) -> Result<bool, BuildError> {
173 self.stack.push(CompositeBuilder::new(composite_type));
174 Ok(false)
175 }
176
177 fn end(&mut self, composite_type: CompositeType) -> Result<bool, BuildError> {
178 if self.stack.last().unwrap().composite_type() == composite_type {
179 Ok(true)
180 } else {
181 Err(BuildError::InconsistentCollections)
182 }
183 }
184
185 fn add_to_composite(&mut self, value: Value<'a>) -> Result<bool, BuildError> {
186 self.stack.last_mut().unwrap().add(value)
187 }
188
189 fn build_composite(&mut self) -> Result<bool, BuildError> {
190 let b = self.stack.pop().unwrap();
191 self.add_to_composite(b.build()?)
192 }
193
194 fn build_top_level(mut self) -> Result<Value<'a>, BuildError> {
195 let b = self.stack.pop().unwrap();
199 if b.composite_type() == CompositeType::TopLevel {
200 b.build()
201 } else {
202 Err(BuildError::RunawayCollection)
203 }
204 }
205}
206
207trait BuildComposite<'a> {
208 fn composite_type(&self) -> CompositeType;
209
210 fn add(&mut self, value: Value<'a>) -> Result<bool, BuildError>;
213
214 fn build(self) -> Result<Value<'a>, BuildError>;
215}
216
217#[derive(Clone, Copy, Debug, PartialEq, Eq)]
219enum CompositeType {
220 List,
221 Vector,
222 Set,
223 Map,
224 TaggedLiteral,
228 VarQuoted,
230 TopLevel,
234}
235
236enum CompositeBuilder<'a> {
244 TopLevel(TopLevelBuilder<'a>),
245 Seq(SeqBuilder<'a>),
246 Map(MapBuilder<'a>),
247 TaggedLiteral(TaggedLiteralBuilder<'a>),
248 VarQuoted(VarQuotedBuilder<'a>),
249}
250
251impl<'a> CompositeBuilder<'a> {
252 fn new(composite_type: CompositeType) -> Self {
253 use CompositeType as T;
254 match composite_type {
255 T::TopLevel => Self::TopLevel(TopLevelBuilder::new()),
256 T::List => Self::Seq(SeqBuilder::new(SeqType::List)),
257 T::Vector => Self::Seq(SeqBuilder::new(SeqType::Vector)),
258 T::Set => Self::Seq(SeqBuilder::new(SeqType::Set)),
259 T::Map => Self::Map(Default::default()),
260 T::TaggedLiteral => Self::TaggedLiteral(Default::default()),
261 T::VarQuoted => Self::VarQuoted(Default::default()),
262 }
263 }
264}
265
266impl<'a> BuildComposite<'a> for CompositeBuilder<'a> {
267 fn composite_type(&self) -> CompositeType {
268 match self {
269 CompositeBuilder::Seq(b) => b.composite_type(),
270 CompositeBuilder::Map(b) => b.composite_type(),
271 CompositeBuilder::TopLevel(b) => b.composite_type(),
272 CompositeBuilder::TaggedLiteral(b) => b.composite_type(),
273 CompositeBuilder::VarQuoted(b) => b.composite_type(),
274 }
275 }
276
277 fn add(&mut self, value: Value<'a>) -> Result<bool, BuildError> {
278 match self {
279 CompositeBuilder::Seq(b) => b.add(value),
280 CompositeBuilder::Map(b) => b.add(value),
281 CompositeBuilder::TopLevel(b) => b.add(value),
282 CompositeBuilder::TaggedLiteral(b) => b.add(value),
283 CompositeBuilder::VarQuoted(b) => b.add(value),
284 }
285 }
286
287 fn build(self) -> Result<Value<'a>, BuildError> {
288 match self {
289 CompositeBuilder::Seq(b) => b.build(),
290 CompositeBuilder::Map(b) => b.build(),
291 CompositeBuilder::TopLevel(b) => b.build(),
292 CompositeBuilder::TaggedLiteral(b) => b.build(),
293 CompositeBuilder::VarQuoted(b) => b.build(),
294 }
295 }
296}
297
298struct SeqBuilder<'a> {
299 seq_type: SeqType,
300 values: Vec<Value<'a>>,
301}
302
303impl<'a> SeqBuilder<'a> {
304 fn new(seq_type: SeqType) -> Self {
305 SeqBuilder {
306 seq_type,
307 values: Vec::new(),
308 }
309 }
310}
311
312impl<'a> BuildComposite<'a> for SeqBuilder<'a> {
313 fn composite_type(&self) -> CompositeType {
314 match self.seq_type {
315 SeqType::List => CompositeType::List,
316 SeqType::Vector => CompositeType::Vector,
317 SeqType::Set => CompositeType::Set,
318 }
319 }
320
321 fn add(&mut self, value: Value<'a>) -> Result<bool, BuildError> {
322 self.values.push(value);
323 Ok(false)
324 }
325
326 fn build(mut self) -> Result<Value<'a>, BuildError> {
327 self.values.shrink_to_fit();
328 let values = self.values.into_boxed_slice();
329 Ok(match self.seq_type {
330 SeqType::List => Value::List { values },
331 SeqType::Vector => Value::Vector { values },
332 SeqType::Set => Value::Set { values },
333 })
334 }
335}
336
337enum SeqType {
338 List,
339 Vector,
340 Set,
341}
342
343#[derive(Default)]
344enum TaggedLiteralBuilder<'a> {
345 #[default]
346 Empty,
347 WithTag {
348 namespace: Option<&'a str>,
349 name: &'a str,
350 },
351 WithTagAndValue {
352 namespace: Option<&'a str>,
353 name: &'a str,
354 value: Value<'a>,
355 },
356 Invalid,
357}
358
359impl<'a> BuildComposite<'a> for TaggedLiteralBuilder<'a> {
360 fn composite_type(&self) -> CompositeType {
361 CompositeType::TaggedLiteral
362 }
363
364 fn add(&mut self, value: Value<'a>) -> Result<bool, BuildError> {
365 use TaggedLiteralBuilder as B;
366 match std::mem::replace(self, B::Invalid) {
367 B::Empty => match value {
368 Value::Symbol { namespace, name } => {
369 *self = B::WithTag { namespace, name };
370 Ok(false)
371 }
372 _ => Err(BuildError::ExpectedSymbolForLiteralTag),
373 },
374 B::WithTag { namespace, name } => {
375 *self = B::WithTagAndValue {
376 namespace,
377 name,
378 value,
379 };
380 Ok(true)
381 }
382 _ => Err(BuildError::ExpectedValueForTaggedLiteral),
386 }
387 }
388
389 fn build(self) -> Result<Value<'a>, BuildError> {
390 if let TaggedLiteralBuilder::WithTagAndValue {
391 namespace,
392 name,
393 value,
394 } = self
395 {
396 Ok(Value::TaggedLiteral {
397 namespace,
398 name,
399 value: value.into(),
400 })
401 } else {
402 Err(BuildError::IncompleteTaggedLiteral)
405 }
406 }
407}
408
409#[derive(Default)]
410enum VarQuotedBuilder<'a> {
411 #[default]
412 Empty,
413 WithSymbol {
414 namespace: Option<&'a str>,
415 name: &'a str,
416 },
417 Invalid,
418}
419
420impl<'a> BuildComposite<'a> for VarQuotedBuilder<'a> {
421 fn composite_type(&self) -> CompositeType {
422 CompositeType::VarQuoted
423 }
424
425 fn add(&mut self, value: Value<'a>) -> Result<bool, BuildError> {
426 use VarQuotedBuilder as B;
427 match std::mem::replace(self, VarQuotedBuilder::Invalid) {
428 B::Empty => match value {
429 Value::Symbol { namespace, name } => {
430 *self = VarQuotedBuilder::WithSymbol { namespace, name };
431 Ok(true)
432 }
433 _ => Err(BuildError::ExpectedSymbolForVarQuote),
434 },
435 _ => unreachable!("should have triggered error or build"),
436 }
437 }
438
439 fn build(self) -> Result<Value<'a>, BuildError> {
440 if let VarQuotedBuilder::WithSymbol { namespace, name } = self {
441 Ok(Value::VarQuoted { namespace, name })
442 } else {
443 unreachable!("should not have been triggered unless ready");
445 }
446 }
447}
448
449#[derive(Default)]
450struct MapBuilder<'a> {
451 key: Option<Value<'a>>,
452 entries: Vec<MapEntry<'a>>,
453}
454
455impl<'a> BuildComposite<'a> for MapBuilder<'a> {
456 fn composite_type(&self) -> CompositeType {
457 CompositeType::Map
458 }
459
460 fn add(&mut self, value: Value<'a>) -> Result<bool, BuildError> {
461 if let Some(key) = self.key.take() {
462 self.entries.push(MapEntry { key, value });
463 } else {
464 self.key = Some(value);
465 }
466 Ok(false)
467 }
468
469 fn build(mut self) -> Result<Value<'a>, BuildError> {
470 if self.key.is_none() {
471 self.entries.shrink_to_fit();
472 Ok(Value::Map {
473 entries: self.entries.into_boxed_slice(),
474 })
475 } else {
476 Err(BuildError::IncompleteMapEntry)
477 }
478 }
479}
480
481#[derive(Default)]
482struct TopLevelBuilder<'a> {
483 value: Option<Value<'a>>,
484}
485
486impl<'a> TopLevelBuilder<'a> {
487 fn new() -> Self {
488 Default::default()
489 }
490}
491
492impl<'a> BuildComposite<'a> for TopLevelBuilder<'a> {
493 fn composite_type(&self) -> CompositeType {
494 CompositeType::TopLevel
495 }
496
497 fn add(&mut self, value: Value<'a>) -> Result<bool, BuildError> {
498 if self.value.is_none() {
499 self.value = Some(value);
500 Ok(false)
504 } else {
505 Err(BuildError::TooManyTopLevelValues)
506 }
507 }
508
509 fn build(self) -> Result<Value<'a>, BuildError> {
510 self.value.ok_or(BuildError::TooFewTopLevelValues)
511 }
512}