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),
Pow(u8),
Not(u8),
UnaryMinus(u8),
Eq(u8),
Ne(u8),
Gt(u8),
Lt(u8),
Ge(u8),
Le(u8),
And(u8),
Or(u8),
NullCoalesce(u8),
In(u8),
NotIn(u8),
BitAnd(u8),
BitOr(u8),
BitXor(u8),
BitNot,
Shl(u8),
Shr(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::UnaryMinus(_) |
Operator::BitNot |
Operator::Function(_) |
Operator::LeftParenthesis)
}
pub fn get_max_args(&self) -> Option<usize> {
match *self {
Operator::Add(_) | Operator::Sub(_) | Operator::Mul(_) | Operator::Div(_) |
Operator::Eq(_) | Operator::Ne(_) | Operator::Gt(_) | Operator::Lt(_) |
Operator::Ge(_) | Operator::Le(_) | Operator::And(_) | Operator::Or(_) |
Operator::Rem(_) | Operator::Pow(_) | Operator::NullCoalesce(_) |
Operator::In(_) | Operator::NotIn(_) |
Operator::BitAnd(_) | Operator::BitOr(_) | Operator::BitXor(_) |
Operator::Shl(_) | Operator::Shr(_) => Some(2),
Operator::Not(_) | Operator::UnaryMinus(_) | Operator::BitNot => Some(1),
Operator::Function(_) => None,
_ => Some(0),
}
}
pub fn get_min_args(&self) -> Option<usize> {
match *self {
Operator::Add(_) | Operator::Sub(_) | Operator::Mul(_) | Operator::Div(_) |
Operator::Eq(_) | Operator::Ne(_) | Operator::Gt(_) | Operator::Lt(_) |
Operator::Ge(_) | Operator::Le(_) | Operator::And(_) | Operator::Or(_) |
Operator::Rem(_) | Operator::Pow(_) | Operator::NullCoalesce(_) |
Operator::In(_) | Operator::NotIn(_) |
Operator::BitAnd(_) | Operator::BitOr(_) | Operator::BitXor(_) |
Operator::Shl(_) | Operator::Shr(_) => Some(2),
Operator::Not(_) | Operator::UnaryMinus(_) | Operator::BitNot => Some(1),
Operator::Function(_) => None,
_ => Some(0),
}
}
pub fn get_priority(&self) -> u8 {
match *self {
Operator::Add(priority) |
Operator::Sub(priority) |
Operator::Div(priority) |
Operator::Mul(priority) |
Operator::Eq(priority) |
Operator::Ne(priority) |
Operator::Gt(priority) |
Operator::Lt(priority) |
Operator::Ge(priority) |
Operator::Le(priority) |
Operator::And(priority) |
Operator::Or(priority) |
Operator::Rem(priority) |
Operator::Pow(priority) |
Operator::UnaryMinus(priority) |
Operator::NullCoalesce(priority) |
Operator::In(priority) |
Operator::NotIn(priority) |
Operator::BitAnd(priority) |
Operator::BitOr(priority) |
Operator::BitXor(priority) |
Operator::Shl(priority) |
Operator::Shr(priority) => priority,
Operator::Value(_) |
Operator::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::Pow(_) |
Operator::Eq(_) |
Operator::Ne(_) |
Operator::Gt(_) |
Operator::Lt(_) |
Operator::And(_) |
Operator::Or(_) |
Operator::NullCoalesce(_) |
Operator::In(_) |
Operator::NotIn(_) |
Operator::BitAnd(_) |
Operator::BitOr(_) |
Operator::BitXor(_) |
Operator::BitNot |
Operator::Shl(_) |
Operator::Shr(_) |
Operator::Ge(_) |
Operator::Not(_) |
Operator::UnaryMinus(_) |
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 {
Operator::RightParenthesis => Operator::LeftParenthesis,
Operator::RightSquareBracket => Operator::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 {
Operator::Identifier(ref ident) => ident,
_ => panic!("not identifier"),
}
}
}
impl FromStr for Operator {
type Err = Error;
fn from_str(raw: &str) -> Result<Operator, Error> {
match raw {
"+" => Ok(Operator::Add(8)),
"-" => Ok(Operator::Sub(8)),
"*" => Ok(Operator::Mul(10)),
"**" => Ok(Operator::Pow(12)),
"/" => Ok(Operator::Div(10)),
"%" => Ok(Operator::Rem(10)),
"??" => Ok(Operator::NullCoalesce(1)),
"in" => Ok(Operator::In(6)),
"not in" => Ok(Operator::NotIn(6)),
"&" => Ok(Operator::BitAnd(7)),
"|" => Ok(Operator::BitOr(3)),
"^" => Ok(Operator::BitXor(5)),
"~" => Ok(Operator::BitNot),
"<<" => Ok(Operator::Shl(9)),
">>" => Ok(Operator::Shr(9)),
"(" => Ok(Operator::LeftParenthesis),
")" => Ok(Operator::RightParenthesis),
"[" => Ok(Operator::LeftSquareBracket(100)),
"]" => Ok(Operator::RightSquareBracket),
"." => Ok(Operator::Dot(100)),
"\"" => Ok(Operator::DoubleQuotes),
"'" => Ok(Operator::SingleQuote),
" " => Ok(Operator::WhiteSpace),
"," => Ok(Operator::Comma),
"!" => Ok(Operator::Not(99)),
"false" => Ok(Operator::Value(to_value(false))),
"true" => Ok(Operator::Value(to_value(true))),
"==" => Ok(Operator::Eq(6)),
"!=" => Ok(Operator::Ne(6)),
">" => Ok(Operator::Gt(6)),
"<" => Ok(Operator::Lt(6)),
">=" => Ok(Operator::Ge(6)),
"<=" => Ok(Operator::Le(6)),
"&&" => Ok(Operator::And(4)),
"||" => Ok(Operator::Or(2)),
_ => Ok(Operator::Identifier(raw.to_owned())),
}
}
}