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