nreplops_tool/clojure/
lex.rs

1// clojure/lex.rs
2// Copyright 2024 Matti Hänninen
3//
4// Licensed under the Apache License, Version 2.0 (the "License"); you may not
5// use this file except in compliance with the License. You may obtain a copy of
6// the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13// License for the specific language governing permissions and limitations under
14// the License.
15
16use thiserror::Error;
17
18use super::pest_grammar::*;
19
20use Lexeme as L;
21use Rule as R;
22
23#[derive(Debug, Error)]
24pub enum Error {
25  #[error("Pest error: {0}")]
26  Pest(#[from] pest::error::Error<Rule>),
27}
28
29#[derive(Clone, Copy, Debug)]
30pub struct FormIx {
31  /// The index of the parent form or zero, if none.
32  pub parent: u32,
33  /// The index of this form.
34  pub ix: u32,
35}
36
37impl FormIx {
38  fn root(ix: u32) -> Self {
39    Self { parent: 0, ix }
40  }
41  fn child(&self, ix: u32) -> Self {
42    Self {
43      parent: self.ix,
44      ix,
45    }
46  }
47}
48
49#[derive(Debug)]
50pub enum Lexeme<'a> {
51  /// Whitespace
52  Whitespace {
53    source: &'a str,
54  },
55  /// Comment
56  Comment {
57    /// The original source for the comment line.
58    ///
59    /// Effectively the end of the line starting from the comment marker up to
60    /// but excluding the line break.  Note that in addition to `;` the comment
61    /// marker can be `#!`.
62    source: &'a str,
63  },
64  /// Meta data prefix (`^` or `#^`)
65  Meta {
66    /// The form to which the meta data is attached.  In essence, the form that
67    /// owns the meta data.
68    form_ix: FormIx,
69    /// The form which contains the meta data itself.
70    data_ix: FormIx,
71    /// The original source for the meta data prefix.  Effectively either `"^"`
72    /// or `"#^"`.
73    source: &'a str,
74  },
75  Discard {
76    form_ix: FormIx,
77    source: &'a str,
78  },
79  Quote {
80    form_ix: FormIx,
81    source: &'a str,
82  },
83  VarQuote {
84    form_ix: FormIx,
85    source: &'a str,
86  },
87  Synquote {
88    form_ix: FormIx,
89    source: &'a str,
90  },
91  Unquote {
92    form_ix: FormIx,
93    source: &'a str,
94  },
95  SplicingUnquote {
96    form_ix: FormIx,
97    source: &'a str,
98  },
99  Nil {
100    form_ix: FormIx,
101    source: &'a str,
102  },
103  Boolean {
104    form_ix: FormIx,
105    value: bool,
106    source: &'a str,
107  },
108  Numeric {
109    form_ix: FormIx,
110    class: NumberClass,
111    value: NumericValue<'a>,
112    source: &'a str,
113  },
114  Char {
115    form_ix: FormIx,
116    syntax: CharSyntax,
117    value: char,
118    source: &'a str,
119  },
120  String {
121    form_ix: FormIx,
122    value: Box<[StringFragment<'a>]>,
123    source: &'a str,
124  },
125  Regex {
126    form_ix: FormIx,
127    source: &'a str,
128  },
129  SymbolicValuePrefix {
130    form_ix: FormIx,
131    source: &'a str,
132  },
133  SymbolicValue {
134    form_ix: FormIx,
135    value: SymbolicValue<'a>,
136    source: &'a str,
137  },
138  Symbol {
139    form_ix: FormIx,
140    namespace: Option<&'a str>,
141    name: &'a str,
142    source: &'a str,
143  },
144  Tag {
145    form_ix: FormIx,
146    namespace: Option<&'a str>,
147    name: &'a str,
148    source: &'a str,
149  },
150  Keyword {
151    form_ix: FormIx,
152    alias: bool,
153    namespace: Option<&'a str>,
154    name: &'a str,
155    source: &'a str,
156  },
157  StartList {
158    form_ix: FormIx,
159    source: &'a str,
160  },
161  EndList {
162    form_ix: FormIx,
163    source: &'a str,
164  },
165  StartVector {
166    form_ix: FormIx,
167    source: &'a str,
168  },
169  EndVector {
170    form_ix: FormIx,
171    source: &'a str,
172  },
173  StartSet {
174    form_ix: FormIx,
175    source: &'a str,
176  },
177  EndSet {
178    form_ix: FormIx,
179    source: &'a str,
180  },
181  MapQualifier {
182    form_ix: FormIx,
183    source: &'a str,
184  },
185  StartMap {
186    form_ix: FormIx,
187    alias: bool,
188    namespace: Option<&'a str>,
189    source: &'a str,
190  },
191  EndMap {
192    form_ix: FormIx,
193    source: &'a str,
194  },
195  StartAnonymousFn {
196    form_ix: FormIx,
197    source: &'a str,
198  },
199  EndAnonymousFn {
200    form_ix: FormIx,
201    source: &'a str,
202  },
203  ReaderConditionalPrefix {
204    form_ix: FormIx,
205    source: &'a str,
206  },
207  StartReaderConditional {
208    form_ix: FormIx,
209    splicing: bool,
210    source: &'a str,
211  },
212  EndReaderConditional {
213    form_ix: FormIx,
214    source: &'a str,
215  },
216  TaggedLiteral {
217    form_ix: FormIx,
218    tag_ix: FormIx,
219    arg_ix: FormIx,
220    source: &'a str,
221  },
222  Residual(Pair<'a>),
223}
224
225#[derive(Clone, Copy, Debug)]
226pub enum CharSyntax {
227  Name,
228  Octal,
229  CodePoint,
230  Simple,
231}
232
233#[derive(Clone, Copy, Debug)]
234pub enum SymbolicValue<'a> {
235  PosInf,
236  NegInf,
237  NaN,
238  Other(&'a str),
239}
240
241#[derive(Clone, Copy, Debug)]
242pub enum NumericValue<'a> {
243  Int {
244    positive: bool,
245    radix: u32,
246    value: &'a str,
247  },
248  Float {
249    value: &'a str,
250  },
251  Fraction {
252    positive: bool,
253    numerator: &'a str,
254    denominator: &'a str,
255  },
256}
257
258/// Number class as recognized by Clojure
259#[derive(Clone, Copy, Debug)]
260pub enum NumberClass {
261  Long,
262  Double,
263  BigInt,
264  BigDecimal,
265  Ratio,
266}
267
268#[derive(Clone, Copy, Debug)]
269pub enum StringFragment<'a> {
270  Unescaped { value: &'a str },
271  Escaped { code: u32 },
272}
273
274type Lexemes<'a> = Vec<Lexeme<'a>>;
275
276#[allow(clippy::result_large_err)]
277pub fn lex(input: &str) -> Result<Lexemes, Error> {
278  let mut helper = Helper::default();
279  let mut pairs = Grammar::parse(R::top_level, input)?;
280  let Some(top_level_pair) = pairs.next() else {
281    panic!("at least one top-level");
282  };
283  if pairs.next().is_some() {
284    panic!("at most one top-level");
285  }
286  helper.top_level(top_level_pair);
287  Ok(helper.into_lexemes())
288}
289
290#[derive(Debug, Default)]
291struct Helper<'a> {
292  form_count: u32,
293  lexemes: Lexemes<'a>,
294}
295
296impl<'a> Helper<'a> {
297  fn push(&mut self, lexeme: Lexeme<'a>) {
298    self.lexemes.push(lexeme)
299  }
300
301  fn into_lexemes(mut self) -> Lexemes<'a> {
302    self.lexemes.shrink_to_fit();
303    self.lexemes
304  }
305
306  fn next_form_ix(&mut self, parent: Option<FormIx>) -> FormIx {
307    self.form_count += 1;
308    parent
309      .map(|p| p.child(self.form_count))
310      .unwrap_or_else(|| FormIx::root(self.form_count))
311  }
312
313  fn whitespace(&mut self, pair: Pair<'a>) {
314    self.push(L::Whitespace {
315      source: pair.as_str(),
316    });
317  }
318
319  fn comment(&mut self, pair: Pair<'a>) {
320    self.push(L::Comment {
321      source: pair.as_str(),
322    });
323  }
324
325  fn top_level(&mut self, parent: Pair<'a>) {
326    for child in parent.into_inner() {
327      match child.as_rule() {
328        R::COMMENT => self.comment(child),
329        R::WHITESPACE => self.whitespace(child),
330        R::form => {
331          let current = self.next_form_ix(None);
332          self.form(child, current);
333        }
334        R::EOI => (),
335        _ => self.push(L::Residual(child)),
336      }
337    }
338  }
339
340  fn form(&mut self, parent: Pair<'a>, current: FormIx) {
341    for child in parent.into_inner() {
342      match child.as_rule() {
343        R::COMMENT => self.comment(child),
344        R::WHITESPACE => self.whitespace(child),
345        R::quote_unquote_form => self.quote_unquote_form(child, current),
346        R::preform => self.preforms(child, current),
347        R::form => self.form(child, current),
348        R::expr => self.expr(child, current),
349        _ => self.push(L::Residual(child)),
350      }
351    }
352  }
353
354  fn quote_unquote_form(&mut self, parent: Pair<'a>, parent_ix: FormIx) {
355    let child_ix = self.next_form_ix(Some(parent_ix));
356    for child in parent.into_inner() {
357      match child.as_rule() {
358        R::COMMENT => self.comment(child),
359        R::WHITESPACE => self.whitespace(child),
360        R::quote_unquote_prefix => self.push(match child.as_str() {
361          "'" => L::Quote {
362            form_ix: parent_ix,
363            source: child.as_str(),
364          },
365          "#'" => L::VarQuote {
366            form_ix: parent_ix,
367            source: child.as_str(),
368          },
369          "`" => L::Synquote {
370            form_ix: parent_ix,
371            source: child.as_str(),
372          },
373          "~@" => L::SplicingUnquote {
374            form_ix: parent_ix,
375            source: child.as_str(),
376          },
377          "~" => L::Unquote {
378            form_ix: parent_ix,
379            source: child.as_str(),
380          },
381          _ => unreachable!("quote-unquote prefix case analysis"),
382        }),
383        R::form => self.form(child, child_ix),
384        _ => self.push(L::Residual(child)),
385      }
386    }
387  }
388
389  fn preforms(&mut self, parent: Pair<'a>, current: FormIx) {
390    for child in parent.into_inner() {
391      match child.as_rule() {
392        R::COMMENT => self.comment(child),
393        R::WHITESPACE => self.whitespace(child),
394        R::discarded_form => self.discarded_form(child),
395        R::meta_form => self.meta_form(child, current),
396        _ => self.push(L::Residual(child)),
397      }
398    }
399  }
400
401  fn discarded_form(&mut self, parent: Pair<'a>) {
402    let form_ix = self.next_form_ix(None);
403    for child in parent.into_inner() {
404      match child.as_rule() {
405        R::COMMENT => self.comment(child),
406        R::WHITESPACE => self.whitespace(child),
407        R::discard_prefix => self.push(L::Discard {
408          form_ix,
409          source: child.as_str(),
410        }),
411        R::preform => self.preforms(child, form_ix),
412        R::form => self.form(child, form_ix),
413        _ => self.push(L::Residual(child)),
414      }
415    }
416  }
417
418  fn meta_form(&mut self, parent: Pair<'a>, form_ix: FormIx) {
419    let data_ix = self.next_form_ix(None);
420    for child in parent.into_inner() {
421      match child.as_rule() {
422        R::COMMENT => self.comment(child),
423        R::WHITESPACE => self.whitespace(child),
424        R::meta_prefix => self.push(L::Meta {
425          form_ix,
426          data_ix,
427          source: child.as_str(),
428        }),
429        R::form => self.form(child, data_ix),
430        _ => self.push(L::Residual(child)),
431      }
432    }
433  }
434
435  fn expr(&mut self, parent: Pair<'a>, form_ix: FormIx) {
436    for child in parent.into_inner() {
437      match child.as_rule() {
438        R::COMMENT => self.comment(child),
439        R::WHITESPACE => self.whitespace(child),
440        R::nil => self.push(L::Nil {
441          form_ix,
442          source: child.as_str(),
443        }),
444        R::boolean => self.push(L::Boolean {
445          form_ix,
446          value: child.as_str() == "true",
447          source: child.as_str(),
448        }),
449        R::number => self.number(child, form_ix),
450        R::char => self.char(child, form_ix),
451        R::string => self.string(child, form_ix),
452        R::regex => self.regex(child, form_ix),
453        R::symbolic_value => self.symbolic_value(child, form_ix),
454        R::symbol => self.symbol(child, form_ix),
455        R::keyword => self.keyword(child, form_ix),
456        R::list => self.list(child, form_ix),
457        R::vector => self.vector(child, form_ix),
458        R::anonymous_fn => self.anonymous_fn(child, form_ix),
459        R::set => self.set(child, form_ix),
460        R::map => self.map(child, form_ix),
461        R::reader_conditional => self.reader_conditional(child, form_ix),
462        R::tagged_literal => self.tagged_literal(child, form_ix),
463        _ => self.push(L::Residual(child)),
464      }
465    }
466  }
467
468  fn char(&mut self, parent: Pair<'a>, form_ix: FormIx) {
469    let source = parent.as_str();
470    for child in parent.into_inner() {
471      match child.as_rule() {
472        R::char_name => self.push(L::Char {
473          form_ix,
474          syntax: CharSyntax::Name,
475          value: match child.as_str() {
476            "newline" => '\n',
477            "space" => ' ',
478            "tab" => '\t',
479            "formfeed" => '\u{0C}',
480            "backspace" => '\u{08}',
481            _ => unreachable!("char name case analysis"),
482          },
483          source,
484        }),
485        R::char_octal => self.push(L::Char {
486          form_ix,
487          syntax: CharSyntax::Octal,
488          value: char::from_u32(
489            u32::from_str_radix(child.as_str(), 8).unwrap(),
490          )
491          .unwrap(),
492          source,
493        }),
494        R::char_code_point => self.push(L::Char {
495          form_ix,
496          syntax: CharSyntax::CodePoint,
497          value: char::from_u32(
498            u32::from_str_radix(child.as_str(), 16).unwrap(),
499          )
500          .unwrap(),
501          source,
502        }),
503        _ => self.push(L::Residual(child)),
504      }
505    }
506  }
507
508  fn number(&mut self, parent: Pair<'a>, form_ix: FormIx) {
509    let mut positive = true;
510    let literal = parent.as_str();
511    for child in parent.into_inner() {
512      match child.as_rule() {
513        R::sign => positive = child.as_str() == "+",
514        R::unsigned_bigfloat => {
515          self.unsigned_floats(child, form_ix, literal, true)
516        }
517        R::unsigned_float => {
518          self.unsigned_floats(child, form_ix, literal, false)
519        }
520        R::unsigned_ratio => {
521          self.unsigned_ratio(child, form_ix, literal, positive)
522        }
523        R::unsigned_radix_int => {
524          self.unsigned_radix_int(child, form_ix, literal, positive)
525        }
526        R::unsigned_int => self.unsigned_int(child, form_ix, literal, positive),
527        _ => self.push(L::Residual(child)),
528      }
529    }
530  }
531
532  fn unsigned_floats(
533    &mut self,
534    _parent: Pair<'a>,
535    form_ix: FormIx,
536    literal: &'a str,
537    big: bool,
538  ) {
539    self.push(if big {
540      L::Numeric {
541        form_ix,
542        class: NumberClass::BigDecimal,
543        value: NumericValue::Float {
544          value: &literal[..literal.len() - 1],
545        },
546        source: literal,
547      }
548    } else {
549      L::Numeric {
550        form_ix,
551        class: NumberClass::Double,
552        value: NumericValue::Float { value: literal },
553        source: literal,
554      }
555    })
556  }
557
558  fn unsigned_ratio(
559    &mut self,
560    parent: Pair<'a>,
561
562    form_ix: FormIx,
563    literal: &'a str,
564    positive: bool,
565  ) {
566    let mut numerator = None;
567    let mut denominator = None;
568    for child in parent.into_inner() {
569      match child.as_rule() {
570        R::numerator => numerator = Some(child.as_str()),
571        R::denominator => denominator = Some(child.as_str()),
572        _ => self.push(L::Residual(child)),
573      }
574    }
575    self.push(L::Numeric {
576      form_ix,
577      source: literal,
578      class: NumberClass::Ratio,
579      value: NumericValue::Fraction {
580        positive,
581        numerator: numerator.unwrap(),
582        denominator: denominator.unwrap(),
583      },
584    })
585  }
586  fn unsigned_radix_int(
587    &mut self,
588    parent: Pair<'a>,
589
590    form_ix: FormIx,
591    literal: &'a str,
592    positive: bool,
593  ) {
594    let mut radix = None;
595    for child in parent.into_inner() {
596      match child.as_rule() {
597        R::radix => radix = Some(child.as_str()),
598        R::radix_digits => self.push(L::Numeric {
599          form_ix,
600          source: literal,
601          class: NumberClass::Long,
602          value: NumericValue::Int {
603            positive,
604            radix: radix.unwrap().parse::<u32>().unwrap(),
605            value: child.as_str(),
606          },
607        }),
608        _ => self.push(L::Residual(child)),
609      }
610    }
611  }
612
613  fn unsigned_int(
614    &mut self,
615    parent: Pair<'a>,
616    form_ix: FormIx,
617    literal: &'a str,
618    positive: bool,
619  ) {
620    let mut class = NumberClass::Long;
621    let mut value = None;
622    for child in parent.into_inner() {
623      match child.as_rule() {
624        R::oct_digits => {
625          value = Some(NumericValue::Int {
626            positive,
627            radix: 8,
628            value: child.as_str(),
629          })
630        }
631        R::hex_digits => {
632          value = Some(NumericValue::Int {
633            positive,
634            radix: 16,
635            value: child.as_str(),
636          })
637        }
638        R::unsigned_dec => {
639          value = Some(NumericValue::Int {
640            positive,
641            radix: 10,
642            value: child.as_str(),
643          })
644        }
645        R::bigint_suffix => class = NumberClass::BigInt,
646        _ => self.push(L::Residual(child)),
647      }
648    }
649    self.push(L::Numeric {
650      form_ix,
651      source: literal,
652      class,
653      value: value.unwrap(),
654    })
655  }
656
657  fn string(&mut self, parent: Pair<'a>, form_ix: FormIx) {
658    let mut fragments = Vec::new();
659    let literal = parent.as_str();
660    for child in parent.into_inner() {
661      match child.as_rule() {
662        R::unescaped => fragments.push(StringFragment::Unescaped {
663          value: child.as_str(),
664        }),
665        R::esc_char => {
666          let value = &child.as_str()[1..];
667          let code = match value {
668            "b" => 0x08,
669            "t" => 0x09,
670            "n" => 0x0A,
671            "f" => 0x0C,
672            "r" => 0x0D,
673            "\"" => 0x22,
674            "\\" => 0x5C,
675            e => unreachable!("inexhaustive: {}", e),
676          };
677          fragments.push(StringFragment::Escaped { code })
678        }
679        R::esc_octet => {
680          let value = &child.as_str()[1..];
681          let code = u32::from_str_radix(value, 8).unwrap();
682          fragments.push(StringFragment::Escaped { code })
683        }
684        R::esc_code_point => {
685          let value = &child.as_str()[2..];
686          let code = u32::from_str_radix(value, 16).unwrap();
687          fragments.push(StringFragment::Escaped { code })
688        }
689        _ => self.push(L::Residual(child)),
690      }
691    }
692    fragments.shrink_to_fit();
693    self.push(L::String {
694      form_ix,
695      source: literal,
696      value: fragments.into_boxed_slice(),
697    });
698  }
699
700  fn regex(&mut self, parent: Pair<'a>, form_ix: FormIx) {
701    for child in parent.into_inner() {
702      match child.as_rule() {
703        R::regex_content => self.push(L::Regex {
704          form_ix,
705          source: child.as_str(),
706        }),
707        _ => self.push(L::Residual(child)),
708      }
709    }
710  }
711
712  fn symbolic_value(&mut self, parent: Pair<'a>, form_ix: FormIx) {
713    for child in parent.into_inner() {
714      match child.as_rule() {
715        R::COMMENT => self.comment(child),
716        R::WHITESPACE => self.whitespace(child),
717        R::symbolic_value_prefix => self.push(L::SymbolicValuePrefix {
718          form_ix,
719          source: child.as_str(),
720        }),
721        R::unqualified_symbol => self.push(L::SymbolicValue {
722          form_ix,
723          value: match child.as_str() {
724            "Inf" => SymbolicValue::PosInf,
725            "-Inf" => SymbolicValue::NegInf,
726            "NaN" => SymbolicValue::NaN,
727            _ => SymbolicValue::Other(child.as_str()),
728          },
729          source: child.as_str(),
730        }),
731        _ => self.push(L::Residual(child)),
732      }
733    }
734  }
735
736  fn symbol(&mut self, parent: Pair<'a>, form_ix: FormIx) {
737    let source = parent.as_str();
738    let mut namespace = None;
739    for child in parent.into_inner() {
740      match child.as_rule() {
741        R::namespace => namespace = Some(child.as_str()),
742        R::qualified_symbol | R::unqualified_symbol => self.push(L::Symbol {
743          form_ix,
744          namespace,
745          name: child.as_str(),
746          source,
747        }),
748        _ => self.push(L::Residual(child)),
749      }
750    }
751  }
752
753  fn tag(&mut self, parent: Pair<'a>, form_ix: FormIx) {
754    let source = parent.as_str();
755    let mut namespace = None;
756    for child in parent.into_inner() {
757      match child.as_rule() {
758        R::namespace => namespace = Some(child.as_str()),
759        R::qualified_symbol | R::unqualified_symbol => self.push(L::Tag {
760          form_ix,
761          namespace,
762          name: child.as_str(),
763          source,
764        }),
765        _ => self.push(L::Residual(child)),
766      }
767    }
768  }
769
770  fn keyword(&mut self, parent: Pair<'a>, form_ix: FormIx) {
771    let source = parent.as_str();
772    let mut namespace = None;
773    let mut alias = false;
774    for child in parent.into_inner() {
775      match child.as_rule() {
776        R::keyword_prefix => alias = child.as_str() == "::",
777        R::namespace => namespace = Some(child.as_str()),
778        R::qualified_symbol | R::unqualified_keyword => self.push(L::Keyword {
779          form_ix,
780          alias,
781          namespace,
782          name: child.as_str(),
783          source,
784        }),
785        _ => self.push(L::Residual(child)),
786      }
787    }
788  }
789
790  fn list(&mut self, parent: Pair<'a>, parent_ix: FormIx) {
791    let source = parent.as_str();
792    self.body(
793      parent,
794      parent_ix,
795      L::StartList {
796        form_ix: parent_ix,
797        source: &source[..1],
798      },
799      L::EndList {
800        form_ix: parent_ix,
801        source: &source[source.len() - 1..],
802      },
803    );
804  }
805
806  fn vector(&mut self, parent: Pair<'a>, parent_ix: FormIx) {
807    let source = parent.as_str();
808    self.body(
809      parent,
810      parent_ix,
811      L::StartVector {
812        form_ix: parent_ix,
813        source: &source[..1],
814      },
815      L::EndVector {
816        form_ix: parent_ix,
817        source: &source[source.len() - 1..],
818      },
819    );
820  }
821
822  fn anonymous_fn(&mut self, parent: Pair<'a>, parent_ix: FormIx) {
823    let source = parent.as_str();
824    self.body(
825      parent,
826      parent_ix,
827      L::StartAnonymousFn {
828        form_ix: parent_ix,
829        source: &source[..2],
830      },
831      L::EndAnonymousFn {
832        form_ix: parent_ix,
833        source: &source[source.len() - 1..],
834      },
835    );
836  }
837
838  fn set(&mut self, parent: Pair<'a>, parent_ix: FormIx) {
839    let source = parent.as_str();
840    self.body(
841      parent,
842      parent_ix,
843      L::StartSet {
844        form_ix: parent_ix,
845        source: &source[..2],
846      },
847      L::EndSet {
848        form_ix: parent_ix,
849        source: &source[source.len() - 1..],
850      },
851    );
852  }
853
854  fn map(&mut self, parent: Pair<'a>, form_ix: FormIx) {
855    let mut alias = false;
856    let mut namespace = None;
857    for child in parent.into_inner() {
858      match child.as_rule() {
859        R::COMMENT => self.comment(child),
860        R::WHITESPACE => self.whitespace(child),
861        R::map_qualifier => {
862          self.push(L::MapQualifier {
863            form_ix,
864            source: child.as_str(),
865          });
866          for child2 in child.into_inner() {
867            match child2.as_rule() {
868              R::map_qualifier_prefix => alias = child2.as_str() == "#::",
869              R::namespace => namespace = Some(child2.as_str()),
870              _ => self.push(L::Residual(child2)),
871            }
872          }
873        }
874        R::unqualified_map => {
875          let source = child.as_str();
876          self.body(
877            child,
878            form_ix,
879            L::StartMap {
880              form_ix,
881              alias,
882              namespace,
883              source: &source[..1],
884            },
885            L::EndMap {
886              form_ix,
887              source: &source[source.len() - 1..],
888            },
889          )
890        }
891        R::discarded_form => self.discarded_form(child),
892        _ => self.push(L::Residual(child)),
893      }
894    }
895  }
896
897  fn reader_conditional(&mut self, parent: Pair<'a>, form_ix: FormIx) {
898    let mut splicing = false;
899    for child in parent.into_inner() {
900      match child.as_rule() {
901        R::COMMENT => self.comment(child),
902        R::WHITESPACE => self.whitespace(child),
903        R::reader_conditional_prefix => splicing = child.as_str() == "#?@",
904        R::reader_conditional_body => {
905          let source = child.as_str();
906          self.body(
907            child,
908            form_ix,
909            L::StartReaderConditional {
910              form_ix,
911              splicing,
912              source: &source[1..],
913            },
914            L::EndReaderConditional {
915              form_ix,
916              source: &source[source.len() - 1..],
917            },
918          )
919        }
920        R::discarded_form => self.discarded_form(child),
921        _ => self.push(L::Residual(child)),
922      }
923    }
924  }
925
926  fn body(
927    &mut self,
928    parent: Pair<'a>,
929    parent_ix: FormIx,
930    start_lexeme: Lexeme<'a>,
931    end_lexeme: Lexeme<'a>,
932  ) {
933    self.push(start_lexeme);
934    for child in parent.into_inner() {
935      match child.as_rule() {
936        R::COMMENT => self.comment(child),
937        R::WHITESPACE => self.whitespace(child),
938        R::form => {
939          let child_ix = self.next_form_ix(Some(parent_ix));
940          self.form(child, child_ix)
941        }
942        R::discarded_form => self.discarded_form(child),
943        _ => self.push(L::Residual(child)),
944      }
945    }
946    self.push(end_lexeme);
947  }
948
949  fn tagged_literal(&mut self, parent: Pair<'a>, form_ix: FormIx) {
950    let tag_ix = self.next_form_ix(Some(form_ix));
951    let arg_ix = self.next_form_ix(Some(form_ix));
952    self.push(L::TaggedLiteral {
953      form_ix,
954      tag_ix,
955      arg_ix,
956      // XXX(soija) Aw, this is a hack.  We want to capture only the prefix as
957      //            the rest of the tagged literal is captured be the following
958      //            lexemes.
959      source: &parent.as_str()[..1],
960    });
961    for child in parent.into_inner() {
962      match child.as_rule() {
963        R::COMMENT => self.comment(child),
964        R::WHITESPACE => self.whitespace(child),
965        R::tagged_literal_tag => {
966          for child2 in child.into_inner() {
967            match child2.as_rule() {
968              R::COMMENT => self.comment(child2),
969              R::WHITESPACE => self.whitespace(child2),
970              R::preform => self.preforms(child2, tag_ix),
971              R::symbol => self.tag(child2, tag_ix),
972              _ => self.push(L::Residual(child2)),
973            }
974          }
975        }
976        R::form => self.form(child, arg_ix),
977        _ => self.push(L::Residual(child)),
978      }
979    }
980  }
981}