token-lists 0.3.0

A simple token list representation
Documentation
#![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, Eq)]
pub enum Token {
    /// A symbol token represented by its name.
    Symbol(Box<str>),
    /// A list token containing other tokens.
    List(Vec<Self>),
}

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<Box<str>> {
        match self {
            Symbol(string) => Some(string),
            List(_) => None,
        }
    }

    /// Same as `fn symbol`, but returns a ref.
    pub fn symbol_ref(&self) -> Option<&str> {
        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<Self>> {
        match self {
            Symbol(_) => None,
            List(tokens) => Some(tokens),
        }
    }

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

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

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

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

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

impl<T: Into<Self>> From<Vec<T>> for Token {
    fn from(list: Vec<T>) -> Self {
        List(list.into_iter().map(T::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 {
                Self::Symbol(string) => write!(f, "{string:?}"),
                Self::List(vec) => {
                    let mut first = true;
                    write!(f, "(")?;
                    for tok in vec {
                        if first {
                            first = false;
                        } else {
                            write!(f, " ")?;
                        }
                        write!(f, "{tok}")?;
                    }
                    write!(f, ")")
                }
            }
        }
    }
}

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