eventql-parser 0.1.17

EventQL Lexer and Parser
Documentation
use crate::arena::Arena;
use crate::ast::{Limit, Order, Query};
use crate::prelude::{Type, Typed};
use crate::token::Operator;
use crate::{Attrs, ExprRef, Pos, Raw, SourceKind, Value};
use ordered_float::OrderedFloat;
use serde::Serialize;
use std::collections::BTreeMap;
use std::fmt::Debug;

mod analysis;
mod lexer;
mod parser;

#[derive(Debug, Serialize)]
pub struct ExprView {
    pub attrs: Attrs,
    pub value: ValueView,
}

impl ExprView {
    pub fn new(attrs: Attrs, value: ValueView) -> Self {
        Self { attrs, value }
    }
}

#[derive(Debug, Serialize)]
pub enum ValueView {
    Number(OrderedFloat<f64>),
    String(String),
    Bool(bool),
    Id(String),
    Array(Vec<ExprView>),
    Record(Vec<FieldView>),
    Access(AccessView),
    App(AppView),
    Binary(BinaryView),
    Unary(UnaryView),
    Group(Box<ExprView>),
}

#[derive(Debug, Serialize)]
pub struct FieldView {
    pub attrs: Attrs,
    pub name: String,
    pub value: ExprView,
}

#[derive(Debug, Serialize)]
pub struct AccessView {
    pub target: Box<ExprView>,
    pub field: String,
}

#[derive(Debug, Serialize)]
pub struct AppView {
    pub func: String,
    pub args: Vec<ExprView>,
}

#[derive(Debug, Serialize)]
pub struct BinaryView {
    pub lhs: Box<ExprView>,
    pub operator: Operator,
    pub rhs: Box<ExprView>,
}

#[derive(Debug, Serialize)]
pub struct UnaryView {
    pub operator: Operator,
    pub expr: Box<ExprView>,
}

#[derive(Debug, Serialize)]
pub struct QueryView<A> {
    pub attrs: Attrs,
    pub sources: Vec<SourceView<A>>,
    pub predicate: Option<ExprView>,
    pub group_by: Option<GroupByView>,
    pub order_by: Option<OrderByView>,
    pub limit: Option<Limit>,
    pub projection: ExprView,
    pub distinct: bool,
    pub meta: A,
}

#[derive(Debug, Serialize)]
pub struct SourceView<A> {
    pub binding: BindingView,
    pub kind: SourceKindView<A>,
}

#[derive(Debug, Serialize)]
pub struct BindingView {
    pub name: String,
    pub pos: Pos,
}

#[derive(Debug, Serialize)]
pub enum SourceKindView<A> {
    Name(String),
    Subject(String),
    Subquery(Box<QueryView<A>>),
}

#[derive(Debug, Serialize)]
pub struct GroupByView {
    pub expr: ExprView,
    pub predicate: Option<ExprView>,
}

#[derive(Debug, Serialize)]
pub struct OrderByView {
    pub expr: ExprView,
    pub order: Order,
}

impl ExprRef {
    pub fn view(self, arena: &Arena) -> ExprView {
        let node = arena.exprs.get(self);
        let value = match node.value {
            Value::Number(n) => ValueView::Number(n),
            Value::String(s) => ValueView::String(arena.strings.get(s).to_owned()),
            Value::Bool(b) => ValueView::Bool(b),
            Value::Id(id) => ValueView::Id(arena.strings.get(id).to_owned()),
            Value::Array(arr) => {
                let mut values = Vec::with_capacity(arena.exprs.vec(arr).len());
                for idx in arena.exprs.vec_idxes(arr) {
                    let expr = arena.exprs.vec_get(arr, idx);
                    values.push(expr.view(arena));
                }

                ValueView::Array(values)
            }
            Value::Record(fields) => {
                let mut values = Vec::with_capacity(arena.exprs.rec(fields).len());

                for idx in arena.exprs.rec_idxes(fields) {
                    let field = arena.exprs.rec_get(fields, idx);
                    values.push(FieldView {
                        attrs: field.attrs,
                        name: arena.strings.get(field.name).to_owned(),
                        value: field.expr.view(arena),
                    })
                }

                ValueView::Record(values)
            }
            Value::Access(access) => ValueView::Access(AccessView {
                target: Box::new(access.target.view(arena)),
                field: arena.strings.get(access.field).to_owned(),
            }),
            Value::App(app) => {
                let mut args = Vec::with_capacity(arena.exprs.vec(app.args).len());

                for idx in arena.exprs.vec_idxes(app.args) {
                    let expr = arena.exprs.vec_get(app.args, idx);
                    args.push(expr.view(arena));
                }

                ValueView::App(AppView {
                    func: arena.strings.get(app.func).to_owned(),
                    args,
                })
            }
            Value::Binary(binary) => ValueView::Binary(BinaryView {
                lhs: Box::new(binary.lhs.view(arena)),
                operator: binary.operator,
                rhs: Box::new(binary.rhs.view(arena)),
            }),
            Value::Unary(unary) => ValueView::Unary(UnaryView {
                operator: unary.operator,
                expr: Box::new(unary.expr.view(arena)),
            }),
            Value::Group(expr) => ValueView::Group(Box::new(expr.view(arena))),
        };

        ExprView::new(node.attrs, value)
    }
}

