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
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::*;
use std::rc::Rc;

/// Parses a 'word', which is anything that starts with an upper or lowercase ASCII
/// character (a-z, A-Z) and ends in a space or one of the following characters: `()[]{}\;`
impl Sexpy for String {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        let chars = " ()[]{}\\;\n\t\r";
        let (next, (s, s1)) = tuple((alpha1, many0(none_of(chars))))(input)?;
        Ok((next, format!("{}{}", s, s1.into_iter().collect::<String>())))
    }
}

/// Parses unsigned 64 bit integers
impl Sexpy for u64 {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        let (next, digits) = digit1(input)?;
        match digits.parse::<u64>() {
            Ok(num) => Ok((next, num)),
            Err(_) => Err(Err::Error(SexpyError::number(input))),
        }
    }
}

/// Parses unsigned 32 bit integers
impl Sexpy for u32 {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        let (next, digits) = digit1(input)?;
        match digits.parse::<u32>() {
            Ok(num) => Ok((next, num)),
            Err(_) => Err(Err::Error(SexpyError::number(input))),
        }
    }
}

/// Parses signed 64 bit integers
impl Sexpy for i64 {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        let (next, (neg, digits)) = tuple((opt(char('-')), digit1))(input)?;
        match digits.parse::<i64>() {
            Ok(num) => {
                if neg.is_some() {
                    Ok((next, -num))
                } else {
                    Ok((next, num))
                }
            }
            Err(_) => Err(Err::Error(SexpyError::number(input))),
        }
    }
}

/// Parses signed 32 bit integers
impl Sexpy for i32 {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        let (next, (neg, digits)) = tuple((opt(char('-')), digit1))(input)?;
        match digits.parse::<i32>() {
            Ok(num) => {
                if neg.is_some() {
                    Ok((next, -num))
                } else {
                    Ok((next, num))
                }
            }
            Err(_) => Err(Err::Error(SexpyError::number(input))),
        }
    }
}

/// Optionally parses `T`
impl<T: Sexpy> Sexpy for Option<T> {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        match opt(T::sexp_parse)(input) {
            Ok((next, res)) => Ok((next, res)),
            Err(_) => Ok((input, None)),
        }
    }
}

/// Parses 0 or more instances of `T` seperated by whitespace
impl<T: Sexpy> Sexpy for Vec<T> {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        let (next, res) = many0(preceded(wordbreak0, T::sexp_parse))(input)?;
        Ok((next, res))
    }
}

/// Just parses `T` but puts the result in a `Box<T>`
impl<T: Sexpy> Sexpy for Box<T> {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        let (next, res) = T::sexp_parse(input)?;
        Ok((next, Box::new(res)))
    }
}

/// Just parses `T` but puts the result in an `Rc<T>`
impl<T: Sexpy> Sexpy for Rc<T> {
    fn sexp_parse(input: &str) -> IResult<&str, Self, SexpyError<&str>>
    where
        Self: Sized,
    {
        let (next, res) = T::sexp_parse(input)?;
        Ok((next, Rc::new(res)))
    }
}