evalx 0.5.0

Expression evaluator
Documentation
use std::str::FromStr;
use serde_json::Value;
use crate::to_value;
use crate::error::Error;
use crate::node::Node;


#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operator {
    Add(u8),
    Mul(u8),
    Sub(u8),
    Div(u8),
    Rem(u8),
    Not(u8),
    Eq(u8),
    Ne(u8),
    Gt(u8),
    Lt(u8),
    Ge(u8),
    Le(u8),
    And(u8),
    Or(u8),
    Dot(u8),
    LeftParenthesis,
    RightParenthesis,
    LeftSquareBracket(u8),
    RightSquareBracket,
    DoubleQuotes,
    SingleQuote,
    WhiteSpace,
    Comma,
    Function(String),
    Identifier(String),
    Value(Value),
}

impl Operator {
    pub fn is_identifier(&self) -> bool {
        matches!(self, Operator::Identifier(_))
    }

    pub fn can_at_beginning(&self) -> bool {
        matches!(self, Operator::Not(_) | Operator::Function(_) | Operator::LeftParenthesis)
    }

    pub fn get_max_args(&self) -> Option<usize> {
        match *self {
            Self::Add(_) | Self::Sub(_) | Self::Mul(_) | Self::Div(_) |
            Self::Eq(_) | Self::Ne(_) | Self::Gt(_) | Self::Lt(_) |
            Self::Ge(_) | Self::Le(_) | Self::And(_) | Self::Or(_) |
            Self::Rem(_) => Some(2),
            Self::Not(_) => Some(1),
            Self::Function(_) => None,
            _ => Some(0),
        }
    }

    pub fn get_min_args(&self) -> Option<usize> {
        match *self {
            Self::Add(_) | Self::Sub(_) | Self::Mul(_) | Self::Div(_) |
            Self::Eq(_) | Self::Ne(_) | Self::Gt(_) | Self::Lt(_) |
            Self::Ge(_) | Self::Le(_) | Self::And(_) | Self::Or(_) |
            Self::Rem(_) => Some(2),
            Self::Not(_) => Some(1),
            Self::Function(_) => None,
            _ => Some(0),
        }
    }

    pub fn get_priority(&self) -> u8 {
        match *self {
            Self::Add(priority) |
            Self::Sub(priority) |
            Self::Div(priority) |
            Self::Mul(priority) |
            Self::Eq(priority) |
            Self::Ne(priority) |
            Self::Gt(priority) |
            Self::Lt(priority) |
            Self::Ge(priority) |
            Self::Le(priority) |
            Self::And(priority) |
            Self::Or(priority) |
            Self::Rem(priority) => priority,
            Self::Value(_) |
            Self::Identifier(_) => 0,
            _ => 99,
        }
    }

    pub fn is_left_parenthesis(&self) -> bool {
        *self == Operator::LeftParenthesis
    }

    pub fn is_not(&self) -> bool {
        matches!(self, Operator::Not(_))
    }

    pub fn is_left_square_bracket(&self) -> bool {
        matches!(self, Operator::LeftSquareBracket(_))
    }

    pub fn is_dot(&self) -> bool {
        matches!(self, Operator::Dot(_))
    }

    pub fn is_value_or_ident(&self) -> bool {
        matches!(self, Operator::Value(_) | Operator::Identifier(_))
    }

    pub fn can_have_child(&self) -> bool {
        matches!(self,
            Operator::Function(_)
            | Operator::Add(_)
            | Operator::Sub(_)
            | Operator::Div(_)
            | Operator::Mul(_)
            | Operator::Rem(_)
            | Operator::Eq(_)
            | Operator::Ne(_)
            | Operator::Gt(_)
            | Operator::Lt(_)
            | Operator::And(_)
            | Operator::Or(_)
            | Operator::Ge(_)
            | Operator::Not(_)
            | Operator::Dot(_)
            | Operator::LeftSquareBracket(_)
            | Operator::Le(_)
        )
    }

    pub fn is_left(&self) -> bool {
        matches!(self, Operator::LeftParenthesis | Operator::LeftSquareBracket(_))
    }

    pub fn get_left(&self) -> Operator {
        match *self {
            Self::RightParenthesis => Self::LeftParenthesis,
            Self::RightSquareBracket => Self::LeftSquareBracket(100),
            _ => panic!("not bracket"),
        }
    }

    pub fn to_node(&self) -> Node {
        Node::new(self.clone())
    }

    pub fn children_to_node(&self, children: Vec<Node>) -> Node {
        let mut node = self.to_node();
        node.children = children;
        node
    }

    pub fn get_identifier(&self) -> &str {
        match *self {
            Self::Identifier(ref ident) => ident,
            _ => panic!("not identifier"),
        }
    }
}

impl FromStr for Operator {
    type Err = Error;

    fn from_str(raw: &str) -> Result<Self, Error> {
        match raw {
            "+" => Ok(Self::Add(8)),
            "-" => Ok(Self::Sub(8)),
            "*" => Ok(Self::Mul(10)),
            "/" => Ok(Self::Div(10)),
            "%" => Ok(Self::Rem(10)),
            "(" => Ok(Self::LeftParenthesis),
            ")" => Ok(Self::RightParenthesis),
            "[" => Ok(Self::LeftSquareBracket(100)),
            "]" => Ok(Self::RightSquareBracket),
            "." => Ok(Self::Dot(100)),
            "\"" => Ok(Self::DoubleQuotes),
            "'" => Ok(Self::SingleQuote),
            " " => Ok(Self::WhiteSpace),
            "," => Ok(Self::Comma),
            "!" => Ok(Self::Not(99)),
            "false" => Ok(Self::Value(to_value(false))),
            "true" => Ok(Self::Value(to_value(true))),
            "==" => Ok(Self::Eq(6)),
            "!=" => Ok(Self::Ne(6)),
            ">" => Ok(Self::Gt(6)),
            "<" => Ok(Self::Lt(6)),
            ">=" => Ok(Self::Ge(6)),
            "<=" => Ok(Self::Le(6)),
            "&&" => Ok(Self::And(4)),
            "||" => Ok(Self::Or(2)),
            _ => Ok(Self::Identifier(raw.to_owned())),
        }
    }
}