ralix 0.2.0

A simple, type-safe, tree walking interpreter
use std::{
    fmt::{Debug, Display},
    rc::Rc,
};

pub type Literal = Rc<str>;

#[derive(Debug, PartialEq, Default, Clone)]
pub enum Token {
    #[default]
    Unknown,
    Illegal(Literal),
    Ident(Literal),
    #[allow(clippy::upper_case_acronyms)]
    EOF,
    /// "\n"
    NewLine,
    /// "->"
    ThinArrow,
    /// "=>"
    FatArrow,

    /// Example: "hello world", "uwu :3", "meow \nowo"
    String(Literal),
    /// Example: 'a', '1', '\n'
    Char(Literal),
    /// Example: 2, 3, 5, 7, 10, 0
    Int(Literal),
    /// Example: 3.141, 20.20, NaN, 0.0
    Float(Literal),

    /// "="
    Assign,
    /// "!"
    Bang,
    /// "|"
    Pipe,
    /// "&"
    Ampersant,
    /// "#"
    Hash,
    /// "@"
    AtSign,
    /// ?
    QuestionMark,
    /// ^
    Caret,
    /// ~
    Tilde,
    /// >>
    ShiftRight,
    /// <<
    ShiftLeft,

    /// "=="
    Equal,
    /// "!="
    NotEqual,

    /// "+"
    Plus,
    /// "-"
    Minus,
    /// "/"
    Slash,
    /// "*"
    Asterisk,
    /// "%"
    Percent,

    /// "++"
    Increase,
    /// "--"
    Decrease,

    /// "<"
    LessThan,
    /// ">"
    GreaterThan,
    /// "<="
    LessEqual,
    /// ">="
    GreatEqual,

    /// ","
    Comma,
    /// "."
    Dot,
    /// ".."
    TwoDots,
    /// ";"
    SemiColon,
    /// ":"
    Colon,
    /// "("
    LParen,
    /// ")"
    RParen,
    /// "{"
    LBrace,
    /// "}"
    RBrace,
    /// "["
    LBracket,
    /// "]"
    RBracket,
    /// "::"
    Namespace,

    // # Keywords
    Null,
    If,
    Else,
    Function,
    Const,
    Return,
    True,
    False,
    While,
    For,
    Continue,
    Break,
    Match,
    Struct,
    Interface,
    Out,
    Get,
    As,
    Not,
    And,
    Or,
    Type,
    TypeOf,
    Let,

    // Type Keywords
    /// "int"
    TyInt,
    /// "float"
    TyFloat,
    /// "str"
    TyString,
    /// "char"
    TyChar,
    /// "bool"
    TyBool,
    /// "arr[<type>]"
    TyArr,
    /// "map[<type>]"
    TyMap,
}
impl Token {
    pub fn keyword(keyword: &str) -> Token {
        match keyword {
            "null" => Token::Null,
            "fn" => Token::Function,
            "true" => Token::True,
            "false" => Token::False,
            "if" => Token::If,
            "else" => Token::Else,
            "const" => Token::Const,
            "while" => Token::While,
            "for" => Token::For,
            "return" => Token::Return,
            "continue" => Token::Continue,
            "break" => Token::Break,
            "match" => Token::Match,
            "struct" => Token::Struct,
            "interface" => Token::Interface,
            "get" => Token::Get,
            "as" => Token::As,
            "out" => Token::Out,
            "and" => Token::And,
            "or" => Token::Or,
            "not" => Token::Not,
            "int" => Token::TyInt,
            "float" => Token::TyFloat,
            "str" => Token::TyString,
            "char" => Token::TyChar,
            "bool" => Token::TyBool,
            "type" => Token::Type,
            "typeof" => Token::TypeOf,
            "map" => Token::TyMap,
            "arr" => Token::TyArr,
            "let" => Token::Let,
            lit => Token::Ident(Literal::from(lit)),
        }
    }

    pub fn literal(&self) -> Literal {
        use Token as T;
        match self {
            T::Ident(lit) => lit.clone(),
            T::Illegal(lit) => lit.clone(),
            T::String(lit) => lit.clone(),
            T::Char(lit) => lit.clone(),
            T::Int(lit) => lit.clone(),
            T::Float(lit) => lit.clone(),
            T::True => Literal::from("true"),
            T::False => Literal::from("false"),
            t => Literal::from(t.to_string()),
        }
        .clone()
    }
}
impl Display for Token {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        use Token as T;
        f.write_str(match self {
            T::Ident(_) => "identifier",
            T::Illegal(lit) => lit,
            T::Unknown => "unknown",
            T::EOF => "EOF",
            T::TyInt | T::Int(_) => "int",
            T::TyFloat | T::Float(_) => "float",
            T::TyBool | T::True | T::False => "bool",
            T::TyChar | T::Char(_) => "char",
            T::TyString | T::String(_) => "str",

            T::ThinArrow => "->",
            T::FatArrow => "=>",

            T::NewLine => "\n",
            T::Assign => "=",
            T::Bang => "!",
            T::Pipe => "|",
            T::Ampersant => "&",
            T::Hash => "#",
            T::AtSign => "@",
            T::QuestionMark => "?",
            T::Caret => "^",
            T::Tilde => "~",

            T::Equal => "==",
            T::NotEqual => "!=",
            T::Plus => "+",
            T::Minus => "-",
            T::Slash => "/",
            T::Percent => "%",
            T::ShiftRight => ">>",
            T::ShiftLeft => "<<",

            T::Asterisk => "*",
            T::Increase => "++",
            T::Decrease => "--",
            T::LessThan => "<",
            T::GreaterThan => ">",
            T::LessEqual => "<=",
            T::GreatEqual => ">=",
            T::Comma => ",",
            T::Dot => ".",
            T::TwoDots => "..",
            T::SemiColon => ";",
            T::Colon => ":",
            T::LParen => "(",
            T::RParen => ")",
            T::LBrace => "{",
            T::RBrace => "}",
            T::LBracket => "[",
            T::RBracket => "]",
            T::Namespace => "::",

            T::Null => "null",
            T::If => "if",
            T::Else => "else",
            T::Function => "fn",
            T::Const => "const",
            T::Return => "return",
            T::While => "while",
            T::For => "for",
            T::Continue => "continue",
            T::Break => "break",
            T::Match => "match",
            T::Struct => "struct",
            T::Interface => "interface",
            T::Out => "out",
            T::Get => "get",
            T::As => "as",
            T::Not => "not",
            T::And => "and",
            T::Or => "or",
            T::Type => "type",
            T::TypeOf => "typeof",
            T::TyArr => "arr",
            T::TyMap => "map",
            T::Let => "let",
        })
    }
}