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
#![deny(missing_docs)]
/*!
This crate contains a minimal form of s-expressions, which will be called token lists.

Every element, called token, is either a symbol or a list of multiple tokens.

Other libraries like the token parser can be used to parse tokens.
**/

/// Represents the token lists.
#[derive(Clone, Debug, PartialEq)]
pub enum Token {
    /// A symbol token represented by its name.
    Symbol(String),
    /// A list token containing other tokens.
    List(Vec<Token>),
}

use Token::*;

impl Token {
    /// If the token is a `Symbol`, returns an `Option`, containing the symbol name.
    /// Else returns `None`.
    pub fn symbol(self) -> Option<String> {
        match self {
            Symbol(string) => Some(string),
            List(_) => None,
        }
    }

    /// Same as `fn symbol`, but returns a ref.
    pub fn symbol_ref(&self) -> Option<&String> {
        match self {
            Symbol(string) => Some(string),
            List(_) => None,
        }
    }

    /// If the token is a `List`, returns an `Option`, containing the elements.
    /// Else returns `None`.
    pub fn list(self) -> Option<Vec<Token>> {
        match self {
            Symbol(_) => None,
            List(tokens) => Some(tokens),
        }
    }

    /// Same as `fn list`, but returns a ref.
    pub fn list_ref(&self) -> Option<&Vec<Token>> {
        match self {
            Symbol(_) => None,
            List(tokens) => Some(tokens),
        }
    }
}

impl From<String> for Token {
    fn from(arg: String) -> Token {
        Symbol(arg)
    }
}

impl From<&str> for Token {
    fn from(arg: &str) -> Token {
        Symbol(arg.into())
    }
}

impl<T: Copy + Into<Token>> From<&T> for Token {
    fn from(arg: &T) -> Token {
        (*arg).into()
    }
}

impl<T: Into<Token>> From<Vec<T>> for Token {
    fn from(list: Vec<T>) -> Token {
        List(list.into_iter().map(|token| token.into()).collect())
    }
}

mod implement_display {
    use std::fmt::{Display, Formatter, Result};

    use crate::Token;

    impl Display for Token {
        fn fmt(&self, f: &mut Formatter) -> Result {
            match self {
                Token::Symbol(string) => write!(f, "'{}'", string),
                Token::List(vec) => {
                    let mut first = true;
                    write!(f, "(").expect("Unexpected end of file");
                    for tok in vec.iter() {
                        if !first {
                            write!(f, " ").expect("Unexpected end of file");
                        } else {
                            first = false;
                        }
                        let result = write!(f, "{}", tok);
                        if result.is_err() {
                            return result;
                        }
                    }
                    write!(f, ")")
                }
            }
        }
    }
}

#[cfg(feature = "parser")]
mod parser;