use super::{
block::block,
comment::mightbespace,
common::{closechevron, expect_delimited, openchevron},
kind::kind,
operator,
value::single,
IResult,
};
use crate::{Cast, Expression, Future};
use nom::{bytes::complete::tag, character::complete::char, combinator::cut, sequence::delimited};
pub fn cast(i: &str) -> IResult<&str, Cast> {
let (i, k) = delimited(char('<'), cut(kind), char('>'))(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = cut(single)(i)?;
Ok((i, Cast(k, v)))
}
pub fn unary(i: &str) -> IResult<&str, Expression> {
let (i, o) = operator::unary(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = single(i)?;
Ok((
i,
Expression::Unary {
o,
v,
},
))
}
#[cfg(test)]
pub fn binary(i: &str) -> IResult<&str, Expression> {
use crate::Value;
use super::depth;
use super::value;
let (i, l) = single(i)?;
let (i, o) = operator::binary(i)?;
let _diving = depth::dive(i)?;
let (i, r) = value::value(i)?;
let v = match r {
Value::Expression(r) => r.augment(l, o),
_ => Expression::new(l, o, r),
};
Ok((i, v))
}
pub fn future(i: &str) -> IResult<&str, Future> {
let (i, _) = expect_delimited(openchevron, tag("future"), closechevron)(i)?;
cut(|i| {
let (i, _) = mightbespace(i)?;
let (i, v) = block(i)?;
Ok((i, Future(v)))
})(i)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Block, Kind, Number, Operator, Value};
#[test]
fn cast_int() {
let sql = "<int>1.2345";
let res = cast(sql);
let out = res.unwrap().1;
assert_eq!("<int> 1.2345f", format!("{}", out));
assert_eq!(out, Cast(Kind::Int, 1.2345.into()));
}
#[test]
fn cast_string() {
let sql = "<string>1.2345";
let res = cast(sql);
let out = res.unwrap().1;
assert_eq!("<string> 1.2345f", format!("{}", out));
assert_eq!(out, Cast(Kind::String, 1.2345.into()));
}
#[test]
fn expression_statement() {
let sql = "true AND false";
let res = binary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("true AND false", format!("{}", out));
}
#[test]
fn expression_left_opened() {
let sql = "3 * 3 * 3 = 27";
let res = binary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("3 * 3 * 3 = 27", format!("{}", out));
}
#[test]
fn expression_left_closed() {
let sql = "(3 * 3 * 3) = 27";
let res = binary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("(3 * 3 * 3) = 27", format!("{}", out));
}
#[test]
fn expression_right_opened() {
let sql = "27 = 3 * 3 * 3";
let res = binary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("27 = 3 * 3 * 3", format!("{}", out));
}
#[test]
fn expression_right_closed() {
let sql = "27 = (3 * 3 * 3)";
let res = binary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("27 = (3 * 3 * 3)", format!("{}", out));
}
#[test]
fn expression_both_opened() {
let sql = "3 * 3 * 3 = 3 * 3 * 3";
let res = binary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("3 * 3 * 3 = 3 * 3 * 3", format!("{}", out));
}
#[test]
fn expression_both_closed() {
let sql = "(3 * 3 * 3) = (3 * 3 * 3)";
let res = binary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("(3 * 3 * 3) = (3 * 3 * 3)", format!("{}", out));
}
#[test]
fn expression_unary() {
let sql = "-a";
let res = unary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!(sql, format!("{}", out));
}
#[test]
fn expression_with_unary() {
let sql = "-(5) + 5";
let res = binary(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!(sql, format!("{}", out));
}
#[test]
fn future_expression() {
let sql = "<future> { 5 + 10 }";
let res = future(sql);
let out = res.unwrap().1;
assert_eq!("<future> { 5 + 10 }", format!("{}", out));
assert_eq!(
out,
Future(Block::from(Value::from(Expression::Binary {
l: Value::Number(Number::Int(5)),
o: Operator::Add,
r: Value::Number(Number::Int(10))
})))
);
}
}