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
use crate::TokenKind;
use crate::{Parameter, Statement};
use std::collections::HashMap;

#[derive(Debug, PartialEq)]
pub enum Expression {
    String(String),
    Number(f64),
    Bool(bool),
    Array(Vec<Expression>),
    Map(HashMap<String, Expression>),
    Identifier(String),
    Prefix(Op, Box<Expression>),
    Infix(Box<Expression>, Op, Box<Expression>),
    Call(Box<Expression>, Vec<Expression>),
    Assign(Box<Expression>, Box<Expression>),
    Index(Box<Expression>, Option<Box<Expression>>),
    Dot(Box<Expression>, Box<Expression>),
    Closure(Vec<Parameter>, Vec<Statement>),
}

impl Expression {
    pub fn boxed(self) -> Box<Self> {
        Box::new(self)
    }
}

/// The `Op` enumeration is used to represent prefix, infix and other operations.
#[derive(Debug, PartialEq, Clone)]
pub enum Op {
    Add,
    Subtract,
    Multiply,
    Divide,
    GreaterThan,
    LessThan,
    GreaterThanEquals,
    LessThanEquals,
    Equals,
    NotEquals,
    Assign,
    AddAssign,
    SubtractAssign,
    MultiplyAssign,
    DivideAssign,
    Not,
    And,
    Or,
    Mod,
}

impl From<TokenKind> for Op {
    fn from(kind: TokenKind) -> Self {
        match kind {
            TokenKind::Plus => Op::Add,
            TokenKind::Minus => Op::Subtract,
            TokenKind::Asterisk => Op::Multiply,
            TokenKind::Slash => Op::Divide,
            TokenKind::GreaterThan => Self::GreaterThan,
            TokenKind::LessThan => Self::LessThan,
            TokenKind::GreaterThanEquals => Self::GreaterThanEquals,
            TokenKind::LessThanEquals => Self::LessThanEquals,
            TokenKind::EqualsEquals => Self::Equals,
            TokenKind::NotEquals => Self::NotEquals,
            TokenKind::Equals => Self::Assign,
            TokenKind::Not => Self::Not,
            TokenKind::And => Self::And,
            TokenKind::Or => Self::Or,
            TokenKind::Percent => Self::Mod,
            TokenKind::PlusEquals => Self::AddAssign,
            TokenKind::MinusEquals => Self::SubtractAssign,
            TokenKind::AsteriskEquals => Self::MultiplyAssign,
            TokenKind::SlashEquals => Self::DivideAssign,
            _ => todo!()
        }
    }
}

impl From<&TokenKind> for Op {
    fn from(kind: &TokenKind) -> Self {
        match kind {
            TokenKind::Plus => Op::Add,
            TokenKind::Minus => Op::Subtract,
            TokenKind::Asterisk => Op::Multiply,
            TokenKind::Slash => Op::Divide,
            TokenKind::GreaterThan => Self::GreaterThan,
            TokenKind::LessThan => Self::LessThan,
            TokenKind::GreaterThanEquals => Self::GreaterThanEquals,
            TokenKind::LessThanEquals => Self::LessThanEquals,
            TokenKind::EqualsEquals => Self::Equals,
            TokenKind::NotEquals => Self::NotEquals,
            TokenKind::Equals => Self::Assign,
            TokenKind::Not => Self::Not,
            TokenKind::And => Self::And,
            TokenKind::Or => Self::Or,
            TokenKind::Percent => Self::Mod,
            TokenKind::PlusEquals => Self::AddAssign,
            TokenKind::MinusEquals => Self::SubtractAssign,
            TokenKind::AsteriskEquals => Self::MultiplyAssign,
            TokenKind::SlashEquals => Self::DivideAssign,
            _ => todo!()
        }
    }
}

impl Op {
    pub fn math(&self) -> bool {
        matches!(self, Self::Add | Self::Subtract | Self::Multiply | Self::Divide)
    }
}