1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
use std::iter;
use crate::sexp::SExp;
use crate::sexp::SLeaf;
use crate::sexp::SExp::*;
use crate::sexp::SLeaf::*;
impl From<i32> for Box<SExp> {
fn from(int: i32) -> Self {
Box::new(Atom(Int(int)))
}
}
impl From<bool> for SExp {
fn from(bl: bool) -> Self {
Atom( if bl { True } else { False } )
}
}
impl From<SLeaf> for Box<SExp> {
fn from(leaf: SLeaf) -> Self {
Box::new(Atom(leaf))
}
}
impl From<i32> for SLeaf {
fn from(int: i32) -> Self {
Int(int)
}
}
pub fn scons(x: impl Into<Box<SExp>>, y: impl Into<Box<SExp>>) -> SExp {
SCons(x.into(), y.into())
}
pub fn var(name: &str) -> SExp {
Atom(Var(name.to_string()))
}
impl SExp {
/// Transforms this SExp into a Vec<SLeaf>.
///
/// Errors if the left-hand side of SCons has an SCons,
/// or if the passed SExp is an Atom, or if the
/// lists aren't Nil-terminated.
///
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
/// assert_eq!(
/// scons(1, scons(2, scons(3, Nil))).into_vec(),
/// Ok(vec![Int(1), Int(2), Int(3)])
/// );
/// assert!(scons(scons(1, Nil), Nil).into_vec().is_err());
/// assert!(scons(1, 2).into_vec().is_err());
/// ```
pub fn into_vec(self) -> Result<Vec<SLeaf>, String> {
match self {
SCons(a, b) => match (*a, *b) {
(Atom(a), Atom(Nil)) => Ok(iter::once(a).collect::<Vec<SLeaf>>()),
(Atom(a), b) => Ok(iter::once(a).chain(b.into_vec()?).collect::<Vec<SLeaf>>()),
(a, b) => Err(format!("invalid list structure: {:?}", scons(a, b)))
},
_ => Err("expected list, found atom".to_string()),
}
}
pub fn parts(self) -> Vec<SExp> {
match self {
Atom(x) => vec![Atom(x)],
SCons(a, b) if *b == Atom(Nil) => vec![*a],
SCons(a, b) => {
let mut res = vec![*a];
res.extend_from_slice(&(*b).parts());
res
},
}
}
}
|