use nom::{IResult, character::complete::multispace0};
use crate::parser::ast::Operator;
pub fn parse_operator(input: &str) -> IResult<&str, Operator> {
let (input, _) = multispace0(input)?;
let bytes = input.as_bytes();
let err = || nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Tag));
let (op, consumed) = match bytes.first().copied() {
Some(b'=') => {
if bytes.get(1).copied() == Some(b'=') {
if bytes.get(2).copied() == Some(b'=') {
return Err(err());
}
(Operator::Equal, 2)
} else {
(Operator::Equal, 1)
}
}
Some(b'!') => {
if bytes.get(1).copied() == Some(b'=') {
(Operator::NotEqual, 2)
} else {
(Operator::NotEqual, 1)
}
}
Some(b'<') => {
match bytes.get(1).copied() {
Some(b'=') => (Operator::LessEqual, 2),
Some(b'>') => (Operator::NotEqual, 2),
_ => (Operator::LessThan, 1),
}
}
Some(b'>') => {
if bytes.get(1).copied() == Some(b'=') {
(Operator::GreaterEqual, 2)
} else {
(Operator::GreaterThan, 1)
}
}
Some(b'&') => {
if bytes.get(1).copied() == Some(b'&') {
return Err(err());
}
(Operator::BitwiseAnd, 1)
}
Some(b'^') => {
if bytes.get(1).copied() == Some(b'^') {
return Err(err());
}
(Operator::BitwiseXor, 1)
}
Some(b'~') => {
if bytes.get(1).copied() == Some(b'~') {
return Err(err());
}
(Operator::BitwiseNot, 1)
}
Some(b'x') => {
if input
.get(1..)
.is_some_and(|s| s.starts_with(|c: char| c.is_alphanumeric() || c == '_'))
{
return Err(err());
}
(Operator::AnyValue, 1)
}
_ => return Err(err()),
};
let remaining = &input[consumed..];
let (remaining, _) = multispace0(remaining)?;
Ok((remaining, op))
}