use crate::ast::visit::AstVisitor;
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime};
#[cfg(feature = "serde")]
use serde_crate::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum Value {
Null,
Bool(bool),
Int(i64),
Float(f64),
String(String),
Date(NaiveDate),
DateTime(DateTime<FixedOffset>),
NaiveDateTime(NaiveDateTime),
RelativeTime(RelativeTime),
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum RelativeTime {
Now,
Duration(Duration, TimeAnchor),
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum Duration {
Seconds(i16),
Minutes(i16),
Hours(i16),
Days(i16),
Weeks(i16),
Months(i16),
Years(i16),
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum TimeAnchor {
Ago,
}
pub type AbsolutePath = Vec<String>;
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub struct WildcardPath(pub Vec<PathElement>);
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum PathElement {
Field(String),
Wildcard,
RecursiveWildcard,
}
impl From<AbsolutePath> for WildcardPath {
fn from(vec: Vec<String>) -> WildcardPath {
WildcardPath(vec.into_iter().map(PathElement::Field).collect())
}
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub struct UnaryExpression {
pub op: UnaryOperator,
pub expr: Expression,
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum UnaryOperator {
Not,
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub struct BinaryExpression {
pub lhs: Expression,
pub op: BinaryOperator,
pub rhs: Expression,
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum BinaryOperator {
Eq,
Ne,
Lt,
Gt,
Lte,
Gte,
Match,
IMatch,
And,
Or,
}
impl BinaryOperator {
pub fn precedence(&self) -> u8 {
match self {
BinaryOperator::Or => 1,
BinaryOperator::And => 2,
BinaryOperator::Eq | BinaryOperator::Ne => 3,
BinaryOperator::Lt
| BinaryOperator::Gt
| BinaryOperator::Lte
| BinaryOperator::Gte
| BinaryOperator::Match
| BinaryOperator::IMatch => 4,
}
}
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum Expression {
AbsolutePath(AbsolutePath),
WildcardPath(WildcardPath),
Value(Value),
UnaryExpression(Box<UnaryExpression>),
BinaryExpression(Box<BinaryExpression>),
Error(ErrorToken),
}
impl Expression {
pub fn is_error(&self) -> bool {
let mut is_error_visitor = IsErrorVisitor::default();
is_error_visitor.visit_expression(self);
is_error_visitor.is_error
}
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(crate = "serde_crate", tag = "kind", content = "value")
)]
pub enum ErrorToken {
PathStart,
Identifier(String),
List(Vec<Expression>),
Unexpected,
}
#[derive(Default)]
struct IsErrorVisitor {
is_error: bool,
}
impl<'a> AstVisitor<'a> for IsErrorVisitor {
fn visit_expression(&mut self, expression: &'a Expression) {
if !self.is_error {
visit::walk_expression(self, expression)
}
}
fn visit_error_token(&mut self, _: &'a ErrorToken) {
self.is_error = true;
}
}
pub mod visit {
use super::*;
pub trait AstVisitor<'a> {
fn visit_expression(&mut self, expression: &'a Expression) {
walk_expression(self, expression)
}
fn visit_unary_expression(&mut self, unary_expression: &'a UnaryExpression) {
walk_unary_expression(self, unary_expression)
}
fn visit_unary_operator(&mut self, _op: &'a UnaryOperator) {}
fn visit_binary_expression(&mut self, binary_expression: &'a BinaryExpression) {
walk_binary_expression(self, binary_expression)
}
fn visit_binary_operator(&mut self, _op: &'a BinaryOperator) {}
fn visit_absolute_path(&mut self, _path: &'a AbsolutePath) {}
fn visit_wildcard_path(&mut self, _path: &'a WildcardPath) {}
fn visit_value(&mut self, _value: &'a Value) {}
fn visit_error_token(&mut self, error: &'a ErrorToken) {
walk_error_token(self, error)
}
fn should_continue(&self) -> bool {
true
}
}
pub fn walk_expression<'a, V: AstVisitor<'a> + ?Sized>(
visitor: &mut V,
expression: &'a Expression,
) -> () {
if !visitor.should_continue() {
return;
}
match *expression {
Expression::AbsolutePath(ref path) => visitor.visit_absolute_path(path),
Expression::WildcardPath(ref path) => visitor.visit_wildcard_path(path),
Expression::Value(ref value) => visitor.visit_value(value),
Expression::UnaryExpression(ref unary_expression) => {
visitor.visit_unary_expression(unary_expression)
}
Expression::BinaryExpression(ref binary_expression) => {
visitor.visit_binary_expression(binary_expression)
}
Expression::Error(ref error) => visitor.visit_error_token(error),
}
}
pub fn walk_unary_expression<'a, V: AstVisitor<'a> + ?Sized>(
visitor: &mut V,
unary_expression: &'a UnaryExpression,
) -> () {
if !visitor.should_continue() {
return;
}
visitor.visit_unary_operator(&unary_expression.op);
if !visitor.should_continue() {
return;
}
visitor.visit_expression(&unary_expression.expr);
}
pub fn walk_binary_expression<'a, V: AstVisitor<'a> + ?Sized>(
visitor: &mut V,
binary_expression: &'a BinaryExpression,
) -> () {
if !visitor.should_continue() {
return;
}
visitor.visit_expression(&binary_expression.lhs);
if !visitor.should_continue() {
return;
}
visitor.visit_binary_operator(&binary_expression.op);
if !visitor.should_continue() {
return;
}
visitor.visit_expression(&binary_expression.rhs);
}
pub fn walk_error_token<'a, V: AstVisitor<'a> + ?Sized>(
visitor: &mut V,
error: &'a ErrorToken,
) -> () {
match *error {
ErrorToken::List(ref expressions) => {
for expression in expressions {
if !visitor.should_continue() {
return;
}
visitor.visit_expression(&expression);
}
}
_ => {}
}
}
}