]> Witch of Git - ess/blob - src/sexp.rs
Split the project into multiple modules
[ess] / src / sexp.rs
1 use std::borrow::Cow;
2
3 use span::{Span, ByteSpan};
4
5 /// A type representing arbitrary symbolic expressions. `Sexp` carries the
6 /// source code location it came from along with it for later diagnostic
7 /// purposes.
8 #[derive(Debug, PartialEq, Clone, PartialOrd)]
9 pub enum Sexp<'a, Loc=ByteSpan> where Loc: Span {
10 /// A value representing a symbol.
11 Sym(Cow<'a, str>, Loc),
12 /// A value representing a string literal.
13 Str(Cow<'a, str>, Loc),
14 /// A value representing a single character.
15 Char(char, Loc),
16 /// A value representing an integer. Any number containing no decimal point
17 /// will be parsed as an `Int`.
18 Int(i64, Loc),
19 /// A value representing a floating point number. Any number containing a
20 /// decimal point will be parsed as a `Float`.
21 Float(f64, Loc),
22 /// A list of subexpressions.
23 List(Vec<Sexp<'a, Loc>>, Loc),
24 }
25
26 impl<'a, Loc> Sexp<'a, Loc> where Loc: Span {
27 pub fn get_loc(&self) -> &Loc {
28 match *self {
29 Sexp::Sym(.., ref l) | Sexp::Str(.., ref l) |
30 Sexp::Char(.., ref l) | Sexp::Int(.., ref l) |
31 Sexp::Float(.., ref l) | Sexp::List(.., ref l) => l,
32 }
33 }
34
35 pub fn get_loc_mut(&mut self) -> &mut Loc {
36 match *self {
37 Sexp::Sym(.., ref mut l) | Sexp::Str(.., ref mut l) |
38 Sexp::Char(.., ref mut l) | Sexp::Int(.., ref mut l) |
39 Sexp::Float(.., ref mut l) | Sexp::List(.., ref mut l) => l,
40 }
41 }
42 }
43
44 fn extend_cow<'a, T: ?Sized>(cow: &Cow<'a, T>) -> Cow<'static, T>
45 where T: ToOwned
46 {
47 Cow::Owned(cow.clone().into_owned())
48 }
49
50 impl<'a, Loc> Sexp<'a, Loc> where Loc: Span + Clone {
51 pub fn to_owned(&self) -> Sexp<'static, Loc> {
52 match *self {
53 Sexp::Sym(ref s, ref l) => Sexp::Sym(extend_cow(s), l.clone()),
54 Sexp::Str(ref s, ref l) => Sexp::Str(extend_cow(s), l.clone()),
55 Sexp::Char(c, ref l) => Sexp::Char(c, l.clone()),
56 Sexp::Int(i, ref l) => Sexp::Int(i, l.clone()),
57 Sexp::Float(f, ref l) => Sexp::Float(f, l.clone()),
58 Sexp::List(ref xs, ref l) =>
59 Sexp::List(xs.iter().map(Sexp::to_owned).collect(),
60 l.clone()),
61 }
62 }
63 }