impl<A> Query<A> {
    pub fn view(self, arena: &Arena) -> QueryView<<A as ProjectMeta>::View>
    where
        A: ProjectMeta,
    {
        QueryView {
            attrs: self.attrs,
            sources: self
                .sources
                .into_iter()
                .map(|s| SourceView {
                    binding: BindingView {
                        name: arena.strings.get(s.binding.name).to_owned(),
                        pos: s.binding.pos,
                    },
                    kind: match s.kind {
                        SourceKind::Name(name) => {
                            SourceKindView::Name(arena.strings.get(name).to_owned())
                        }
                        SourceKind::Subject(subject) => {
                            SourceKindView::Subject(arena.strings.get(subject).to_owned())
                        }
                        SourceKind::Subquery(subquery) => {
                            SourceKindView::Subquery(Box::new(subquery.view(arena)))
                        }
                    },
                })
                .collect(),
            predicate: self.predicate.map(|e| e.view(arena)),
            group_by: self.group_by.map(|g| GroupByView {
                expr: g.expr.view(arena),
                predicate: g.predicate.map(|e| e.view(arena)),
            }),
            order_by: self.order_by.map(|o| OrderByView {
                expr: o.expr.view(arena),
                order: o.order,
            }),
            limit: self.limit,
            projection: self.projection.view(arena),
            meta: self.meta.project_meta(arena),
            distinct: self.distinct,
        }
    }
}

#[derive(Debug, Serialize)]
pub enum TypeView {
    Unspecified,
    Number,
    String,
    Bool,
    Subject,
    Date,
    Time,
    DateTime,
    Array(Box<TypeView>),
    Record(BTreeMap<String, TypeView>),
    App {
        args: Vec<TypeView>,
        result: Box<TypeView>,
        aggregate: bool,
    },
}

pub trait ProjectMeta {
    type View: Debug + Serialize;
    fn project_meta(&self, arena: &Arena) -> Self::View;
}

impl ProjectMeta for Raw {
    type View = Raw;

    fn project_meta(&self, _arena: &Arena) -> Self::View {
        *self
    }
}

#[derive(Debug, Serialize)]
pub struct MetaView {
    project: TypeView,
    aggregate: bool,
}

impl ProjectMeta for Typed {
    type View = MetaView;

    fn project_meta(&self, arena: &Arena) -> Self::View {
        MetaView {
            project: project_type(arena, self.project),
            aggregate: self.aggregate,
        }
    }
}

fn project_type(arena: &Arena, tpe: Type) -> TypeView {
    match tpe {
        Type::Unspecified => TypeView::Unspecified,
        Type::Number => TypeView::Number,
        Type::String => TypeView::String,
        Type::Bool => TypeView::Bool,
        Type::Subject => TypeView::Subject,
        Type::Date => TypeView::Date,
        Type::Time => TypeView::Time,
        Type::DateTime => TypeView::DateTime,

        Type::Array(arr) => {
            TypeView::Array(Box::new(project_type(arena, arena.types.get_type(arr))))
        }

        Type::Record(rec) => {
            let mut props = BTreeMap::new();

            for (key, val) in arena.types.get_record(rec) {
                props.insert(
                    arena.strings.get(*key).to_owned(),
                    project_type(arena, *val),
                );
            }

            TypeView::Record(props)
        }

        Type::App {
            args,
            result,
            aggregate,
        } => {
            let mut args_view = Vec::new();

            for val in arena.types.get_args(args.values) {
                args_view.push(project_type(arena, *val));
            }

            TypeView::App {
                args: args_view,
                result: Box::new(project_type(arena, arena.types.get_type(result))),
                aggregate,
            }
        }
    }
}