]> Witch of Git - ess/blob - src/sexp.rs
Add a module description line to Sexp
[ess] / src / sexp.rs
1 //! The `Sexp` type, the representation of s-expressions.
2
3 use std::borrow::Cow;
4
5 use span::{Span, ByteSpan};
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> where Loc: Span {
13 /// A value representing a symbol.
14 Sym(Cow<'a, str>, Loc),
15 /// A value representing a string literal.
16 Str(Cow<'a, str>, Loc),
17 /// A value representing a single character.
18 Char(char, Loc),
19 /// A value representing an integer. Any number containing no decimal point
20 /// will be parsed as an `Int`.
21 Int(i64, Loc),
22 /// A value representing a floating point number. Any number containing a
23 /// decimal point will be parsed as a `Float`.
24 Float(f64, Loc),
25 /// A list of subexpressions.
26 List(Vec<Sexp<'a, Loc>>, Loc),
27 }
28
29 impl<'a, Loc> Sexp<'a, Loc> where Loc: Span {
30 /// Gives a reference to the source location contained in the `Sexp`.
31 pub fn get_loc(&self) -> &Loc {
32 match *self {
33 Sexp::Sym(.., ref l) | Sexp::Str(.., ref l) |
34 Sexp::Char(.., ref l) | Sexp::Int(.., ref l) |
35 Sexp::Float(.., ref l) | Sexp::List(.., ref l) => l,
36 }
37 }
38
39 /// Gives a mutable reference to the `Sexp`'s source location.
40 pub fn get_loc_mut(&mut self) -> &mut Loc {
41 match *self {
42 Sexp::Sym(.., ref mut l) | Sexp::Str(.., ref mut l) |
43 Sexp::Char(.., ref mut l) | Sexp::Int(.., ref mut l) |
44 Sexp::Float(.., ref mut l) | Sexp::List(.., ref mut l) => l,
45 }
46 }
47 }
48
49 fn extend_cow<'a, T: ?Sized>(cow: &Cow<'a, T>) -> Cow<'static, T>
50 where T: ToOwned
51 {
52 Cow::Owned(cow.clone().into_owned())
53 }
54
55 impl<'a, Loc> Sexp<'a, Loc> where Loc: Span + Clone {
56 /// Take ownership of an s-expression's contents.
57 pub fn to_owned(&self) -> Sexp<'static, Loc> {
58 match *self {
59 Sexp::Sym(ref s, ref l) => Sexp::Sym(extend_cow(s), l.clone()),
60 Sexp::Str(ref s, ref l) => Sexp::Str(extend_cow(s), l.clone()),
61 Sexp::Char(c, ref l) => Sexp::Char(c, l.clone()),
62 Sexp::Int(i, ref l) => Sexp::Int(i, l.clone()),
63 Sexp::Float(f, ref l) => Sexp::Float(f, l.clone()),
64 Sexp::List(ref xs, ref l) =>
65 Sexp::List(xs.iter().map(Sexp::to_owned).collect(),
66 l.clone()),
67 }
68 }
69 }